From 4418a7bebce6497e63c19d1626f4b772f4025e7a Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 28 Jan 2024 20:15:11 +0800 Subject: [PATCH] =?UTF-8?q?CRM-=E5=90=88=E5=90=8C=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E6=96=B0=E5=A2=9E=E5=90=88=E5=90=8C=E6=8F=92=E5=85=A5?= =?UTF-8?q?=E5=85=B3=E8=81=94=E7=9A=84=E5=95=86=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 1 + .../contract/vo/CrmContractSaveReqVO.java | 5 +- .../contract/CrmContractServiceImpl.java | 93 ++++++++++++++++++- .../listener/CrmContractResultListener.java | 1 + 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 9db937aa6..b12990dd3 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -11,6 +11,7 @@ public interface ErrorCodeConstants { // ========== 合同管理 1-020-000-000 ========== ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在"); + ErrorCode CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_000_001, "更新合同失败,原因:禁止编辑"); // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java index 607aa08f5..ef90f2f2f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java @@ -89,6 +89,9 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "备注") private String remark; + @Schema(description = "审批状态", example = "1") + private Integer auditStatus; + @Schema(description = "产品列表") private List productItems; @@ -104,7 +107,7 @@ public class CrmContractSaveReqVO { @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") @NotNull(message = "产品数量不能为空") - private Long count; + private Integer count; @Schema(description = "产品折扣") private Integer discountPercent; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 8a1ad339e..59274b522 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; @@ -10,16 +12,23 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; +import cn.iocoder.yudao.module.crm.service.product.CrmProductService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; @@ -30,10 +39,14 @@ import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; /** * CRM 合同 Service 实现类 @@ -53,16 +66,25 @@ public class CrmContractServiceImpl implements CrmContractService { private CrmPermissionService crmPermissionService; @Resource private CrmBusinessProductService businessProductService; - + @Resource + private CrmProductService productService; @Resource private BpmProcessInstanceApi bpmProcessInstanceApi; + @Resource + private CrmCustomerService customerService; + @Resource + private CrmContactService contactService; + @Resource + private CrmBusinessService businessService; + @Resource + private AdminUserApi adminUserApi; @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}", success = CRM_CONTRACT_CREATE_SUCCESS) public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) { - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO + validateRelationDataExists(createReqVO); // 插入合同 CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); contractMapper.insert(contract); @@ -71,6 +93,10 @@ public class CrmContractServiceImpl implements CrmContractService { crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); + + // 插入商机关联商品 + List businessProduct = convertBusinessProductList(createReqVO); + businessProductService.insertBatch(businessProduct); // 4. 记录操作日志上下文 LogRecordContext.putVariable("contract", contract); return contract.getId(); @@ -83,12 +109,21 @@ public class CrmContractServiceImpl implements CrmContractService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContract(CrmContractSaveReqVO updateReqVO) { // TODO @合同待定:只有草稿、审批中,可以编辑; + if (ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) || + ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { + throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); + } + validateRelationDataExists(updateReqVO); // 校验存在 CrmContractDO oldContract = validateContractExists(updateReqVO.getId()); // 更新合同 CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class); contractMapper.updateById(updateObj); - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO + + // TODO puhui999: @芋艿:合同变更关联的商机后商品怎么处理? + //List businessProduct = convertBusinessProductList(updateReqVO); + //businessProductService.selectListByBusinessId() + //diffList() // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class)); @@ -97,8 +132,55 @@ public class CrmContractServiceImpl implements CrmContractService { // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum - // TODO @合同待定:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum + private List convertBusinessProductList(CrmContractSaveReqVO reqVO) { + // 校验商品存在 + Set productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId); + List productList = productService.getProductList(productIds); + if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { + throw exception(PRODUCT_NOT_EXISTS); + } + Map productMap = convertMap(productList, CrmProductDO::getId); + return convertList(reqVO.getProductItems(), productItem -> { + CrmBusinessProductDO businessProduct = BeanUtils.toBean(productMap.get(productItem.getId()), CrmBusinessProductDO.class); + businessProduct.setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()) + .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()).setTotalPrice(calculator(businessProduct)); + return businessProduct; + }); + } + /** + * 计算商品总价 + * + * @param businessProduct 关联商品 + * @return 商品总价 + */ + private Integer calculator(CrmBusinessProductDO businessProduct) { + int price = businessProduct.getPrice() * businessProduct.getCount(); + if (businessProduct.getDiscountPercent() == null) { + return price; + } + return MoneyUtils.calculateRatePriceFloor(price, (double) (businessProduct.getDiscountPercent() / 100)); + } + + /** + * 校验关联数据是否存在 + * + * @param reqVO 请求 + */ + private void validateRelationDataExists(CrmContractSaveReqVO reqVO) { + // 1. 校验客户 + if (reqVO.getCustomerId() != null && customerService.getCustomer(reqVO.getCustomerId()) == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + // 2. 校验负责人 + if (reqVO.getOwnerUserId() != null && adminUserApi.getUser(reqVO.getOwnerUserId()) == null) { + throw exception(USER_NOT_EXISTS); + } + // 4. 如果有关联商机,则需要校验存在 + if (reqVO.getBusinessId() != null && businessService.getBusiness(reqVO.getBusinessId()) == null) { + throw exception(BUSINESS_NOT_EXISTS); + } + } @Override @Transactional(rollbackFor = Exception.class) @@ -151,6 +233,7 @@ public class CrmContractServiceImpl implements CrmContractService { } @Override + @Transactional(rollbackFor = Exception.class) public void handleApprove(Long id, Long userId) { // 创建合同审批流程实例 String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index 078bbbd6a..e393c2664 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -1,4 +1,5 @@ package cn.iocoder.yudao.module.crm.service.contract.listener; public class CrmContractResultListener { + // TODO puhui999: @芋艿: 艿艿写一下这个,没研究明白哈哈 }