feat(erp): 后端添加自动编号生成及状态自动更新功能

- 引入 RemoteCodeRuleService 用于自动生成项目计划、变更、收货及验收确认编号
- 新增编号自动填充方法,确保首次保存时生成唯一编号
- 项目收货完成后自动更新项目状态为 5(已收货),仅升级不降级
- 项目验收完成后自动更新项目状态为 7(已验收),仅升级不降级
- 在更新项目计划阶段时支持同步更新实际开始和结束时间字段
- 保持编号未变时更新操作不覆盖原编号,确保数据一致性
dev
zangch@mesnac.com 3 months ago
parent eaacd488a8
commit 6f64659d7e

@ -14,6 +14,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.RemoteCodeRuleService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
import org.dromara.workflow.api.domain.RemoteStartProcess;
@ -51,11 +52,16 @@ import java.util.Objects;
@Slf4j
public class ErpProjectAcceptanceServiceImpl implements IErpProjectAcceptanceService {
private static final String ACCEPTANCE_CODE_RULE = "1008";
private final ErpProjectAcceptanceMapper baseMapper;
private final ErpProjectInfoMapper projectInfoMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
@DubboReference(timeout = 30000)
private RemoteCodeRuleService remoteCodeRuleService;
/**
*
@ -128,6 +134,7 @@ public class ErpProjectAcceptanceServiceImpl implements IErpProjectAcceptanceSer
validateProjectManager(bo.getManagerId());
ErpProjectAcceptance add = MapstructUtils.convert(bo, ErpProjectAcceptance.class);
fillAcceptanceCode(add);
validEntityBeforeSave(add);
// 默认业务状态:暂存
if (StringUtils.isBlank(add.getAcceptanceStatus())) {
@ -136,6 +143,7 @@ public class ErpProjectAcceptanceServiceImpl implements IErpProjectAcceptanceSer
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setAcceptanceId(add.getAcceptanceId());
bo.setAcceptanceCode(add.getAcceptanceCode());
}
return flag;
}
@ -156,6 +164,9 @@ public class ErpProjectAcceptanceServiceImpl implements IErpProjectAcceptanceSer
validateProjectManager(existing.getManagerId());
ErpProjectAcceptance update = MapstructUtils.convert(bo, ErpProjectAcceptance.class);
if (StringUtils.isBlank(update.getAcceptanceCode())) {
update.setAcceptanceCode(existing.getAcceptanceCode());
}
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
@ -167,6 +178,20 @@ public class ErpProjectAcceptanceServiceImpl implements IErpProjectAcceptanceSer
//TODO 做一些数据校验,如唯一约束
}
/**
*
*/
private void fillAcceptanceCode(ErpProjectAcceptance entity) {
if (StringUtils.isNotBlank(entity.getAcceptanceCode())) {
return;
}
String code = remoteCodeRuleService.selectCodeRuleCode(ACCEPTANCE_CODE_RULE);
if (StringUtils.isBlank(code)) {
throw new ServiceException("生成验收确认编号失败");
}
entity.setAcceptanceCode(code);
}
/**
* /
*
@ -301,6 +326,33 @@ public class ErpProjectAcceptanceServiceImpl implements IErpProjectAcceptanceSer
// 根据流程状态更新业务状态
if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) {
acceptance.setAcceptanceStatus(OAStatusEnum.COMPLETED.getStatus());
// 审批完成后,更新项目信息的项目状态为 7已验收
Long projectId = acceptance.getProjectId();
if (projectId != null) {
ErpProjectInfo projectInfo = projectInfoMapper.selectById(projectId);
if (projectInfo != null) {
String currentStatus = projectInfo.getProjectStatus();
boolean needUpdate = false;
if (StringUtils.isBlank(currentStatus)) {
needUpdate = true;
} else {
try {
/** 7 1 3 5 "7"
退 8 7 */
needUpdate = Integer.parseInt(currentStatus) < 7;
} catch (NumberFormatException e) {
// 非数字状态直接覆盖为已验收
needUpdate = true;
}
}
if (needUpdate) {
projectInfo.setProjectStatus("7"); // 7已验收
projectInfoMapper.updateById(projectInfo);
}
}
}
log.info("项目验收确认完成: acceptanceId={}", acceptance.getAcceptanceId());
} else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.INVALID.getStatus())
|| Objects.equals(processEvent.getStatus(), BusinessStatusEnum.TERMINATION.getStatus())) {

@ -19,6 +19,7 @@ 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.system.api.RemoteCodeRuleService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.event.ProcessEvent;
@ -51,6 +52,8 @@ import java.math.BigDecimal;
@Slf4j
public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
private static final String PROJECT_CHANGE_CODE_RULE = "1011";
// 计划变更主子表
private final ErpProjectChangeMapper baseMapper;
private final ErpProjectChangeBudgetMapper changeBudgetMapper;
@ -66,6 +69,8 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
@DubboReference(timeout = 30000)
private RemoteCodeRuleService remoteCodeRuleService;
/**
*
@ -203,6 +208,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
*/
ErpProjectChange add = MapstructUtils.convert(bo, ErpProjectChange.class);
fillProjectChangeCode(add);
validEntityBeforeSave(add);
// 设置默认状态
@ -216,6 +222,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setProjectChangeId(add.getProjectChangeId());
bo.setProjectChangeCode(add.getProjectChangeCode());
// 保存预算变更明细
if (bo.getBudgetList() != null && !bo.getBudgetList().isEmpty()) {
@ -261,6 +268,9 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
}
ErpProjectChange update = MapstructUtils.convert(bo, ErpProjectChange.class);
if (StringUtils.isBlank(update.getProjectChangeCode())) {
update.setProjectChangeCode(existing.getProjectChangeCode());
}
validEntityBeforeSave(update);
boolean flag = baseMapper.updateById(update) > 0;
@ -306,12 +316,17 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
if (projectId == null) {
throw new ServiceException("项目ID不能为空");
}
// 查询项目信息
ErpProjectChangeVo vo = baseMapper.prepareByProjectId(projectId);
if (vo == null) {
throw new ServiceException("项目信息不存在");
}
// 检查是否有未完成的变更状态1或2
List<ErpProjectChange> existingChanges = baseMapper.selectList(
Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.in(ErpProjectChange::getProjectChangeStatus, Arrays.asList("1", "2"))
.in(ErpProjectChange::getProjectChangeStatus, Arrays.asList("1", "2"))//项目变更状态(1暂存 2审批中 3可用)
.orderByDesc(ErpProjectChange::getCreateTime)
);
@ -326,17 +341,12 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
throw new ServiceException("该项目存在未完成的变更申请,请先完成或取消后再发起新的变更");
}
// 查询项目信息
ErpProjectChangeVo vo = baseMapper.prepareByProjectId(projectId);
if (vo == null) {
throw new ServiceException("项目信息不存在");
}
// 计算变更次数(已完成的变更数量)
Long changeCount = baseMapper.selectCount(
Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.eq(ErpProjectChange::getProjectChangeStatus, "3")
.eq(ErpProjectChange::getProjectChangeStatus, "3")//项目变更状态(1暂存 2审批中 3可用)
);
vo.setChangeNumber(changeCount.intValue() + 1);
@ -345,8 +355,8 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
ErpProjectChange lastChange = baseMapper.selectOne(
Wrappers.<ErpProjectChange>lambdaQuery()
.eq(ErpProjectChange::getProjectId, projectId)
.eq(ErpProjectChange::getProjectChangeStatus, "3")
.orderByDesc(ErpProjectChange::getCreateTime)
.eq(ErpProjectChange::getProjectChangeStatus, "3")// 项目变更状态(1暂存 2审批中 3可用)
.orderByDesc(ErpProjectChange::getChangeNumber)// 按变更次数降序
.last("limit 1")
);
@ -463,7 +473,7 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
// 设置默认状态
vo.setProjectChangeStatus("1"); // 暂存
vo.setActiveFlag("1");
vo.setActiveFlag("1");//默认激活
return vo;
}
@ -566,6 +576,20 @@ public class ErpProjectChangeServiceImpl implements IErpProjectChangeService {
//TODO 做一些数据校验,如唯一约束
}
/**
*
*/
private void fillProjectChangeCode(ErpProjectChange entity) {
if (StringUtils.isNotBlank(entity.getProjectChangeCode())) {
return;
}
String code = remoteCodeRuleService.selectCodeRuleCode(PROJECT_CHANGE_CODE_RULE);
if (StringUtils.isBlank(code)) {
throw new ServiceException("生成项目变更编号失败");
}
entity.setProjectChangeCode(code);
}
/**
*
* ErpProjectChange project_id project_plan_id

@ -23,6 +23,7 @@ import org.dromara.oa.erp.domain.ErpProjectInfo;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper;
import org.dromara.system.api.RemoteCodeRuleService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.event.ProcessEvent;
@ -50,12 +51,16 @@ import java.util.stream.Collectors;
@Slf4j
public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
private static final String PROJECT_PLAN_CODE_RULE = "1010";
private final ErpProjectPlanMapper baseMapper;
private final ErpProjectPlanStageMapper planStageMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
@DubboReference(timeout = 30000)
private RemoteCodeRuleService remoteCodeRuleService;
/**
*
@ -140,6 +145,7 @@ public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(ErpProjectPlanBo bo) {
ErpProjectPlan add = MapstructUtils.convert(bo, ErpProjectPlan.class);
fillProjectPlanCode(add);
validEntityBeforeSave(add);
// 权限校验:只有项目经理才能提交
validateProjectManager(bo.getManagerId());
@ -147,6 +153,7 @@ public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setProjectPlanId(add.getProjectPlanId());
bo.setProjectPlanCode(add.getProjectPlanCode());
if ( ObjectUtils.isNotEmpty(planStageList)) {
for (ErpProjectPlanStage planStage : planStageList) {
planStage.setProjectPlanId(add.getProjectPlanId());
@ -183,12 +190,14 @@ public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
if (planStageList != null && !planStageList.isEmpty()) {
for (ErpProjectPlanStage newStage : planStageList) {
if (newStage.getPlanStageId() != null) {
// 只更新delayDay、scheduleRemark和receivableDate
// 只更新delayDay、scheduleRemark、receivableDate、realStartTime、realEndTime字段
ErpProjectPlanStage existingStage = planStageMapper.selectById(newStage.getPlanStageId());
if (existingStage != null) {
existingStage.setDelayDay(newStage.getDelayDay());
existingStage.setScheduleRemark(newStage.getScheduleRemark());
existingStage.setReceivableDate(newStage.getReceivableDate());
existingStage.setRealStartTime(newStage.getRealStartTime());// 实际开始时间
existingStage.setRealEndTime(newStage.getRealEndTime());//实际结束时间
planStageMapper.updateById(existingStage);
}
}
@ -200,6 +209,9 @@ public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
// 草稿状态,允许全面更新
ErpProjectPlan update = MapstructUtils.convert(bo, ErpProjectPlan.class);
if (StringUtils.isBlank(update.getProjectPlanCode())) {
update.setProjectPlanCode(existingPlan.getProjectPlanCode());
}
validEntityBeforeSave(update);
List<ErpProjectPlanStage> planStageList = bo.getPlanStageList();
MPJLambdaWrapper<ErpProjectPlanStage> lqwRecord = JoinWrappers.lambda(ErpProjectPlanStage.class);
@ -255,6 +267,20 @@ public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
}
}
/**
*
*/
private void fillProjectPlanCode(ErpProjectPlan entity) {
if (StringUtils.isNotBlank(entity.getProjectPlanCode())) {
return;
}
String code = remoteCodeRuleService.selectCodeRuleCode(PROJECT_PLAN_CODE_RULE);
if (StringUtils.isBlank(code)) {
throw new ServiceException("生成项目计划编号失败");
}
entity.setProjectPlanCode(code);
}
/**
*
*

@ -14,6 +14,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.RemoteCodeRuleService;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
import org.dromara.workflow.api.domain.RemoteStartProcess;
@ -48,11 +49,15 @@ import java.util.*;
@Slf4j
public class ErpProjectReceivingServiceImpl implements IErpProjectReceivingService {
private static final String RECEIVING_CODE_RULE = "1009";
private final ErpProjectReceivingMapper baseMapper;
private final ErpProjectInfoMapper projectInfoMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
@DubboReference(timeout = 30000)
private RemoteCodeRuleService remoteCodeRuleService;
/**
*
@ -124,6 +129,7 @@ public class ErpProjectReceivingServiceImpl implements IErpProjectReceivingServi
validateProjectManager(bo.getManagerId());
ErpProjectReceiving add = MapstructUtils.convert(bo, ErpProjectReceiving.class);
fillReceivingCode(add);
validEntityBeforeSave(add);
// 默认业务状态:暂存
if (StringUtils.isBlank(add.getReceivingStatus())) {
@ -132,6 +138,7 @@ public class ErpProjectReceivingServiceImpl implements IErpProjectReceivingServi
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setReceivingId(add.getReceivingId());
bo.setReceivingCode(add.getReceivingCode());
}
return flag;
}
@ -152,6 +159,9 @@ public class ErpProjectReceivingServiceImpl implements IErpProjectReceivingServi
validateProjectManager(existing.getManagerId());
ErpProjectReceiving update = MapstructUtils.convert(bo, ErpProjectReceiving.class);
if (StringUtils.isBlank(update.getReceivingCode())) {
update.setReceivingCode(existing.getReceivingCode());
}
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
@ -163,6 +173,20 @@ public class ErpProjectReceivingServiceImpl implements IErpProjectReceivingServi
//TODO 做一些数据校验,如唯一约束
}
/**
*
*/
private void fillReceivingCode(ErpProjectReceiving entity) {
if (StringUtils.isNotBlank(entity.getReceivingCode())) {
return;
}
String code = remoteCodeRuleService.selectCodeRuleCode(RECEIVING_CODE_RULE);
if (StringUtils.isBlank(code)) {
throw new ServiceException("生成收货确认编号失败");
}
entity.setReceivingCode(code);
}
/**
* /
*
@ -297,6 +321,33 @@ public class ErpProjectReceivingServiceImpl implements IErpProjectReceivingServi
// 根据流程状态更新业务状态
if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) {
receiving.setReceivingStatus(OAStatusEnum.COMPLETED.getStatus());
// 审批完成后,更新项目信息的项目状态为 5已收货
Long projectId = receiving.getProjectId();
if (projectId != null) {
ErpProjectInfo projectInfo = projectInfoMapper.selectById(projectId);
if (projectInfo != null) {
String currentStatus = projectInfo.getProjectStatus();
boolean needUpdate = false;
if (StringUtils.isBlank(currentStatus)) {
needUpdate = true;
} else {
try {
/** 5 1 3 "5"
退 8 5 */
needUpdate = Integer.parseInt(currentStatus) < 5;
} catch (NumberFormatException e) {
// 非数字状态直接覆盖为已收货
needUpdate = true;
}
}
if (needUpdate) {
projectInfo.setProjectStatus("5"); // 5已收货
projectInfoMapper.updateById(projectInfo);
}
}
}
log.info("项目收货确认完成: receivingId={}", receiving.getReceivingId());
} else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.INVALID.getStatus())
|| Objects.equals(processEvent.getStatus(), BusinessStatusEnum.TERMINATION.getStatus())) {

Loading…
Cancel
Save