|
|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
package org.dromara.oa.erp.service.impl;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
|
|
import cn.hutool.core.convert.Convert;
|
|
|
|
|
import cn.hutool.core.map.MapUtil;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
@ -7,6 +8,7 @@ import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.dromara.common.core.enums.BusinessStatusEnum;
|
|
|
|
|
import org.dromara.common.core.enums.OAStatusEnum;
|
|
|
|
|
import org.dromara.common.tenant.helper.TenantHelper;
|
|
|
|
|
import org.dromara.oa.erp.domain.bo.ErpContractChangeInfoBo;
|
|
|
|
|
import org.dromara.oa.erp.domain.bo.ErpContractChangeMaterialBo;
|
|
|
|
|
import org.dromara.oa.erp.domain.bo.ErpContractChangePaymentMethodBo;
|
|
|
|
|
import org.dromara.workflow.api.event.ProcessEvent;
|
|
|
|
|
@ -27,6 +29,8 @@ import org.dromara.oa.erp.domain.bo.ErpContractChangeSaveBo;
|
|
|
|
|
import org.dromara.oa.erp.domain.vo.*;
|
|
|
|
|
import org.dromara.oa.erp.mapper.*;
|
|
|
|
|
import org.dromara.oa.erp.service.IErpContractChangeService;
|
|
|
|
|
import org.dromara.oa.erp.service.IErpContractInfoService;
|
|
|
|
|
import org.dromara.oa.erp.domain.bo.ErpContractInfoBo;
|
|
|
|
|
import org.dromara.system.api.RemoteCodeRuleService;
|
|
|
|
|
import org.dromara.workflow.api.RemoteWorkflowService;
|
|
|
|
|
import org.dromara.workflow.api.domain.RemoteStartProcess;
|
|
|
|
|
@ -63,6 +67,8 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService {
|
|
|
|
|
private final ErpContractInfoMapper contractInfoMapper;
|
|
|
|
|
private final ErpContractMaterialMapper contractMaterialMapper;
|
|
|
|
|
private final ErpContractPaymentMethodMapper contractPaymentMethodMapper;
|
|
|
|
|
private final ErpProjectContractsMapper projectContractsMapper;
|
|
|
|
|
private final IErpContractInfoService contractInfoService;
|
|
|
|
|
|
|
|
|
|
@DubboReference
|
|
|
|
|
private RemoteCodeRuleService remoteCodeRuleService;
|
|
|
|
|
@ -234,6 +240,7 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService {
|
|
|
|
|
boolean isUpdate = bo.getContractChangeId() != null;
|
|
|
|
|
ErpContractChange main = buildMainEntity(bo);
|
|
|
|
|
validEntityBeforeSave(main);
|
|
|
|
|
validContentChangeContractCode(bo);
|
|
|
|
|
|
|
|
|
|
if (isUpdate) {
|
|
|
|
|
// 已回写的数据不允许覆盖回写相关字段
|
|
|
|
|
@ -313,6 +320,94 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService {
|
|
|
|
|
return baseMapper.selectVoById(changeId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 合同内容变更提交:不走 HTBG,保存变更单后新增合同并写入 new_contract_id,新合同由用户在合同管理中走正常合同流程(OAC)。
|
|
|
|
|
* 校验:变更后合同编号必须与原合同编号不同。
|
|
|
|
|
*
|
|
|
|
|
* @param bo 保存数据(主表 + changeInfo + changeMaterialList + changePaymentMethodList)
|
|
|
|
|
* @return 合同变更主表 VO(含 newContractId)
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@GlobalTransactional(rollbackFor = Exception.class)
|
|
|
|
|
public ErpContractChangeVo submitContentChange(ErpContractChangeSaveBo bo) {
|
|
|
|
|
// 保存变更单,变更状态设为可用、不发起流程
|
|
|
|
|
bo.setChangeStatus(CHANGE_STATUS_AVAILABLE);
|
|
|
|
|
bo.setFlowStatus("finish");
|
|
|
|
|
Long changeId = saveContractChange(bo);
|
|
|
|
|
ErpContractChange main = baseMapper.selectById(changeId);
|
|
|
|
|
if (main == null) {
|
|
|
|
|
throw new ServiceException("保存合同变更失败");
|
|
|
|
|
}
|
|
|
|
|
// 由变更快照新增合同,并直接走合同审批流程(OAC)
|
|
|
|
|
ErpContractInfoBo contractBo = buildContractBoFromChange(bo);
|
|
|
|
|
// 先插入合同主数据及子表
|
|
|
|
|
ErpContractInfoVo contractVo = contractInfoService.insertByBo(contractBo);
|
|
|
|
|
Long newContractId = contractVo.getContractId();
|
|
|
|
|
if (newContractId == null) {
|
|
|
|
|
throw new ServiceException("新增合同失败");
|
|
|
|
|
}
|
|
|
|
|
// 直接发起合同流程
|
|
|
|
|
contractBo.setContractId(newContractId);
|
|
|
|
|
contractInfoService.contractSubmitAndFlowStart(contractBo);
|
|
|
|
|
|
|
|
|
|
main.setNewContractId(newContractId);
|
|
|
|
|
baseMapper.updateById(main);
|
|
|
|
|
return baseMapper.selectVoById(changeId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 内容变更时校验:变更后合同编号必须与原合同编号不同
|
|
|
|
|
*/
|
|
|
|
|
private void validContentChangeContractCode(ErpContractChangeSaveBo bo) {
|
|
|
|
|
if (CHANGE_TYPE_CONTENT.equals(bo.getChangeType())) {
|
|
|
|
|
ErpContractInfo orig = contractInfoMapper.selectById(bo.getContractId());
|
|
|
|
|
if (orig == null) {
|
|
|
|
|
throw new ServiceException("原合同不存在");
|
|
|
|
|
}
|
|
|
|
|
String originalCode = orig.getContractCode();
|
|
|
|
|
String changeCode = bo.getChangeInfo().getContractCode();
|
|
|
|
|
if (changeCode != null && changeCode.trim().equals(StringUtils.isBlank(originalCode) ? "" : originalCode.trim())) {
|
|
|
|
|
throw new ServiceException("合同内容变更时,变更后合同编号必须与原合同编号不同");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 由变更快照组装合同 BO(不含 contractId,用于新增)
|
|
|
|
|
*/
|
|
|
|
|
private ErpContractInfoBo buildContractBoFromChange(ErpContractChangeSaveBo bo) {
|
|
|
|
|
ErpContractChangeInfoBo info = bo.getChangeInfo();
|
|
|
|
|
if (info == null) {
|
|
|
|
|
throw new ServiceException("内容变更时变更后合同信息不能为空");
|
|
|
|
|
}
|
|
|
|
|
// 不能直接用 MapstructUtils 在 BO 之间转换,这里显式拷贝字段
|
|
|
|
|
ErpContractInfoBo contractBo = new ErpContractInfoBo();
|
|
|
|
|
BeanUtil.copyProperties(info, contractBo, true);
|
|
|
|
|
contractBo.setContractId(null);
|
|
|
|
|
List<ErpContractMaterial> materials = new ArrayList<>();
|
|
|
|
|
if (bo.getChangeMaterialList() != null) {
|
|
|
|
|
for (ErpContractChangeMaterialBo m : bo.getChangeMaterialList()) {
|
|
|
|
|
ErpContractChangeMaterial entity = MapstructUtils.convert(m, ErpContractChangeMaterial.class);
|
|
|
|
|
materials.add(copyChangeMaterialToContract(entity, null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contractBo.setContractMaterialList(materials);
|
|
|
|
|
List<ErpContractPaymentMethod> payments = new ArrayList<>();
|
|
|
|
|
if (bo.getChangePaymentMethodList() != null) {
|
|
|
|
|
for (ErpContractChangePaymentMethodBo p : bo.getChangePaymentMethodList()) {
|
|
|
|
|
ErpContractChangePaymentMethod entity = MapstructUtils.convert(p, ErpContractChangePaymentMethod.class);
|
|
|
|
|
payments.add(copyChangePaymentToContract(entity, null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
contractBo.setContractPaymentMethodList(payments);
|
|
|
|
|
if (info.getDeliveryStart() != null && contractBo.getDeliveryStart() == null) {
|
|
|
|
|
contractBo.setDeliveryStart(info.getDeliveryStart().intValue());
|
|
|
|
|
}
|
|
|
|
|
contractBo.setOriginalContractId(bo.getContractId());
|
|
|
|
|
contractBo.setSignatureAppendix(null);
|
|
|
|
|
return contractBo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从 SaveBo 组装主表实体(不包含子表),新增时默认未回写、变更状态 1、激活 1
|
|
|
|
|
*/
|
|
|
|
|
@ -399,8 +494,6 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService {
|
|
|
|
|
Long contractId = change.getContractId();
|
|
|
|
|
if (CHANGE_TYPE_TERMINATE.equals(change.getChangeType())) {
|
|
|
|
|
doWriteBackTerminate(contractId);
|
|
|
|
|
} else {
|
|
|
|
|
doWriteBackContent(change.getContractChangeId(), contractId);
|
|
|
|
|
}
|
|
|
|
|
change.setChangeStatus(CHANGE_STATUS_AVAILABLE);
|
|
|
|
|
change.setFlowStatus(BusinessStatusEnum.FINISH.getStatus());
|
|
|
|
|
@ -419,6 +512,68 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 新合同激活时:若该合同为由内容变更产生的新合同,则继承原合同关联项目、作废原合同、解除原合同与项目关联并删除原合同订单信息。幂等。
|
|
|
|
|
* 优先从合同表 original_contract_id 取原合同ID,若无则从 erp_contract_change.new_contract_id 反查。
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public void onActivateNewContractFromChange(Long newContractId) {
|
|
|
|
|
if (newContractId == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ErpContractInfo newContract = contractInfoMapper.selectById(newContractId);
|
|
|
|
|
Long originalContractId = null;
|
|
|
|
|
if (newContract != null && newContract.getOriginalContractId() != null) {
|
|
|
|
|
originalContractId = newContract.getOriginalContractId();
|
|
|
|
|
}
|
|
|
|
|
if (originalContractId == null) {
|
|
|
|
|
List<ErpContractChange> list = baseMapper.selectList(
|
|
|
|
|
new LambdaQueryWrapper<ErpContractChange>()
|
|
|
|
|
.eq(ErpContractChange::getNewContractId, newContractId)
|
|
|
|
|
.last("limit 1"));
|
|
|
|
|
if (list.isEmpty()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
originalContractId = list.get(0).getContractId();
|
|
|
|
|
}
|
|
|
|
|
if (originalContractId == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ErpContractInfo originalContract = contractInfoMapper.selectById(originalContractId);
|
|
|
|
|
if (originalContract == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ("0".equals(originalContract.getActiveFlag()) && OAStatusEnum.INVALID.getStatus().equals(originalContract.getContractStatus())) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
List<ErpProjectContracts> oldLinks = projectContractsMapper.selectList(
|
|
|
|
|
new LambdaQueryWrapper<ErpProjectContracts>().eq(ErpProjectContracts::getContractId, originalContractId));
|
|
|
|
|
for (ErpProjectContracts oldLink : oldLinks) {
|
|
|
|
|
long cnt = projectContractsMapper.selectCount(
|
|
|
|
|
new LambdaQueryWrapper<ErpProjectContracts>()
|
|
|
|
|
.eq(ErpProjectContracts::getContractId, newContractId)
|
|
|
|
|
.eq(ErpProjectContracts::getProjectId, oldLink.getProjectId()));
|
|
|
|
|
if (cnt > 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
ErpProjectContracts newLink = new ErpProjectContracts();
|
|
|
|
|
newLink.setContractId(newContractId);
|
|
|
|
|
newLink.setProjectId(oldLink.getProjectId());
|
|
|
|
|
newLink.setSortOrder(oldLink.getSortOrder());
|
|
|
|
|
newLink.setRemark(oldLink.getRemark());
|
|
|
|
|
newLink.setActiveFlag(StringUtils.isNotBlank(oldLink.getActiveFlag()) ? oldLink.getActiveFlag() : "1");
|
|
|
|
|
newLink.setProjectSource(oldLink.getProjectSource());
|
|
|
|
|
projectContractsMapper.insert(newLink);
|
|
|
|
|
}
|
|
|
|
|
originalContract.setActiveFlag("0");
|
|
|
|
|
originalContract.setContractStatus(OAStatusEnum.INVALID.getStatus());
|
|
|
|
|
contractInfoMapper.updateById(originalContract);
|
|
|
|
|
for (ErpProjectContracts oldLink : oldLinks) {
|
|
|
|
|
projectContractsMapper.deleteById(oldLink.getProjectContractsId());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 内容变更回写:用变更信息快照更新原合同主表;原合同物料/付款方式先逻辑删除后按变更快照插入(逻辑删除,实体带 @TableLogic)。
|
|
|
|
|
*/
|
|
|
|
|
|