Merge remote-tracking branch 'origin/dev' into dev

dev
wanghao 1 month ago
commit 7e46d9e0e3

@ -44,6 +44,7 @@
<module>ruoyi-common-nacos</module>
<module>ruoyi-common-bus</module>
<module>ruoyi-common-sse</module>
<module>hwbm-common-workflow</module>
</modules>
<artifactId>ruoyi-common</artifactId>

@ -132,8 +132,8 @@ public class ErpProjectChangeController extends BaseController {
@Log(title = "项目变更申请", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/submitAndFlowStart")
public R<ErpProjectChangeVo> submitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectChangeBo bo) {
return R.ok(erpProjectChangeService.projectChangeSubmitAndFlowStart(bo));
public R<Void> submitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectChangeBo bo) {
return toAjax(erpProjectChangeService.projectChangeSubmitAndFlowStart(bo));
}
}

@ -9,6 +9,7 @@ import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.util.List;
/**
* erp_project_change
@ -146,4 +147,22 @@ public class ErpProjectChange extends TenantEntity {
@TableLogic
private String delFlag;
/**
*
*/
@TableField(exist = false)
private List<ErpProjectChangeBudget> budgetList;
/**
*
*/
@TableField(exist = false)
private List<ErpProjectChangeProgress> progressList;
/**
*
*/
@TableField(exist = false)
private String createName;
}

