1、仿真任务 报工最新记录,映射到 应达成、实际达成状态

2、创建项目的时候,参数里要新加一个参考项目字段
This commit is contained in:
2026-01-29 18:39:58 +08:00
parent 8cc56bcabd
commit b75fa7a274
2 changed files with 229 additions and 50 deletions

View File

@@ -30,6 +30,16 @@ public class SimulationTaskExtra implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 属性名应达成进度shouldProgress
*/
public static final String PROPERTY_NAME_SHOULD_PROGRESS = "shouldProgress";
/**
* 属性名实际达成进度actualProgress
*/
public static final String PROPERTY_NAME_ACTUAL_PROGRESS = "actualProgress";
@TableId(value = "id", type = IdType.AUTO)
private Integer id;

View File

@@ -1,5 +1,7 @@
package com.sdm.project.service.impl;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
@@ -11,7 +13,10 @@ import com.sdm.common.feign.impl.system.SysUserFeignClientImpl;
import com.sdm.common.utils.PageUtils;
import com.sdm.common.utils.TimeCalculator;
import com.sdm.project.common.MemberTypeEnum;
import com.sdm.project.dao.SimulationTaskMapper;
import com.sdm.project.dao.SimulationWorkMapper;
import com.sdm.project.model.entity.SimulationTask;
import com.sdm.project.model.entity.SimulationTaskExtra;
import com.sdm.project.model.entity.SimulationWork;
import com.sdm.project.model.req.SpdmWorkListReq;
import com.sdm.project.model.req.SpdmWorkReq;
@@ -25,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -48,66 +54,229 @@ public class SimulationWorkServiceImpl extends ServiceImpl<SimulationWorkMapper,
@Autowired
private SysUserFeignClientImpl sysUserFeignClient;
@Override
public SdmResponse addWork(SpdmWorkReq req) {
SimulationWork simulationWork = new SimulationWork();
BeanUtils.copyProperties(req, simulationWork);
if (!this.save(simulationWork)) {
return SdmResponse.failed("新增报工失败");
}
return SdmResponse.success("新增报工成功");
@Autowired
private SimulationTaskExtraServiceImpl taskExtraService;
// 报工类型常量
public static final int WORK_TYPE_START = 0; // 开始报工
public static final int WORK_TYPE_FINISH = 1; // 完成报工
public static final int WORK_TYPE_EDIT = 2; // 编辑报工
/**
* 更新任务应达成进度(删除旧值+保存新值)
*/
private void updateTaskShouldProgress(String taskId, String shouldProgress) {
// 删除原有应完成进度配置
taskExtraService.lambdaUpdate()
.eq(SimulationTaskExtra::getTaskId, taskId)
.eq(SimulationTaskExtra::getPropertyName, SimulationTaskExtra.PROPERTY_NAME_SHOULD_PROGRESS)
.remove();
// 保存最新数据
SimulationTaskExtra taskExtra = new SimulationTaskExtra();
taskExtra.setTaskId(taskId);
taskExtra.setPropertyName(SimulationTaskExtra.PROPERTY_NAME_SHOULD_PROGRESS);
taskExtra.setPropertyValue(shouldProgress);
taskExtraService.save(taskExtra);
}
/**
* 新增报工
* @param req
* @return
*/
@Override
public SdmResponse updateWork(SpdmWorkReq req) {
Long id = req.getId();
if (ObjectUtils.isEmpty(id)) {
return SdmResponse.failed("id不能为空");
@Transactional(rollbackFor = Exception.class)
public SdmResponse addWork(SpdmWorkReq req) {
// 1. 参数非空校验
if (req == null) {
log.warn("新增报工失败,报工请求参数为空");
return SdmResponse.failed("报工请求参数不能为空");
}
Integer type = req.getType();
if (type != 0 && type != 1 && type != 2) {
return SdmResponse.failed("type必须为0或1或2");
if (req.getTaskId() == null || req.getTaskId().trim().isEmpty()) {
log.warn("新增报工失败任务ID为空请求参数{}", req);
return SdmResponse.failed("任务ID不能为空");
}
String curDateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
boolean updateFlag;
if (type == 0) {
updateFlag = this.lambdaUpdate().set(SimulationWork::getBeginTime, curDateStr)
.eq(SimulationWork::getId, id)
.update();
} else if (type == 1) {
updateFlag = this.lambdaUpdate().set(SimulationWork::getFinishTime, curDateStr)
.eq(SimulationWork::getId, id)
.update();
} else {
LambdaUpdateChainWrapper<SimulationWork> simulationWorkWrapper = this.lambdaUpdate();
// 校验填写的实际工时是否小于最大工时
String beginTime = req.getBeginTime();
String finishTime = req.getFinishTime();
Integer actualWorkHour = req.getActualWorkHour();
if (ObjectUtils.isNotEmpty(actualWorkHour)) {
if (StringUtils.isBlank(beginTime) || StringUtils.isBlank(finishTime)) {
return SdmResponse.failed("开始和完成时间都不为空时,才能填写实际工时");
}
Integer maxWorkHour = TimeCalculator.calculateWorkHours(beginTime, finishTime);
log.info("actualWorkHour{}maxWorkHour{}",actualWorkHour,maxWorkHour);
if (actualWorkHour > maxWorkHour) {
return SdmResponse.failed("您填写的工时:" + actualWorkHour + "已超出最大可填写的工时:" + maxWorkHour);
}
simulationWorkWrapper.set(SimulationWork::getActualWorkHour, actualWorkHour);
try {
// 2. 封装并保存报工数据
SimulationWork simulationWork = new SimulationWork();
BeanUtils.copyProperties(req, simulationWork);
if (!this.save(simulationWork)) {
log.warn("新增报工失败保存报工数据失败任务ID{}", req.getTaskId());
return SdmResponse.failed("新增报工失败");
}
updateFlag = simulationWorkWrapper
.set(ObjectUtils.isNotEmpty(req.getActualWorkHour()), SimulationWork::getActualWorkHour, req.getActualWorkHour())
.set(ObjectUtils.isNotEmpty(req.getPlanWorkHour()), SimulationWork::getPlanWorkHour, req.getPlanWorkHour())
.set(ObjectUtils.isNotEmpty(req.getDescription()), SimulationWork::getDescription, req.getDescription())
.set(ObjectUtils.isNotEmpty(req.getWorkName()), SimulationWork::getWorkName, req.getWorkName())
.set(ObjectUtils.isNotEmpty(req.getActualProgress()), SimulationWork::getActualProgress, req.getActualProgress())
.set(ObjectUtils.isNotEmpty(req.getShouldProgress()), SimulationWork::getShouldProgress, req.getShouldProgress())
.eq(SimulationWork::getId, req.getId())
.update();
// 3. 更新任务应达成进度
if (StringUtils.isNotBlank(req.getShouldProgress())) {
updateTaskShouldProgress(req.getTaskId(), req.getShouldProgress());
}
log.info("新增报工成功任务ID{}报工ID{},应达成进度:{}",
req.getTaskId(), simulationWork.getId(), req.getShouldProgress());
return SdmResponse.success("新增报工成功");
} catch (Exception e) {
log.error("新增报工异常任务ID{},请求参数:{}", req.getTaskId(), req, e);
return SdmResponse.failed("新增报工异常:" + e.getMessage());
}
}
/**
* 基础参数校验id非空 + type合法
*/
private boolean validateBaseParam(SpdmWorkReq req) {
return ObjectUtils.isNotEmpty(req.getId())
&& ObjectUtils.isNotEmpty(req.getType())
&& (req.getType().equals(WORK_TYPE_START)
|| req.getType().equals(WORK_TYPE_FINISH)
|| req.getType().equals(WORK_TYPE_EDIT));
}
/**
* 类型0更新开始时间
*/
private boolean updateStartWork(Long workId, String curDateStr) {
return this.lambdaUpdate()
.set(SimulationWork::getBeginTime, curDateStr)
.eq(SimulationWork::getId, workId)
.update();
}
/**
* 类型1更新完成时间
*/
private boolean updateFinishWork(Long workId, String curDateStr) {
return this.lambdaUpdate()
.set(SimulationWork::getFinishTime, curDateStr)
.eq(SimulationWork::getId, workId)
.update();
}
/**
* 类型2编辑报工
*/
private boolean updateEditWork(SpdmWorkReq req, Long workId) {
LambdaUpdateChainWrapper<SimulationWork> updateWrapper = this.lambdaUpdate();
Integer actualWorkHour = req.getActualWorkHour();
// 1. 实际工时校验与设置(有值时才校验)
if (ObjectUtils.isNotEmpty(actualWorkHour)) {
if (!validateActualWorkHour(req)) {
throw new IllegalArgumentException("开始和完成时间不能为空,且实际工时不能超过最大工时");
}
updateWrapper.set(SimulationWork::getActualWorkHour, actualWorkHour);
}
// 2. 动态设置非空字段
setIfPresent(updateWrapper, req.getPlanWorkHour(), SimulationWork::getPlanWorkHour);
setIfPresent(updateWrapper, req.getDescription(), SimulationWork::getDescription);
setIfPresent(updateWrapper, req.getWorkName(), SimulationWork::getWorkName);
setIfPresent(updateWrapper, req.getActualProgress(), SimulationWork::getActualProgress);
setIfPresent(updateWrapper, req.getShouldProgress(), SimulationWork::getShouldProgress);
// 3. 更新报工
boolean updateFlag = updateWrapper.eq(SimulationWork::getId, workId).update();
// 4. 同步更新任务实际进度(有值时才执行)
String actualProgress = req.getActualProgress();
if (StringUtils.isNotBlank(actualProgress) && updateFlag) {
syncTaskActualProgress(workId, actualProgress);
}
return updateFlag;
}
/**
* 实际工时校验:时间非空 + 实际工时≤最大工时
*/
private boolean validateActualWorkHour(SpdmWorkReq req) {
String beginTime = req.getBeginTime();
String finishTime = req.getFinishTime();
// 先校验时间非空
if (StringUtils.isAnyBlank(beginTime, finishTime)) {
return false;
}
// 计算最大工时并校验
Integer maxWorkHour = TimeCalculator.calculateWorkHours(beginTime, finishTime);
Integer actualWorkHour = req.getActualWorkHour();
log.info("实际工时:{},最大可填写工时:{}", actualWorkHour, maxWorkHour);
return actualWorkHour <= maxWorkHour;
}
/**
* 非空时设置更新字段
*/
private <T> void setIfPresent(LambdaUpdateChainWrapper<SimulationWork> wrapper,
T value,
SFunction<SimulationWork, T> column) {
if (ObjectUtils.isNotEmpty(value)) {
wrapper.set(column, value); // 此时类型完全匹配,无任何报错
}
}
/**
* 同步更新任务实际进度:删旧存新
*/
private void syncTaskActualProgress(Long workId, String actualProgress) {
// 查询报工主数据(未查询到直接返回,不抛异常)
SimulationWork simulationWork = this.getById(workId);
if (ObjectUtils.isEmpty(simulationWork) || ObjectUtils.isEmpty(simulationWork.getTaskId())) {
log.warn("报工记录不存在或任务ID为空报工ID{}", workId);
return;
}
// 报工关联的任务uuid
String taskId = simulationWork.getTaskId();
// 删除原有进度配置
taskExtraService.lambdaUpdate()
.eq(SimulationTaskExtra::getTaskId, taskId)
.eq(SimulationTaskExtra::getPropertyName, SimulationTaskExtra.PROPERTY_NAME_ACTUAL_PROGRESS)
.remove();
// 保存最新进度配置
SimulationTaskExtra taskExtra = new SimulationTaskExtra();
taskExtra.setTaskId(taskId);
taskExtra.setPropertyName(SimulationTaskExtra.PROPERTY_NAME_ACTUAL_PROGRESS);
taskExtra.setPropertyValue(actualProgress);
taskExtraService.save(taskExtra);
}
/**
* 更新报工信息
*/
@Transactional(rollbackFor = Exception.class)
public SdmResponse updateWork(SpdmWorkReq req) {
// 1. 基础参数校验
if (!validateBaseParam(req)) {
return SdmResponse.failed("id不能为空type必须为0/1/2");
}
Long workId = req.getId();
Integer type = req.getType();
String curDateStr = DateUtil.formatDateTime(DateUtil.date());
// 2. 根据不同类型执行更新逻辑
boolean updateFlag = false;
switch (type) {
case WORK_TYPE_START:
updateFlag = updateStartWork(workId, curDateStr);
break;
case WORK_TYPE_FINISH:
updateFlag = updateFinishWork(workId, curDateStr);
break;
case WORK_TYPE_EDIT:
updateFlag = updateEditWork(req, workId);
break;
default:
updateFlag = false;
}
// 3. 返回更新结果
return updateFlag ? SdmResponse.success() : SdmResponse.failed("更新报工信息失败");
}
private void setPMemberList(SpdmTaskVo task, List<SpdmTaskMemberVo> eachMemberList) {
// 由于我分发的、我执行的、我关注的、所有任务,都需要展示仿真负责人,故将负责人抽成方法调用
List<Long> pUserIdList = eachMemberList.stream().filter(member -> MemberTypeEnum.PRINCIPAL.getCode().equals(member.getType()) && StringUtils.equals(task.getUuid(), member.getTaskId())).map(SpdmTaskMemberVo::getUserId).distinct().toList();