diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 6622dd2e..91d833b9 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -44,6 +44,7 @@
ruoyi-common-nacos
ruoyi-common-bus
ruoyi-common-sse
+ hwbm-common-workflow
ruoyi-common
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpProjectChangeController.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpProjectChangeController.java
index 60a74ee8..bc271e1e 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpProjectChangeController.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpProjectChangeController.java
@@ -132,8 +132,8 @@ public class ErpProjectChangeController extends BaseController {
@Log(title = "项目变更申请", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/submitAndFlowStart")
- public R submitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectChangeBo bo) {
- return R.ok(erpProjectChangeService.projectChangeSubmitAndFlowStart(bo));
+ public R submitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectChangeBo bo) {
+ return toAjax(erpProjectChangeService.projectChangeSubmitAndFlowStart(bo));
}
}
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChange.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChange.java
index 7f2d833f..74a25485 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChange.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChange.java
@@ -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 budgetList;
+
+ /**
+ * 进度变更明细列表
+ */
+ @TableField(exist = false)
+ private List progressList;
+
+ /**
+ * 创建人名称
+ */
+ @TableField(exist = false)
+ private String createName;
+
}
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeBudget.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeBudget.java
index 24b9c930..36599c96 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeBudget.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeBudget.java
@@ -68,7 +68,7 @@ public class ErpProjectChangeBudget extends TenantEntity {
/**
* 排序顺序
*/
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeProgress.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeProgress.java
index 42e6472f..39f2aed4 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeProgress.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectChangeProgress.java
@@ -78,9 +78,9 @@ public class ErpProjectChangeProgress extends TenantEntity {
private BigDecimal completionDegree;
/**
- * 排序顺序
+ * 排序
*/
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectPlanStage.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectPlanStage.java
index 2a89b4a1..eec21538 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectPlanStage.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectPlanStage.java
@@ -107,7 +107,7 @@ public class ErpProjectPlanStage extends TenantEntity {
/**
* 排序号
*/
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeBudgetBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeBudgetBo.java
index bbf6b8a6..3399bf3b 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeBudgetBo.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeBudgetBo.java
@@ -67,7 +67,7 @@ public class ErpProjectChangeBudgetBo extends BaseEntity {
/**
* 排序顺序
*/
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeProgressBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeProgressBo.java
index 64641fda..5cc382b6 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeProgressBo.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectChangeProgressBo.java
@@ -75,7 +75,7 @@ public class ErpProjectChangeProgressBo extends BaseEntity {
/**
* 排序顺序
*/
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPlanStageBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPlanStageBo.java
index 687f4c7f..5dadcb76 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPlanStageBo.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPlanStageBo.java
@@ -106,7 +106,7 @@ public class ErpProjectPlanStageBo extends BaseEntity {
/**
* 排序号
*/
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeBudgetVo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeBudgetVo.java
index c3a87632..f6e5fb00 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeBudgetVo.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeBudgetVo.java
@@ -82,7 +82,7 @@ public class ErpProjectChangeBudgetVo implements Serializable {
* 排序顺序
*/
@ExcelProperty(value = "排序顺序")
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeProgressVo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeProgressVo.java
index e65708c7..482481d3 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeProgressVo.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeProgressVo.java
@@ -97,7 +97,7 @@ public class ErpProjectChangeProgressVo implements Serializable {
* 排序顺序
*/
@ExcelProperty(value = "排序顺序")
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeVo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeVo.java
index 421eb6a3..c548b6ca 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeVo.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectChangeVo.java
@@ -192,13 +192,16 @@ public class ErpProjectChangeVo implements Serializable {
/**
* 预算变更明细列表
*/
- @TableField(exist = false)
private List budgetList;
/**
* 进度变更明细列表
*/
- @TableField(exist = false)
private List progressList;
+ /**
+ * 创建人名称
+ */
+ private String createName;
+
}
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectPlanStageVo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectPlanStageVo.java
index 8c915889..6230e098 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectPlanStageVo.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectPlanStageVo.java
@@ -132,7 +132,7 @@ public class ErpProjectPlanStageVo implements Serializable {
* 排序号
*/
@ExcelProperty(value = "排序号")
- private Long sortOrder;
+ private Integer sortOrder;
/**
* 备注
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpProjectChangeProgressMapper.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpProjectChangeProgressMapper.java
index 4e7e2356..cc40a3fa 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpProjectChangeProgressMapper.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpProjectChangeProgressMapper.java
@@ -109,5 +109,12 @@ public interface ErpProjectChangeProgressMapper extends BaseMapperPlus queryWrapper);
+ /**
+ * 查询进度变更明细(连表查询项目阶段信息)
+ *
+ * @param projectChangeId 项目变更ID
+ * @return 进度变更明细集合
+ */
+ List selectProgressWithStageInfo(@Param("projectChangeId") Long projectChangeId);
}
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectChangeServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectChangeServiceImpl.java
index f1070935..26560545 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectChangeServiceImpl.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectChangeServiceImpl.java
@@ -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 budgetList = changeBudgetMapper.selectList(
+ Wrappers.lambdaQuery()
+ .eq(ErpProjectChangeBudget::getProjectChangeId, projectChangeId)
+ .orderByAsc(ErpProjectChangeBudget::getSortOrder)
+ );
+ vo.setBudgetList(budgetList);
+
+ // 查询进度变更明细(连表查询项目阶段信息)
+ List progressList = changeProgressMapper.selectProgressWithStageInfo(projectChangeId);
+ vo.setProgressList(progressList);
+ }
+ return vo;
+ }*/
/**
* 分页查询项目变更申请列表
@@ -102,7 +130,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
@Override
public TableDataInfo queryPageList(ErpProjectChangeBo bo, PageQuery pageQuery) {
MPJLambdaWrapper lqw = buildQueryWrapper(bo);
- Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ Page result = baseMapper.selectCustomErpProjectChangeVoList(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@@ -115,7 +143,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
@Override
public List queryList(ErpProjectChangeBo bo) {
MPJLambdaWrapper lqw = buildQueryWrapper(bo);
- return baseMapper.selectVoList(lqw);
+ return baseMapper.selectCustomErpProjectChangeVoList(lqw);
}
private MPJLambdaWrapper 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 budgetList = bo.getBudgetList();
- List 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 budgetList = bo.getBudgetList();
- List progressList = bo.getProgressList();
+ boolean flag = baseMapper.updateById(update) > 0;
+ if (flag) {
+ // 删除原有的预算变更明细
+ changeBudgetMapper.delete(Wrappers.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.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 existingBudgetIds = budgetList.stream()
- .map(ErpProjectChangeBudget::getChangeBudgetId)
- .filter(Objects::nonNull)
- .collect(Collectors.toSet());
- MPJLambdaWrapper budgetLqw = JoinWrappers.lambda(ErpProjectChangeBudget.class);
- budgetLqw.eq(ErpProjectChangeBudget::getProjectChangeId, bo.getProjectChangeId());
- List 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 existingProgressIds = progressList.stream()
- .map(ErpProjectChangeProgress::getChangeProgressId)
- .filter(Objects::nonNull)
- .collect(Collectors.toSet());
- MPJLambdaWrapper progressLqw = JoinWrappers.lambda(ErpProjectChangeProgress.class);
- progressLqw.eq(ErpProjectChangeProgress::getProjectChangeId, bo.getProjectChangeId());
- List 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 ids, Boolean isValid) {
- if(isValid){
- //TODO 做一些业务上的校验,判断是否需要校验
- }
- // 先删除子表
- changeBudgetMapper.delete(Wrappers.lambdaQuery().in(ErpProjectChangeBudget::getProjectChangeId, ids));
- changeProgressMapper.delete(Wrappers.lambdaQuery().in(ErpProjectChangeProgress::getProjectChangeId, ids));
- // 删除主表
- baseMapper.deleteByIds(ids);
- //删除工作流
- List 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.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 existingChanges = baseMapper.selectList(
+ Wrappers.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.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 planLqw = JoinWrappers.lambda(ErpProjectPlan.class)
- .eq(ErpProjectPlan::getProjectId, projectId)
- .eq(ErpProjectPlan::getDelFlag, "0");
- ErpProjectPlan projectPlan = projectPlanMapper.selectOne(planLqw);
+ // 计算变更次数(已完成的变更数量)
+ Long changeCount = baseMapper.selectCount(
+ Wrappers.lambdaQuery()
+ .eq(ErpProjectChange::getProjectId, projectId)
+ .eq(ErpProjectChange::getProjectChangeStatus, "3")
+ );
+ vo.setChangeNumber(changeCount.intValue() + 1);
- if (projectPlan != null) {
- // 查询项目计划阶段
- MPJLambdaWrapper stageLqw = JoinWrappers.lambda(ErpProjectPlanStage.class)
- .eq(ErpProjectPlanStage::getProjectPlanId, projectPlan.getProjectPlanId())
- .eq(ErpProjectPlanStage::getDelFlag, "0")
- .orderByAsc(ErpProjectPlanStage::getSortOrder);
- List planStageList = planStageMapper.selectList(stageLqw);
+ // 如果存在已完成的变更,将最新一次的变更数据作为默认值
+ if (changeCount > 0) {
+ ErpProjectChange lastChange = baseMapper.selectOne(
+ Wrappers.lambdaQuery()
+ .eq(ErpProjectChange::getProjectId, projectId)
+ .eq(ErpProjectChange::getProjectChangeStatus, "3")
+ .orderByDesc(ErpProjectChange::getCreateTime)
+ .last("limit 1")
+ );
- // 将项目阶段转换为进度变更明细
- if (ObjectUtils.isNotEmpty(planStageList)) {
- List 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 lastBudgetList = changeBudgetMapper.selectList(
+ Wrappers.lambdaQuery()
+ .eq(ErpProjectChangeBudget::getProjectChangeId, lastChange.getProjectChangeId())
+ .orderByAsc(ErpProjectChangeBudget::getSortOrder)
+ );
+
+ List 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 lastProgressList = changeProgressMapper.selectList(
+ Wrappers.lambdaQuery()
+ .eq(ErpProjectChangeProgress::getProjectChangeId, lastChange.getProjectChangeId())
+ .orderByAsc(ErpProjectChangeProgress::getSortOrder)
+ );
+
+ List 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 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 planStages = planStageMapper.selectList(
+ Wrappers.lambdaQuery()
+ .eq(ErpProjectPlanStage::getProjectId, projectId)
+ .orderByAsc(ErpProjectPlanStage::getSortOrder)
+ );
- vo.setChangeNumber(changeCount + 1); // 当前变更次数 = 已有次数 + 1
+ List 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.lambdaQuery()
+ .eq(ErpBudgetInfo::getProjectId, projectId)
+ .eq(ErpBudgetInfo::getBudgetStatus, "3") // 可用状态
+ .orderByDesc(ErpBudgetInfo::getBudgetVersion)
+ .last("limit 1")
+ );
+
+ List budgetList = new ArrayList<>();
+ if (budgetInfo != null) {
+ // 查询预算明细
+ List budgetDetails = budgetDetailMapper.selectList(
+ Wrappers.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 existingChanges = baseMapper.selectList(
+ Wrappers.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 ids, Boolean isValid) {
+ if(isValid){
+ // 校验是否可以删除(只能删除暂存状态的记录)
+ List changes = baseMapper.selectBatchIds(ids);
+ for (ErpProjectChange change : changes) {
+ if (!"1".equals(change.getProjectChangeStatus())) {
+ throw new ServiceException("只能删除暂存状态的变更申请");
+ }
+ }
+ }
+
+ // 删除主表和子表数据
+ for (Long id : ids) {
+ changeBudgetMapper.delete(Wrappers.lambdaQuery()
+ .eq(ErpProjectChangeBudget::getProjectChangeId, id));
+ changeProgressMapper.delete(Wrappers.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("只有项目经理才能提交项目变更申请");
- }
- }
}
diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPlanServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPlanServiceImpl.java
index 892c87d3..c7c2c4d5 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPlanServiceImpl.java
+++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPlanServiceImpl.java
@@ -283,12 +283,12 @@ public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
- List businessIds = ids.stream().toList();
// 先删除子表
planStageMapper.delete(Wrappers.lambdaQuery()
.in(ErpProjectPlanStage::getProjectPlanId, ids));
baseMapper.deleteByIds(ids);
//删除工作流
+ List businessIds = ids.stream().toList();
return remoteWorkflowService.deleteInstance(businessIds);
}
diff --git a/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeMapper.xml b/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeMapper.xml
index d9e7e207..9db0fd87 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeMapper.xml
+++ b/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeMapper.xml
@@ -7,35 +7,39 @@
@@ -309,7 +313,7 @@
+
diff --git a/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeProgressMapper.xml b/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeProgressMapper.xml
index bd47a671..3c308a16 100644
--- a/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeProgressMapper.xml
+++ b/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpProjectChangeProgressMapper.xml
@@ -195,5 +195,16 @@
${ew.getCustomSqlSegment}
+
+