@ -68,7 +68,7 @@ public class ErpProjectChangeBudget extends TenantEntity {
/**
*
*/
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -78,9 +78,9 @@ public class ErpProjectChangeProgress extends TenantEntity {
private BigDecimal completionDegree;
/**
*
*
*/
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -107,7 +107,7 @@ public class ErpProjectPlanStage extends TenantEntity {
/**
*
*/
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -67,7 +67,7 @@ public class ErpProjectChangeBudgetBo extends BaseEntity {
/**
*
*/
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -75,7 +75,7 @@ public class ErpProjectChangeProgressBo extends BaseEntity {
/**
*
*/
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -106,7 +106,7 @@ public class ErpProjectPlanStageBo extends BaseEntity {
/**
*
*/
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -82,7 +82,7 @@ public class ErpProjectChangeBudgetVo implements Serializable {
*
*/
@ExcelProperty(value = "排序顺序")
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -97,7 +97,7 @@ public class ErpProjectChangeProgressVo implements Serializable {
*
*/
@ExcelProperty(value = "排序顺序")
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -192,13 +192,16 @@ public class ErpProjectChangeVo implements Serializable {
/**
*
*/
@TableField(exist = false)
private List<ErpProjectChangeBudget> budgetList;
/**
*
*/
@TableField(exist = false)
private List<ErpProjectChangeProgress> progressList;
/**
*
*/
private String createName;
}

@ -132,7 +132,7 @@ public class ErpProjectPlanStageVo implements Serializable {
*
*/
@ExcelProperty(value = "排序号")
private Long sortOrder;
private Integer sortOrder;
/**
*

@ -109,5 +109,12 @@ public interface ErpProjectChangeProgressMapper extends BaseMapperPlus<ErpProjec
*/
Boolean existsErpProjectChangeProgress(@Param(Constants.WRAPPER) Wrapper<ErpProjectChangeProgress> queryWrapper);
/**
*
*
* @param projectChangeId ID
* @return
*/
List<ErpProjectChangeProgress> selectProgressWithStageInfo(@Param("projectChangeId") Long projectChangeId);
}

@ -11,30 +11,34 @@ import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.oa.erp.domain.*;
import org.dromara.oa.erp.domain.bo.ErpProjectChangeBo;
import org.dromara.oa.erp.domain.vo.ErpProjectChangeVo;
import org.dromara.oa.erp.mapper.*;
import org.dromara.oa.erp.service.IErpProjectChangeService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.event.ProcessEvent;
import org.springframework.context.event.EventListener;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;
import org.dromara.oa.erp.domain.bo.ErpProjectChangeBo;
import org.dromara.oa.erp.domain.vo.ErpProjectChangeVo;
import org.dromara.oa.erp.service.IErpProjectChangeService;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.common.satoken.utils.LoginHelper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.time.LocalDate;
import java.time.ZoneId;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import java.math.BigDecimal;
/**
* Service
@ -47,12 +51,18 @@ import java.util.stream.Collectors;
@Slf4j
public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
// 计划变更主子表
private final ErpProjectChangeMapper baseMapper;
private final ErpProjectChangeBudgetMapper changeBudgetMapper;
private final ErpProjectChangeProgressMapper changeProgressMapper;
private final ErpProjectInfoMapper projectInfoMapper;
//项目计划主子表
private final ErpProjectPlanMapper projectPlanMapper;
private final ErpProjectPlanStageMapper planStageMapper;
//项目预算主子表
private final ErpBudgetDetailMapper budgetDetailMapper;
private final ErpBudgetInfoMapper budgetInfoMapper;
//项目信息
private final ErpProjectInfoMapper projectInfoMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
@ -91,6 +101,24 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
return projectChangeVo;
}
/* @Override
public ErpProjectChangeVo queryById(Long projectChangeId){
ErpProjectChangeVo vo = baseMapper.selectCustomErpProjectChangeVoById(projectChangeId);
if (vo != null) {
// 查询预算变更明细
List<ErpProjectChangeBudget> budgetList = changeBudgetMapper.selectList(
Wrappers.<ErpProjectChangeBudget>lambdaQuery()
.eq(ErpProjectChangeBudget::getProjectChangeId, projectChangeId)
.orderByAsc(ErpProjectChangeBudget::getSortOrder)
);
vo.setBudgetList(budgetList);
// 查询进度变更明细(连表查询项目阶段信息)
List<ErpProjectChangeProgress> progressList = changeProgressMapper.selectProgressWithStageInfo(projectChangeId);
vo.setProgressList(progressList);
}
return vo;
}*/
/**
*
@ -102,7 +130,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
@Override
public TableDataInfo<ErpProjectChangeVo> queryPageList(ErpProjectChangeBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<ErpProjectChange> lqw = buildQueryWrapper(bo);
Page<ErpProjectChangeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
Page<ErpProjectChangeVo> result = baseMapper.selectCustomErpProjectChangeVoList(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@ -115,7 +143,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
@Override
public List<ErpProjectChangeVo> queryList(ErpProjectChangeBo bo) {
MPJLambdaWrapper<ErpProjectChange> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
return baseMapper.selectCustomErpProjectChangeVoList(lqw);
}
private MPJLambdaWrapper<ErpProjectChange> buildQueryWrapper(ErpProjectChangeBo bo) {
@ -148,37 +176,50 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
return lqw;
}
/**
*
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(ErpProjectChangeBo bo) {
// 权限校验:只有项目经理才能提交
validateProjectManager(bo.getProjectManagerId());
ErpProjectChange add = MapstructUtils.convert(bo, ErpProjectChange.class);
validEntityBeforeSave(add);
List<ErpProjectChangeBudget> budgetList = bo.getBudgetList();
List<ErpProjectChangeProgress> progressList = bo.getProgressList();
// 设置默认状态
if (StringUtils.isBlank(add.getProjectChangeStatus())) {
add.setProjectChangeStatus("1"); // 暂存
}
if (StringUtils.isBlank(add.getActiveFlag())) {
add.setActiveFlag("1");
}
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setProjectChangeId(add.getProjectChangeId());
// 保存预算变更明细
if (ObjectUtils.isNotEmpty(budgetList)) {
for (ErpProjectChangeBudget budget : budgetList) {
if (bo.getBudgetList() != null && !bo.getBudgetList().isEmpty()) {
for (int i = 0; i < bo.getBudgetList().size(); i++) {
ErpProjectChangeBudget budget = bo.getBudgetList().get(i);
budget.setProjectChangeId(add.getProjectChangeId());
budget.setSortOrder( (i + 1));
changeBudgetMapper.insert(budget);
}
}
// 保存进度变更明细
if (ObjectUtils.isNotEmpty(progressList)) {
for (ErpProjectChangeProgress progress : progressList) {
if (bo.getProgressList() != null && !bo.getProgressList().isEmpty()) {
for (int i = 0; i < bo.getProgressList().size(); i++) {
ErpProjectChangeProgress progress = bo.getProgressList().get(i);
progress.setProjectChangeId(add.getProjectChangeId());
progress.setSortOrder( (i + 1));
changeProgressMapper.insert(progress);
}
}
@ -190,93 +231,62 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
*
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(ErpProjectChangeBo bo) {
// 权限校验:只有项目经理才能修改
validateProjectManager(bo.getProjectManagerId());
// 状态校验:只有草稿状态才能修改
ErpProjectChange existing = baseMapper.selectById(bo.getProjectChangeId());
if (existing == null) {
throw new ServiceException("项目变更申请不存在");
}
if (!"1".equals(existing.getProjectChangeStatus())) {
throw new ServiceException("只有草稿状态的变更申请才能修改");
}
ErpProjectChange update = MapstructUtils.convert(bo, ErpProjectChange.class);
validEntityBeforeSave(update);
List<ErpProjectChangeBudget> budgetList = bo.getBudgetList();
List<ErpProjectChangeProgress> progressList = bo.getProgressList();
boolean flag = baseMapper.updateById(update) > 0;
if (flag) {
// 删除原有的预算变更明细
changeBudgetMapper.delete(Wrappers.<ErpProjectChangeBudget>lambdaQuery()
.eq(ErpProjectChangeBudget::getProjectChangeId, bo.getProjectChangeId()));
// 处理预算变更明细
if (budgetList != null && !budgetList.isEmpty()) {
for (ErpProjectChangeBudget budget : budgetList) {
budget.setProjectChangeId(bo.getProjectChangeId());
changeBudgetMapper.insertOrUpdate(budget);
// 删除原有的进度变更明细
changeProgressMapper.delete(Wrappers.<ErpProjectChangeProgress>lambdaQuery()
.eq(ErpProjectChangeProgress::getProjectChangeId, bo.getProjectChangeId()));
// 重新保存预算变更明细
if (bo.getBudgetList() != null && !bo.getBudgetList().isEmpty()) {
for (int i = 0; i < bo.getBudgetList().size(); i++) {
ErpProjectChangeBudget budget = bo.getBudgetList().get(i);
budget.setChangeBudgetId(null); // 清空主键,让数据库重新生成
budget.setProjectChangeId(bo.getProjectChangeId());
budget.setSortOrder( (i + 1));
changeBudgetMapper.insert(budget);
}
}
// 删除前端未提交的旧数据
Set<Long> existingBudgetIds = budgetList.stream()
.map(ErpProjectChangeBudget::getChangeBudgetId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
MPJLambdaWrapper<ErpProjectChangeBudget> budgetLqw = JoinWrappers.lambda(ErpProjectChangeBudget.class);
budgetLqw.eq(ErpProjectChangeBudget::getProjectChangeId, bo.getProjectChangeId());
List<ErpProjectChangeBudget> oldBudgetList = changeBudgetMapper.selectList(budgetLqw);
oldBudgetList.stream()
.filter(budget -> !existingBudgetIds.contains(budget.getChangeBudgetId()))
.forEach(budget -> changeBudgetMapper.deleteById(budget.getChangeBudgetId()));
}
// 处理进度变更明细
if (progressList != null && !progressList.isEmpty()) {
for (ErpProjectChangeProgress progress : progressList) {
progress.setProjectChangeId(bo.getProjectChangeId());
changeProgressMapper.insertOrUpdate(progress);
// 重新保存进度变更明细
if (bo.getProgressList() != null && !bo.getProgressList().isEmpty()) {
for (int i = 0; i < bo.getProgressList().size(); i++) {
ErpProjectChangeProgress progress = bo.getProgressList().get(i);
progress.setChangeProgressId(null); // 清空主键,让数据库重新生成
progress.setProjectChangeId(bo.getProjectChangeId());
progress.setSortOrder( (i + 1));
changeProgressMapper.insert(progress);
}
}
// 删除前端未提交的旧数据
Set<Long> existingProgressIds = progressList.stream()
.map(ErpProjectChangeProgress::getChangeProgressId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
MPJLambdaWrapper<ErpProjectChangeProgress> progressLqw = JoinWrappers.lambda(ErpProjectChangeProgress.class);
progressLqw.eq(ErpProjectChangeProgress::getProjectChangeId, bo.getProjectChangeId());
List<ErpProjectChangeProgress> oldProgressList = changeProgressMapper.selectList(progressLqw);
oldProgressList.stream()
.filter(progress -> !existingProgressIds.contains(progress.getChangeProgressId()))
.forEach(progress -> changeProgressMapper.deleteById(progress.getChangeProgressId()));
}
return baseMapper.updateById(update) > 0;
return flag;
}
/**
*
*/
private void validEntityBeforeSave(ErpProjectChange entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
// 先删除子表
changeBudgetMapper.delete(Wrappers.<ErpProjectChangeBudget>lambdaQuery().in(ErpProjectChangeBudget::getProjectChangeId, ids));
changeProgressMapper.delete(Wrappers.<ErpProjectChangeProgress>lambdaQuery().in(ErpProjectChangeProgress::getProjectChangeId, ids));
// 删除主表
baseMapper.deleteByIds(ids);
//删除工作流
List<Long> businessIds = ids.stream().toList();
return remoteWorkflowService.deleteInstance(businessIds);
}
/**
* ID
*
* @param projectId ID
* @return
* ID
*/
@Override
public ErpProjectChangeVo prepareByProjectWithInfo(Long projectId) {
@ -284,124 +294,268 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
throw new ServiceException("项目ID不能为空");
}
// 若存在审批中的项目变更则禁止再次发起
long approvingCount = baseMapper.selectCount(Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.eq(ErpProjectChange::getDelFlag, "0")
.eq(ErpProjectChange::getProjectChangeStatus, OAStatusEnum.APPROVING.getStatus()));// "2"审批中,"3"可用
if (approvingCount > 0) {
throw new ServiceException("该项目存在未完成的变更申请,请等待审批完成后再发起新的变更");
// 检查是否有未完成的变更状态1或2
List<ErpProjectChange> existingChanges = baseMapper.selectList(
Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.in(ErpProjectChange::getProjectChangeStatus, Arrays.asList("1", "2"))
.orderByDesc(ErpProjectChange::getCreateTime)
);
if (!existingChanges.isEmpty()) {
// 如果有暂存记录,返回该记录供继续编辑
ErpProjectChange draftChange = existingChanges.stream()
.filter(change -> "1".equals(change.getProjectChangeStatus()))
.findFirst().orElse(null);
if (draftChange != null) {
return queryById(draftChange.getProjectChangeId());
}
throw new ServiceException("该项目存在未完成的变更申请,请先完成或取消后再发起新的变更");
}
// 如果已有暂存记录,返回该记录供继续编辑
ErpProjectChange draftChange = baseMapper.selectOne(Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.eq(ErpProjectChange::getDelFlag, "0")
.eq(ErpProjectChange::getProjectChangeStatus, "1")
.orderByDesc(ErpProjectChange::getCreateTime)
.last("limit 1"));
if (draftChange != null) {
return queryById(draftChange.getProjectChangeId());
}
// 通过自定义Mapper方法查询项目信息和用户名称连表查询sys_user
// 查询项目信息
ErpProjectChangeVo vo = baseMapper.prepareByProjectId(projectId);
if (vo == null) {
throw new ServiceException("项目不存在");
throw new ServiceException("项目信息不存在");
}
// 查询项目计划信息
MPJLambdaWrapper<ErpProjectPlan> planLqw = JoinWrappers.lambda(ErpProjectPlan.class)
.eq(ErpProjectPlan::getProjectId, projectId)
.eq(ErpProjectPlan::getDelFlag, "0");
ErpProjectPlan projectPlan = projectPlanMapper.selectOne(planLqw);
// 计算变更次数(已完成的变更数量)
Long changeCount = baseMapper.selectCount(
Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.eq(ErpProjectChange::getProjectChangeStatus, "3")
);
vo.setChangeNumber(changeCount.intValue() + 1);
if (projectPlan != null) {
// 查询项目计划阶段
MPJLambdaWrapper<ErpProjectPlanStage> stageLqw = JoinWrappers.lambda(ErpProjectPlanStage.class)
.eq(ErpProjectPlanStage::getProjectPlanId, projectPlan.getProjectPlanId())
.eq(ErpProjectPlanStage::getDelFlag, "0")
.orderByAsc(ErpProjectPlanStage::getSortOrder);
List<ErpProjectPlanStage> planStageList = planStageMapper.selectList(stageLqw);
// 如果存在已完成的变更,将最新一次的变更数据作为默认值
if (changeCount > 0) {
ErpProjectChange lastChange = baseMapper.selectOne(
Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.eq(ErpProjectChange::getProjectChangeStatus, "3")
.orderByDesc(ErpProjectChange::getCreateTime)
.last("limit 1")
);
// 将项目阶段转换为进度变更明细
if (ObjectUtils.isNotEmpty(planStageList)) {
List<ErpProjectChangeProgress> progressList = planStageList.stream().map(stage -> {
ErpProjectChangeProgress progress = new ErpProjectChangeProgress();
progress.setPlanStageId(stage.getPlanStageId()); // 绑定项目计划阶段ID
progress.setProjectPhases(stage.getProjectPhases()); // 项目阶段字典值(禁用显示)
progress.setMilestoneName(""); // 里程碑名称由用户手动输入
progress.setOriginalStart(stage.getPlanStartTime()); // 原计划开始时间
progress.setOriginalEnd(stage.getPlanEndTime()); // 原计划结束时间
progress.setChangedStart(stage.getPlanStartTime()); // 初始值设为原计划时间
progress.setChangedEnd(stage.getPlanEndTime()); // 初始值设为原计划时间
progress.setSortOrder(stage.getSortOrder()); // 排序顺序
return progress;
}).collect(Collectors.toList());
if (lastChange != null) {
// 复制上一次变更的项目当前情况说明等信息作为参考
vo.setCurrentStatus(lastChange.getCurrentStatus());
vo.setChangeReason(""); // 变更原因需要重新填写
vo.setFollowUpWork(""); // 后续工作需要重新填写
// 查询上一次变更的预算变更明细作为参考
List<ErpProjectChangeBudget> lastBudgetList = changeBudgetMapper.selectList(
Wrappers.<ErpProjectChangeBudget>lambdaQuery()
.eq(ErpProjectChangeBudget::getProjectChangeId, lastChange.getProjectChangeId())
.orderByAsc(ErpProjectChangeBudget::getSortOrder)
);
List<ErpProjectChangeBudget> budgetList = new ArrayList<>();
// 将上一次的变更后预算作为本次的变更前预算
for (ErpProjectChangeBudget lastBudget : lastBudgetList) {
ErpProjectChangeBudget newBudget = new ErpProjectChangeBudget();
newBudget.setBudgetDetailId(lastBudget.getBudgetDetailId());
newBudget.setSubjectName(lastBudget.getSubjectName());
newBudget.setBudgetBefore(lastBudget.getBudgetAfter()); // 上次变更后 = 本次变更前
newBudget.setBudgetAfter(lastBudget.getBudgetAfter()); // 默认值
newBudget.setAmountUsed(lastBudget.getAmountUsed());
newBudget.setSortOrder(lastBudget.getSortOrder());
budgetList.add(newBudget);
}
vo.setBudgetList(budgetList);
// 查询上一次变更的进度变更明细作为参考
List<ErpProjectChangeProgress> lastProgressList = changeProgressMapper.selectList(
Wrappers.<ErpProjectChangeProgress>lambdaQuery()
.eq(ErpProjectChangeProgress::getProjectChangeId, lastChange.getProjectChangeId())
.orderByAsc(ErpProjectChangeProgress::getSortOrder)
);
List<ErpProjectChangeProgress> progressList = new ArrayList<>();
// 将上一次的变更后时间作为本次的原计划时间
for (ErpProjectChangeProgress lastProgress : lastProgressList) {
ErpProjectChangeProgress newProgress = new ErpProjectChangeProgress();
newProgress.setPlanStageId(lastProgress.getPlanStageId());
newProgress.setProjectPhases(lastProgress.getProjectPhases());
newProgress.setMilestoneName(lastProgress.getMilestoneName());
newProgress.setOriginalStart(lastProgress.getChangedStart()); // 上次变更后 = 本次原计划
newProgress.setOriginalEnd(lastProgress.getChangedEnd()); // 上次变更后 = 本次原计划
newProgress.setChangedStart(lastProgress.getChangedStart()); // 默认值
newProgress.setChangedEnd(lastProgress.getChangedEnd()); // 默认值
newProgress.setCompletionDegree(lastProgress.getCompletionDegree());
newProgress.setSortOrder(lastProgress.getSortOrder());
progressList.add(newProgress);
}
vo.setProgressList(progressList);
}
}
// 初始化空的预算变更列表(由用户手动添加)
vo.setBudgetList(new ArrayList<>());
// 设置申请变更日期为当前日期
vo.setApplyChangeDate(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()));
// 计算变更次数:查询该项目已完成的变更次数
MPJLambdaWrapper<ErpProjectChange> changeCountLqw = JoinWrappers.lambda(ErpProjectChange.class)
.eq(ErpProjectChange::getProjectId, projectId)
.eq(ErpProjectChange::getDelFlag, "0")
.eq(ErpProjectChange::getProjectChangeStatus, OAStatusEnum.COMPLETED.getStatus());
int changeCount = Math.toIntExact(baseMapper.selectCount(changeCountLqw));
// 如果没有历史变更记录,从项目计划阶段和预算明细中初始化数据
if (changeCount == 0) {
// 查询项目计划阶段,转换为进度变更明细
List<ErpProjectPlanStage> planStages = planStageMapper.selectList(
Wrappers.<ErpProjectPlanStage>lambdaQuery()
.eq(ErpProjectPlanStage::getProjectId, projectId)
.orderByAsc(ErpProjectPlanStage::getSortOrder)
);
vo.setChangeNumber(changeCount + 1); // 当前变更次数 = 已有次数 + 1
List<ErpProjectChangeProgress> progressList = new ArrayList<>();
for (ErpProjectPlanStage stage : planStages) {
ErpProjectChangeProgress progress = new ErpProjectChangeProgress();
progress.setPlanStageId(stage.getPlanStageId());
progress.setProjectPhases(stage.getProjectPhases());
progress.setMilestoneName(""); // 里程碑名称由用户手动输入
progress.setOriginalStart(stage.getPlanStartTime());
progress.setOriginalEnd(stage.getPlanEndTime());
progress.setChangedStart(stage.getPlanStartTime()); // 默认值
progress.setChangedEnd(stage.getPlanEndTime()); // 默认值
progress.setCompletionDegree(BigDecimal.ZERO); // 默认完成程度
progress.setSortOrder(stage.getSortOrder());
progressList.add(progress);
}
vo.setProgressList(progressList);
// 设置默认值
// 查询项目预算明细,转换为预算变更明细
// 首先查询项目的有效预算
ErpBudgetInfo budgetInfo = budgetInfoMapper.selectOne(
Wrappers.<ErpBudgetInfo>lambdaQuery()
.eq(ErpBudgetInfo::getProjectId, projectId)
.eq(ErpBudgetInfo::getBudgetStatus, "3") // 可用状态
.orderByDesc(ErpBudgetInfo::getBudgetVersion)
.last("limit 1")
);
List<ErpProjectChangeBudget> budgetList = new ArrayList<>();
if (budgetInfo != null) {
// 查询预算明细
List<ErpBudgetDetail> budgetDetails = budgetDetailMapper.selectList(
Wrappers.<ErpBudgetDetail>lambdaQuery()
.eq(ErpBudgetDetail::getBudgetId, budgetInfo.getBudgetId())
.orderByAsc(ErpBudgetDetail::getSortOrder)
);
for (ErpBudgetDetail detail : budgetDetails) {
ErpProjectChangeBudget budget = new ErpProjectChangeBudget();
budget.setBudgetDetailId(detail.getBudgetDetailId());
budget.setSubjectName(detail.getBudgetItem());
//xins的预算表数据库是decimal实体类ErpBudgetDetail却是Long所以这里需要转换一下
BigDecimal budgetCost = BigDecimal.valueOf(detail.getBudgetCost());
budget.setBudgetBefore(budgetCost);
budget.setBudgetAfter(budgetCost); // 默认值
budget.setAmountUsed(BigDecimal.ZERO); // 默认已使用金额为0
budget.setSortOrder(Math.toIntExact(detail.getSortOrder()));
budgetList.add(budget);
}
}
vo.setBudgetList(budgetList);
}
// 设置默认状态
vo.setProjectChangeStatus("1"); // 暂存
vo.setActiveFlag("1");
vo.setProjectChangeStatus("1"); // 1-暂存
return vo;
}
/**
*
*
* @param bo
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public ErpProjectChangeVo projectChangeSubmitAndFlowStart(ErpProjectChangeBo bo) {
ErpProjectChange add = MapstructUtils.convert(bo, ErpProjectChange.class);
validEntityBeforeSave(add) ;
public Boolean projectChangeSubmitAndFlowStart(ErpProjectChangeBo bo) {
// 权限校验:只有项目经理才能提交
validateProjectManager(bo.getProjectManagerId());
// 保存或更新项目变更数据
boolean saveFlag;
// 检查是否有未完成的变更
List<ErpProjectChange> existingChanges = baseMapper.selectList(
Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, bo.getProjectId())
.in(ErpProjectChange::getProjectChangeStatus, Arrays.asList("1", "2"))
.ne(bo.getProjectChangeId() != null, ErpProjectChange::getProjectChangeId, bo.getProjectChangeId())
);
if (!existingChanges.isEmpty()) {
throw new ServiceException("该项目存在其他未完成的变更申请,请先完成或取消后再提交");
}
// 设置状态为审批中
// bo.setProjectChangeStatus("2");
// bo.setFlowStatus("running");
Boolean result;
if (bo.getProjectChangeId() == null) {
saveFlag = insertByBo(bo);
result = insertByBo(bo);
} else {
saveFlag = updateByBo(bo);
result = updateByBo(bo);
}
if (!saveFlag) {
throw new ServiceException("保存项目变更失败");
if (result) {
// 发起审批流程
// 后端发起需要忽略权限
bo.getVariables().put("ignore", true);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(bo.getProjectChangeId().toString());
startProcess.setFlowCode(bo.getFlowCode());
startProcess.setVariables(bo.getVariables());
startProcess.setBizExt(bo.getBizExt());
bo.getBizExt().setBusinessId(startProcess.getBusinessId());
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
if (!flagOne) {
throw new ServiceException("发起审批流程失败");
}
}
// 后端发起需要忽略权限
bo.getVariables().put("ignore", true);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(bo.getProjectChangeId().toString());
startProcess.setFlowCode(bo.getFlowCode());
startProcess.setVariables(bo.getVariables());
startProcess.setBizExt(bo.getBizExt());
bo.getBizExt().setBusinessId(startProcess.getBusinessId());
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
if (!flagOne) {
throw new ServiceException("流程发起异常");
return result;
}
/**
*
*/
private void validateProjectManager(Long projectManagerId) {
// 超级管理员跳过校验
if (LoginHelper.isSuperAdmin()) {
return;
}
return MapstructUtils.convert(add, ErpProjectChangeVo.class);
Long currentUserId = LoginHelper.getUserId();
if (!Objects.equals(currentUserId, projectManagerId)) {
throw new ServiceException("只有项目经理才能提交项目计划变更");
}
}
/**
*
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
// 校验是否可以删除(只能删除暂存状态的记录)
List<ErpProjectChange> changes = baseMapper.selectBatchIds(ids);
for (ErpProjectChange change : changes) {
if (!"1".equals(change.getProjectChangeStatus())) {
throw new ServiceException("只能删除暂存状态的变更申请");
}
}
}
// 删除主表和子表数据
for (Long id : ids) {
changeBudgetMapper.delete(Wrappers.<ErpProjectChangeBudget>lambdaQuery()
.eq(ErpProjectChangeBudget::getProjectChangeId, id));
changeProgressMapper.delete(Wrappers.<ErpProjectChangeProgress>lambdaQuery()
.eq(ErpProjectChangeProgress::getProjectChangeId, id));
}
return baseMapper.deleteBatchIds(ids) > 0;
}
private void validEntityBeforeSave(ErpProjectChange entity){
//TODO 做一些数据校验,如唯一约束
}
/**
@ -426,20 +580,4 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
});
}
/**
*
*
* @param projectManagerId ID
*/
private void validateProjectManager(Long projectManagerId) {
// 超级管理员跳过校验
if (LoginHelper.isSuperAdmin()) {
return;
}
Long currentUserId = LoginHelper.getUserId();
if (!currentUserId.equals(projectManagerId)) {
throw new ServiceException("只有项目经理才能提交项目变更申请");
}
}
}

@ -283,12 +283,12 @@ public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
List<Long> businessIds = ids.stream().toList();
// 先删除子表
planStageMapper.delete(Wrappers.<ErpProjectPlanStage>lambdaQuery()
.in(ErpProjectPlanStage::getProjectPlanId, ids));
baseMapper.deleteByIds(ids);
//删除工作流
List<Long> businessIds = ids.stream().toList();
return remoteWorkflowService.deleteInstance(businessIds);
}

@ -7,35 +7,39 @@
</resultMap>
<select id="selectCustomErpProjectChangeVoList" resultMap="ErpProjectChangeResult">
select t.project_change_id, t.tenant_id, t.project_id, t.project_code, t.project_name, t.project_category,
t.change_type, t.change_number, t.project_manager_id, t.dept_head_id, t.responsible_vp_id,
t.apply_change_date, t.contract_amount, t.contract_net_amount, t.current_status, t.change_reason,
t.follow_up_work, t.project_change_status, t.flow_status, t.remark, t.active_flag, t.del_flag,
select t.project_change_id, t.tenant_id, t.project_id, t.project_code, t.project_name, t.project_category,
t.change_type, t.change_number, t.project_manager_id, t.dept_head_id, t.responsible_vp_id,
t.apply_change_date, t.contract_amount, t.contract_net_amount, t.current_status, t.change_reason,
t.follow_up_work, t.project_change_status, t.flow_status, t.remark, t.active_flag, t.del_flag,
t.create_dept, t.create_by, t.create_time, t.update_by, t.update_time,
u1.nick_name as project_manager_name,
u2.nick_name as dept_head_name,
u3.nick_name as responsible_vp_name
u3.nick_name as responsible_vp_name,
u4.nick_name as createName
from erp_project_change t
left join sys_user u1 on t.project_manager_id = u1.user_id
left join sys_user u2 on t.dept_head_id = u2.user_id
left join sys_user u3 on t.responsible_vp_id = u3.user_id
left join sys_user u4 on t.create_by = u4.user_id
${ew.getCustomSqlSegment}
</select>
<!-- 根据ID查询详情 -->
<select id="selectCustomErpProjectChangeVoById" resultMap="ErpProjectChangeResult">
select t.project_change_id, t.tenant_id, t.project_id, t.project_code, t.project_name, t.project_category,
t.change_type, t.change_number, t.project_manager_id, t.dept_head_id, t.responsible_vp_id,
t.apply_change_date, t.contract_amount, t.contract_net_amount, t.current_status, t.change_reason,
t.follow_up_work, t.project_change_status, t.flow_status, t.remark, t.active_flag, t.del_flag,
select t.project_change_id, t.tenant_id, t.project_id, t.project_code, t.project_name, t.project_category,
t.change_type, t.change_number, t.project_manager_id, t.dept_head_id, t.responsible_vp_id,
t.apply_change_date, t.contract_amount, t.contract_net_amount, t.current_status, t.change_reason,
t.follow_up_work, t.project_change_status, t.flow_status, t.remark, t.active_flag, t.del_flag,
t.create_dept, t.create_by, t.create_time, t.update_by, t.update_time,
u1.nick_name as project_manager_name,
u2.nick_name as dept_head_name,
u3.nick_name as responsible_vp_name
u3.nick_name as responsible_vp_name,
u4.nick_name as createName
from erp_project_change t
left join sys_user u1 on t.project_manager_id = u1.user_id
left join sys_user u2 on t.dept_head_id = u2.user_id
left join sys_user u3 on t.responsible_vp_id = u3.user_id
left join sys_user u4 on t.create_by = u4.user_id
where t.project_change_id = #{projectChangeId}
</select>
@ -309,7 +313,7 @@
<!-- 根据项目ID准备项目变更信息带出项目信息和用户名称 -->
<select id="prepareByProjectId" resultMap="ErpProjectChangeResult">
select
select
pi.project_id,
pi.project_code,
pi.project_name,
@ -330,4 +334,5 @@
</select>
</mapper>

@ -195,5 +195,16 @@
${ew.getCustomSqlSegment}
</select>
<!-- 查询进度变更明细(连表查询项目阶段信息) -->
<select id="selectProgressWithStageInfo" resultType="org.dromara.oa.erp.domain.ErpProjectChangeProgress">
select
t.*,
s.project_phases
from erp_project_change_progress t
left join erp_project_plan_stage s on t.plan_stage_id = s.plan_stage_id
where t.project_change_id = #{projectChangeId}
and t.del_flag = '0'
order by t.sort_order
</select>
</mapper>

Loading…
Cancel
Save