From 1ddb949da3fc14206eabf340cc9eb2766311a55f Mon Sep 17 00:00:00 2001 From: yinq Date: Tue, 23 Dec 2025 17:52:25 +0800 Subject: [PATCH] =?UTF-8?q?1.0.49=20=E5=90=88=E5=90=8C=E3=80=81=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96=E3=80=82=E5=90=88?= =?UTF-8?q?=E5=90=8C=E8=AE=A2=E5=8D=95=E5=90=8E=E7=AB=AF=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TemplateVariableAssignServiceImpl.java | 7 +- .../ErpContractOrderController.java | 79 +++++ .../erp/domain/ErpContractPaymentStage.java | 42 ++- .../dromara/oa/erp/domain/ErpProjectInfo.java | 2 +- .../domain/bo/ErpContractPaymentStageBo.java | 43 ++- .../oa/erp/domain/bo/ErpProjectInfoBo.java | 12 +- .../erp/domain/bo/ErpProjectPurchaseBo.java | 10 + .../domain/vo/ErpContractPaymentStageVo.java | 87 +++++- .../oa/erp/domain/vo/ErpProjectInfoVo.java | 2 +- .../mapper/ErpContractPaymentStageMapper.java | 1 - .../erp/service/IErpContractOrderService.java | 46 +++ .../impl/ErpContractInfoServiceImpl.java | 7 +- .../impl/ErpContractOrderServiceImpl.java | 295 ++++++++++++++++++ .../ErpContractPaymentStageServiceImpl.java | 9 +- .../impl/ErpProjectPurchaseServiceImpl.java | 20 +- .../oa/erp/ErpContractPaymentStageMapper.xml | 9 +- 16 files changed, 642 insertions(+), 29 deletions(-) create mode 100644 ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java create mode 100644 ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java create mode 100644 ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/base/service/impl/TemplateVariableAssignServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/base/service/impl/TemplateVariableAssignServiceImpl.java index 73134016..272e77ef 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/base/service/impl/TemplateVariableAssignServiceImpl.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/base/service/impl/TemplateVariableAssignServiceImpl.java @@ -82,13 +82,10 @@ public class TemplateVariableAssignServiceImpl implements ITemplateVariableAssig Map variableMap = buildVariableMap(allTemplateVariables); // 2. 查询合同信息 - ErpContractInfoBo bo = new ErpContractInfoBo(); - bo.setContractId(request.getContractId()); - List contractInfoVoList = erpContractInfoService.queryList(bo); - if (contractInfoVoList.isEmpty()) { + ErpContractInfoVo contractInfo = erpContractInfoService.queryById(request.getContractId()); + if (StringUtils.isNull(contractInfo)) { throw new ServiceException("合同信息不存在,合同ID:" + request.getContractId()); } - ErpContractInfoVo contractInfo = contractInfoVoList.get(0); // 3. 查询合同物料列表(如果存在需要物料数据的变量) List contractMaterials = null; diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java new file mode 100644 index 00000000..bf429285 --- /dev/null +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractOrderController.java @@ -0,0 +1,79 @@ +package org.dromara.oa.erp.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.web.core.BaseController; +import org.dromara.oa.erp.domain.bo.ErpProjectInfoBo; +import org.dromara.oa.erp.domain.vo.ErpProjectInfoVo; +import org.dromara.oa.erp.service.IErpContractOrderService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 合同订单 + * 前端访问路由地址为:/oa/erp/contractOrder + * + * @author Yinq + * @date 2025-12-05 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/erp/contractOrder") +public class ErpContractOrderController extends BaseController { + + private final IErpContractOrderService erpContractOrderService; + + /** + * 暂存合同订单(项目信息) + */ + @SaCheckPermission("oa/erp:projectInfo:add") + @Log(title = "合同订单", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/save") + public R save(@Validated(AddGroup.class) @RequestBody ErpProjectInfoBo bo) { + return R.ok(erpContractOrderService.saveContractOrder(bo)); + } + + /** + * 提交合同订单并提交流程 + */ + @SaCheckPermission("oa/erp:projectInfo:add") + @Log(title = "合同订单", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/submitAndFlowStart") + public R submitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectInfoBo bo) { + return R.ok(erpContractOrderService.submitContractOrderAndFlowStart(bo)); + } + + /** + * 修改合同订单(项目信息) + */ + @SaCheckPermission("oa/erp:projectInfo:edit") + @Log(title = "合同订单", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody ErpProjectInfoBo bo) { + return R.ok(erpContractOrderService.updateContractOrder(bo)); + } + + /** + * 获取合同订单详细信息 + * + * @param projectId 主键 + */ + @SaCheckPermission("oa/erp:projectInfo:query") + @GetMapping("/{projectId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable("projectId") Long projectId) { + return R.ok(erpContractOrderService.queryById(projectId)); + } +} + diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpContractPaymentStage.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpContractPaymentStage.java index 22712b2e..fdeb3ba7 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpContractPaymentStage.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpContractPaymentStage.java @@ -4,7 +4,8 @@ import org.dromara.common.tenant.core.TenantEntity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; -import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; import java.io.Serial; @@ -49,9 +50,44 @@ public class ErpContractPaymentStage extends TenantEntity { private String collectionStage; /** - * 回款比例(%) + * 回款比例(%) */ - private BigDecimal purchasePrice; + private Long repaymentRate; + + /** + * 预计回款日期 + */ + private Date expectRepaymentDate; + + /** + * 回款延期天数 + */ + private Long delayDay; + + /** + * 实际回款日期 + */ + private Date actualRepaymentDate; + + /** + * 回款标识(0否 1是) + */ + private String repaymentFlag; + + /** + * 原因说明 + */ + private String reasonsExplanation; + + /** + * 进度备注 + */ + private String scheduleRemark; + + /** + * 回款金额(预留) + */ + private Long repaymentAmount; /** * 排序号 diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectInfo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectInfo.java index 4f2a1671..97688336 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectInfo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/ErpProjectInfo.java @@ -49,7 +49,7 @@ public class ErpProjectInfo extends TenantEntity { private String businessDirection; /** - * 项目类别(1销售(实施、物流) 2销售(备件) 3研发 4预投) + * 项目类别(1销售(实施、物流) 2销售(备件) 3研发 4预投 5合同订单) */ private String projectCategory; diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractPaymentStageBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractPaymentStageBo.java index 2e601861..286198d6 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractPaymentStageBo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractPaymentStageBo.java @@ -8,7 +8,8 @@ import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; import lombok.EqualsAndHashCode; import jakarta.validation.constraints.*; -import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; /** * 合同回款阶段业务对象 erp_contract_payment_stage @@ -46,13 +47,47 @@ public class ErpContractPaymentStageBo extends BaseEntity { /** * 回款阶段 */ - @NotBlank(message = "回款阶段不能为空", groups = { AddGroup.class, EditGroup.class }) private String collectionStage; /** - * 回款比例(%) + * 回款比例(%) */ - private BigDecimal purchasePrice; + private Long repaymentRate; + + /** + * 预计回款日期 + */ + private Date expectRepaymentDate; + + /** + * 回款延期天数 + */ + private Long delayDay; + + /** + * 实际回款日期 + */ + private Date actualRepaymentDate; + + /** + * 回款标识(0否 1是) + */ + private String repaymentFlag; + + /** + * 原因说明 + */ + private String reasonsExplanation; + + /** + * 进度备注 + */ + private String scheduleRemark; + + /** + * 回款金额(预留) + */ + private Long repaymentAmount; /** * 排序号 diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectInfoBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectInfoBo.java index bc86e29c..f6b84ea0 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectInfoBo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectInfoBo.java @@ -12,6 +12,7 @@ import java.math.BigDecimal; import java.util.*; import cn.hutool.core.util.ObjectUtil; import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt; +import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo; /** * 项目信息业务对象 erp_project_info @@ -38,7 +39,7 @@ public class ErpProjectInfoBo extends BaseEntity { /** * 项目编号 */ - @NotBlank(message = "项目编号不能为空", groups = { AddGroup.class, EditGroup.class }) +// @NotBlank(message = "项目编号不能为空", groups = { AddGroup.class, EditGroup.class }) private String projectCode; /** @@ -53,9 +54,9 @@ public class ErpProjectInfoBo extends BaseEntity { private String businessDirection; /** - * 项目类别(1销售(实施、物流) 2销售(备件) 3研发 4预投) + * 项目类别(1销售(实施、物流) 2销售(备件) 3研发 4预投 5合同订单) */ - @NotBlank(message = "项目类别(1销售(实施、物流) 2销售(备件) 3研发 4预投)不能为空", groups = { AddGroup.class, EditGroup.class }) + @NotBlank(message = "项目类别", groups = { AddGroup.class, EditGroup.class }) private String projectCategory; /** @@ -158,6 +159,11 @@ public class ErpProjectInfoBo extends BaseEntity { */ private RemoteFlowInstanceBizExt bizExt; + /** + * 项目阶段计划列表 + */ + private List planStageList; + public Map getVariables() { if (variables == null) { return new HashMap<>(16); diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPurchaseBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPurchaseBo.java index fe77892c..fe6d62ae 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPurchaseBo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpProjectPurchaseBo.java @@ -41,6 +41,11 @@ public class ErpProjectPurchaseBo extends BaseEntity { @NotBlank(message = "项目号不能为空", groups = { AddGroup.class, EditGroup.class }) private String projectCode; + /** + * 项目名称 + */ + private String projectName; + /** * 采购编号 */ @@ -51,6 +56,11 @@ public class ErpProjectPurchaseBo extends BaseEntity { */ private Long managerId; + /** + * 项目经理名称 + */ + private String managerName; + /** * 部门负责人 */ diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpContractPaymentStageVo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpContractPaymentStageVo.java index 52f221c6..96363f17 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpContractPaymentStageVo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpContractPaymentStageVo.java @@ -1,6 +1,7 @@ package org.dromara.oa.erp.domain.vo; -import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; import org.dromara.oa.erp.domain.ErpContractPaymentStage; import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; @@ -56,15 +57,59 @@ public class ErpContractPaymentStageVo implements Serializable { /** * 回款阶段 */ - @ExcelProperty(value = "回款阶段") + @ExcelProperty(value = "回款阶段", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "collection_stage") private String collectionStage; /** - * 回款比例(%) + * 回款比例(%) */ - @ExcelProperty(value = "回款比例", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "%=") - private BigDecimal purchasePrice; + @ExcelProperty(value = "回款比例(%)") + private Long repaymentRate; + + /** + * 预计回款日期 + */ + @ExcelProperty(value = "预计回款日期") + private Date expectRepaymentDate; + + /** + * 回款延期天数 + */ + @ExcelProperty(value = "回款延期天数") + private Long delayDay; + + /** + * 实际回款日期 + */ + @ExcelProperty(value = "实际回款日期") + private Date actualRepaymentDate; + + /** + * 回款标识(0否 1是) + */ + @ExcelProperty(value = "回款标识", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=否,1=是") + private String repaymentFlag; + + /** + * 原因说明 + */ + @ExcelProperty(value = "原因说明") + private String reasonsExplanation; + + /** + * 进度备注 + */ + @ExcelProperty(value = "进度备注") + private String scheduleRemark; + + /** + * 回款金额(预留) + */ + @ExcelProperty(value = "回款金额", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "预=留") + private Long repaymentAmount; /** * 排序号 @@ -78,5 +123,35 @@ public class ErpContractPaymentStageVo implements Serializable { @ExcelProperty(value = "备注") private String remark; + /** + * 创建部门 + */ + @ExcelProperty(value = "创建部门") + private Long createDept; + + /** + * 创建者 + */ + @ExcelProperty(value = "创建者") + private Long createBy; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + + /** + * 更新者 + */ + @ExcelProperty(value = "更新者") + private Long updateBy; + + /** + * 更新时间 + */ + @ExcelProperty(value = "更新时间") + private Date updateTime; + } diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectInfoVo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectInfoVo.java index b64f45c0..882001c0 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectInfoVo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/vo/ErpProjectInfoVo.java @@ -62,7 +62,7 @@ public class ErpProjectInfoVo implements Serializable { private String businessDirection; /** - * 项目类别(1销售(实施、物流) 2销售(备件) 3研发 4预投) + * 项目类别(1销售(实施、物流) 2销售(备件) 3研发 4预投 5合同订单) */ @ExcelProperty(value = "项目类别", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "project_category") diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpContractPaymentStageMapper.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpContractPaymentStageMapper.java index fee612f5..791bd568 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpContractPaymentStageMapper.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/mapper/ErpContractPaymentStageMapper.java @@ -1,7 +1,6 @@ package org.dromara.oa.erp.mapper; import java.util.List; - import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java new file mode 100644 index 00000000..146753fb --- /dev/null +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractOrderService.java @@ -0,0 +1,46 @@ +package org.dromara.oa.erp.service; + +import org.dromara.oa.erp.domain.vo.ErpProjectInfoVo; +import org.dromara.oa.erp.domain.bo.ErpProjectInfoBo; + +/** + * 合同订单Service接口 + * + * @author Yinq + * @date 2025-12-05 + */ +public interface IErpContractOrderService { + + /** + * 查询合同订单(项目信息) + * + * @param projectId 主键 + * @return 合同订单(项目信息) + */ + ErpProjectInfoVo queryById(Long projectId); + + /** + * 暂存合同订单(项目信息) + * + * @param bo 合同订单(项目信息) + * @return 合同订单(项目信息) + */ + ErpProjectInfoVo saveContractOrder(ErpProjectInfoBo bo); + + /** + * 修改合同订单(项目信息) + * + * @param bo 合同订单(项目信息) + * @return 合同订单(项目信息) + */ + ErpProjectInfoVo updateContractOrder(ErpProjectInfoBo bo); + + /** + * 提交合同订单并提交流程 + * + * @param bo 合同订单(项目信息) + * @return 合同订单(项目信息) + */ + ErpProjectInfoVo submitContractOrderAndFlowStart(ErpProjectInfoBo bo); +} + diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractInfoServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractInfoServiceImpl.java index 9471b1ec..4e5bc603 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractInfoServiceImpl.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractInfoServiceImpl.java @@ -1,6 +1,7 @@ package org.dromara.oa.erp.service.impl; import cn.hutool.core.convert.Convert; +import cn.hutool.core.convert.NumberChineseFormatter; import cn.hutool.core.map.MapUtil; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; @@ -240,6 +241,11 @@ public class ErpContractInfoServiceImpl implements IErpContractInfoService { // if (entity.getContractMaterialList() == null || entity.getContractMaterialList().isEmpty()) { // throw new ServiceException("请填写合同物料!"); // } + //存储合同大写金额 + if (StringUtils.isNotNull(entity.getTotalPrice())) { + String capitalizedAmount = NumberChineseFormatter.format(entity.getTotalPrice().doubleValue(), true, true); + entity.setCapitalizedAmount(capitalizedAmount); + } } /** @@ -267,7 +273,6 @@ public class ErpContractInfoServiceImpl implements IErpContractInfoService { @GlobalTransactional(rollbackFor = Exception.class) public ErpContractInfoVo contractSubmitAndFlowStart(ErpContractInfoBo bo) { ErpContractInfo add = MapstructUtils.convert(bo, ErpContractInfo.class); - validEntityBeforeSave(add); if (StringUtils.isNull(bo.getContractId())) { this.insertByBo(bo); } else { diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java new file mode 100644 index 00000000..51a809ff --- /dev/null +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractOrderServiceImpl.java @@ -0,0 +1,295 @@ +package org.dromara.oa.erp.service.impl; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.seata.spring.annotation.GlobalTransactional; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.enums.OAStatusEnum; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.oa.erp.domain.ErpProjectInfo; +import org.dromara.oa.erp.domain.ErpProjectPlan; +import org.dromara.oa.erp.domain.ErpProjectPlanStage; +import org.dromara.oa.erp.domain.bo.ErpProjectInfoBo; +import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo; +import org.dromara.oa.erp.domain.vo.ErpProjectInfoVo; +import org.dromara.oa.erp.mapper.ErpProjectInfoMapper; +import org.dromara.oa.erp.mapper.ErpProjectPlanMapper; +import org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper; +import org.dromara.oa.erp.service.IErpContractOrderService; +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; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; +import org.apache.dubbo.config.annotation.DubboReference; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.convert.Convert; + +/** + * 合同订单Service业务层处理 + * + * @author Yinq + * @date 2025-12-05 + */ +@RequiredArgsConstructor +@Service +@Slf4j +public class ErpContractOrderServiceImpl implements IErpContractOrderService { + + private final ErpProjectInfoMapper projectInfoMapper; + private final ErpProjectPlanMapper projectPlanMapper; + private final ErpProjectPlanStageMapper planStageMapper; + + @DubboReference(timeout = 30000) + private RemoteWorkflowService remoteWorkflowService; + + @DubboReference(timeout = 30000) + private RemoteCodeRuleService remoteCodeRuleService; + + /** + * 查询合同订单(项目信息) + * + * @param projectId 主键 + * @return 合同订单(项目信息) + */ + @Override + public ErpProjectInfoVo queryById(Long projectId) { + ErpProjectInfo projectInfo = projectInfoMapper.selectById(projectId); + if (projectInfo == null) { + return null; + } + return MapstructUtils.convert(projectInfo, ErpProjectInfoVo.class); + } + + /** + * 暂存合同订单(项目信息) + * + * @param bo 合同订单(项目信息) + * @return 合同订单(项目信息) + */ + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public ErpProjectInfoVo saveContractOrder(ErpProjectInfoBo bo) { + // 保存项目信息 + ErpProjectInfo projectInfo = MapstructUtils.convert(bo, ErpProjectInfo.class); + validEntityBeforeSave(projectInfo); + + if (StringUtils.isNull(bo.getProjectId())) { + // 新增 + projectInfoMapper.insert(projectInfo); + bo.setProjectId(projectInfo.getProjectId()); + } else { + // 更新 + projectInfoMapper.updateById(projectInfo); + } + + // 保存项目阶段计划列表 + savePlanStageList(projectInfo, bo.getPlanStageList()); + + return MapstructUtils.convert(projectInfo, ErpProjectInfoVo.class); + } + + /** + * 修改合同订单(项目信息) + * + * @param bo 合同订单(项目信息) + * @return 合同订单(项目信息) + */ + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public ErpProjectInfoVo updateContractOrder(ErpProjectInfoBo bo) { + return saveContractOrder(bo); + } + + /** + * 提交合同订单并提交流程 + * + * @param bo 合同订单(项目信息) + * @return 合同订单(项目信息) + */ + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public ErpProjectInfoVo submitContractOrderAndFlowStart(ErpProjectInfoBo bo) { + // 先保存项目信息和项目阶段计划 + ErpProjectInfoVo vo = saveContractOrder(bo); + + if (1==1) { + return vo; + } + + // 后端发起需要忽略权限 + bo.getVariables().put("ignore", true); + RemoteStartProcess startProcess = new RemoteStartProcess(); + startProcess.setBusinessId(bo.getProjectId().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 vo; + } + + /** + * 保存项目阶段计划列表 + * + * @param projectInfo 项目信息 + * @param planStageList 项目阶段计划列表 + */ + private void savePlanStageList(ErpProjectInfo projectInfo, List planStageList) { + if (projectInfo == null || projectInfo.getProjectId() == null) { + return; + } + + // 如果planStageList为null,表示前端没有传递该字段,不处理 + if (planStageList == null) { + return; + } + + Long projectId = projectInfo.getProjectId(); + // 先获取或创建项目计划 + Long projectPlanId = getOrCreateProjectPlan(projectInfo); + + // 查询原有的项目阶段计划ID列表(根据projectPlanId查询) + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ErpProjectPlanStage::getProjectPlanId, projectPlanId); + List existingStages = planStageMapper.selectList(queryWrapper); + List existingIds = existingStages.stream() + .map(ErpProjectPlanStage::getPlanStageId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + // 收集前端传来的ID列表(已存在的记录) + List newIds = planStageList.stream() + .map(ErpProjectPlanStageBo::getPlanStageId) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + // 删除不在新列表中的原有记录 + List idsToDelete = existingIds.stream() + .filter(id -> !newIds.contains(id)) + .collect(Collectors.toList()); + if (CollUtil.isNotEmpty(idsToDelete)) { + planStageMapper.deleteBatchIds(idsToDelete); + } + + // 保存或更新项目阶段计划 + for (ErpProjectPlanStageBo stageBo : planStageList) { + ErpProjectPlanStage stage = MapstructUtils.convert(stageBo, ErpProjectPlanStage.class); + stage.setProjectId(projectId); + stage.setProjectPlanId(projectPlanId); + if (StringUtils.isNull(stage.getPlanStageId())) { + // 新增 + planStageMapper.insert(stage); + } else { + // 更新 + planStageMapper.updateById(stage); + } + } + } + + /** + * 获取或创建项目计划 + * + * @param projectInfo 项目信息 + * @return 项目计划ID + */ + private Long getOrCreateProjectPlan(ErpProjectInfo projectInfo) { + if (projectInfo == null || projectInfo.getProjectId() == null) { + throw new ServiceException("项目信息不存在"); + } + + Long projectId = projectInfo.getProjectId(); + // 查询是否已存在项目计划 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ErpProjectPlan::getProjectId, projectId); + queryWrapper.eq(ErpProjectPlan::getDelFlag, "0"); + queryWrapper.orderByDesc(ErpProjectPlan::getCreateTime); + queryWrapper.last("LIMIT 1"); + List existingPlans = projectPlanMapper.selectList(queryWrapper); + + if (CollUtil.isNotEmpty(existingPlans)) { + return existingPlans.get(0).getProjectPlanId(); + } + + // 不存在则创建新的项目计划 + ErpProjectPlan newPlan = new ErpProjectPlan(); + newPlan.setProjectId(projectId); + newPlan.setProjectPlanStatus("3"); + newPlan.setFlowStatus("finish"); + newPlan.setManagerId(projectInfo.getManagerId()); + newPlan.setChargeId(projectInfo.getChargeId()); + + // 生成项目计划编号 + String projectPlanCode = remoteCodeRuleService.selectCodeRuleCode("1010"); + if (StringUtils.isBlank(projectPlanCode)) { + throw new ServiceException("生成项目计划编号失败"); + } + newPlan.setProjectPlanCode(projectPlanCode); + + projectPlanMapper.insert(newPlan); + return newPlan.getProjectPlanId(); + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(ErpProjectInfo entity) { + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成等) + * + * @param processEvent 参数 + */ + @EventListener(condition = "#processEvent.flowCode.startsWith('htdd')") + public void processHandler(ProcessEvent processEvent) { + TenantHelper.dynamic(processEvent.getTenantId(), () -> { + log.info("当前任务执行了{}", processEvent.toString()); + ErpProjectInfo projectInfo = projectInfoMapper.selectById( + Convert.toLong(processEvent.getBusinessId()) + ); + if (projectInfo != null) { + projectInfo.setFlowStatus(processEvent.getStatus()); + Map params = processEvent.getParams(); + if (MapUtil.isNotEmpty(params)) { + // 办理人 + if (params.containsKey("handler")) { + // TODO: 处理办理人 + } + } + // 更新流程状态 + if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.WAITING.getStatus())) { + projectInfo.setProjectStatus(OAStatusEnum.APPROVING.getStatus()); + } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) { + projectInfo.setProjectStatus(OAStatusEnum.COMPLETED.getStatus()); + } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.INVALID.getStatus()) + || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.TERMINATION.getStatus())) { + projectInfo.setProjectStatus(OAStatusEnum.INVALID.getStatus()); + } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.BACK.getStatus()) + || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.CANCEL.getStatus())) { + projectInfo.setProjectStatus(OAStatusEnum.DRAFT.getStatus()); + } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.DRAFT.getStatus())) { + projectInfo.setProjectStatus(OAStatusEnum.DRAFT.getStatus()); + } + projectInfoMapper.updateById(projectInfo); + } + }); + } +} + diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractPaymentStageServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractPaymentStageServiceImpl.java index 2bb856ee..c1dbee0a 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractPaymentStageServiceImpl.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractPaymentStageServiceImpl.java @@ -78,7 +78,14 @@ public class ErpContractPaymentStageServiceImpl implements IErpContractPaymentSt .eq(bo.getPaymentStageId() != null, ErpContractPaymentStage::getPaymentStageId, bo.getPaymentStageId()) .like(StringUtils.isNotBlank(bo.getStageName()), ErpContractPaymentStage::getStageName, bo.getStageName()) .eq(StringUtils.isNotBlank(bo.getCollectionStage()), ErpContractPaymentStage::getCollectionStage, bo.getCollectionStage()) - .eq(bo.getPurchasePrice() != null, ErpContractPaymentStage::getPurchasePrice, bo.getPurchasePrice()) + .eq(bo.getRepaymentRate() != null, ErpContractPaymentStage::getRepaymentRate, bo.getRepaymentRate()) + .eq(bo.getExpectRepaymentDate() != null, ErpContractPaymentStage::getExpectRepaymentDate, bo.getExpectRepaymentDate()) + .eq(bo.getDelayDay() != null, ErpContractPaymentStage::getDelayDay, bo.getDelayDay()) + .eq(bo.getActualRepaymentDate() != null, ErpContractPaymentStage::getActualRepaymentDate, bo.getActualRepaymentDate()) + .eq(StringUtils.isNotBlank(bo.getRepaymentFlag()), ErpContractPaymentStage::getRepaymentFlag, bo.getRepaymentFlag()) + .eq(StringUtils.isNotBlank(bo.getReasonsExplanation()), ErpContractPaymentStage::getReasonsExplanation, bo.getReasonsExplanation()) + .eq(StringUtils.isNotBlank(bo.getScheduleRemark()), ErpContractPaymentStage::getScheduleRemark, bo.getScheduleRemark()) + .eq(bo.getRepaymentAmount() != null, ErpContractPaymentStage::getRepaymentAmount, bo.getRepaymentAmount()) .eq(bo.getSortOrder() != null, ErpContractPaymentStage::getSortOrder, bo.getSortOrder()); return lqw; } diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPurchaseServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPurchaseServiceImpl.java index ba17b413..baad4bc4 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPurchaseServiceImpl.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpProjectPurchaseServiceImpl.java @@ -110,7 +110,7 @@ public class ErpProjectPurchaseServiceImpl implements IErpProjectPurchaseService .selectAll(ErpProjectPurchase.class) .eq(ErpProjectPurchase::getDelFlag, "0") .eq(bo.getProjectId() != null, ErpProjectPurchase::getProjectId, bo.getProjectId()) - .eq(StringUtils.isNotBlank(bo.getProjectCode()), ErpProjectPurchase::getProjectCode, bo.getProjectCode()) + .like(StringUtils.isNotBlank(bo.getProjectCode()), ErpProjectPurchase::getProjectCode, bo.getProjectCode()) .eq(bo.getManagerId() != null, ErpProjectPurchase::getManagerId, bo.getManagerId()) .eq(bo.getChargeId() != null, ErpProjectPurchase::getChargeId, bo.getChargeId()) .eq(bo.getDeputyId() != null, ErpProjectPurchase::getDeputyId, bo.getDeputyId()) @@ -123,7 +123,11 @@ public class ErpProjectPurchaseServiceImpl implements IErpProjectPurchaseService .eq(bo.getSortOrder() != null, ErpProjectPurchase::getSortOrder, bo.getSortOrder()) .eq(bo.getRelationId() != null, ErpProjectPurchase::getRelationId, bo.getRelationId()) .eq(StringUtils.isNotBlank(bo.getSpareFlag()), ErpProjectPurchase::getSpareFlag, bo.getSpareFlag()) - .eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectPurchase::getActiveFlag, bo.getActiveFlag()); + .like(StringUtils.isNotBlank(bo.getPurchaseCode()), ErpProjectPurchase::getPurchaseCode, bo.getPurchaseCode()) + .like(StringUtils.isNotBlank(bo.getManagerName()), "u1.nick_name", bo.getManagerName()) + .like(StringUtils.isNotBlank(bo.getProjectName()), "p.project_name", bo.getProjectName()) + .eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectPurchase::getActiveFlag, bo.getActiveFlag()) + .orderByDesc(ErpProjectPurchase::getCreateTime); return lqw; } @@ -141,6 +145,18 @@ public class ErpProjectPurchaseServiceImpl implements IErpProjectPurchaseService validEntityBeforeSave(add); String purchaseCode = remoteCodeRuleService.selectCodeRuleCode("1007"); add.setPurchaseCode(purchaseCode); + + MPJLambdaWrapper lqw = JoinWrappers.lambda(ErpProjectPurchase.class) + .selectAll(ErpProjectPurchase.class) + .eq(ErpProjectPurchase::getProjectCode, bo.getProjectCode()) + .orderByDesc(ErpProjectPurchase::getVersion); + List purchases = baseMapper.selectList(lqw); + if (purchases.isEmpty()){ + add.setVersion(1L); + } else { + add.setVersion(purchases.get(0).getVersion() + 1); + } + boolean flag = baseMapper.insert(add) > 0; if (flag) { bo.setProjectPurchaseId(add.getProjectPurchaseId()); diff --git a/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpContractPaymentStageMapper.xml b/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpContractPaymentStageMapper.xml index 40d594ab..18465323 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpContractPaymentStageMapper.xml +++ b/ruoyi-modules/ruoyi-oa/src/main/resources/mapper/oa/erp/ErpContractPaymentStageMapper.xml @@ -13,7 +13,14 @@ payment_stage_id, stage_name, collection_stage, - purchase_price, + repayment_rate, + expect_repayment_date, + delay_day, + actual_repayment_date, + repayment_flag, + reasons_explanation, + schedule_remark, + repayment_amount, sort_order, remark, del_flag,