Commit 4418a7bebce6497e63c19d1626f4b772f4025e7a
1 parent
ea6752f1
CRM-合同:完善新增合同插入关联的商品
Showing
4 changed files
with
94 additions
and
6 deletions
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 { |
| 11 | 11 | |
| 12 | 12 | // ========== 合同管理 1-020-000-000 ========== |
| 13 | 13 | ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在"); |
| 14 | + ErrorCode CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_000_001, "更新合同失败,原因:禁止编辑"); | |
| 14 | 15 | |
| 15 | 16 | // ========== 线索管理 1-020-001-000 ========== |
| 16 | 17 | ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); | ... | ... |
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 { |
| 89 | 89 | @DiffLogField(name = "备注") |
| 90 | 90 | private String remark; |
| 91 | 91 | |
| 92 | + @Schema(description = "审批状态", example = "1") | |
| 93 | + private Integer auditStatus; | |
| 94 | + | |
| 92 | 95 | @Schema(description = "产品列表") |
| 93 | 96 | private List<CrmContractProductItem> productItems; |
| 94 | 97 | |
| ... | ... | @@ -104,7 +107,7 @@ public class CrmContractSaveReqVO { |
| 104 | 107 | |
| 105 | 108 | @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") |
| 106 | 109 | @NotNull(message = "产品数量不能为空") |
| 107 | - private Long count; | |
| 110 | + private Integer count; | |
| 108 | 111 | |
| 109 | 112 | @Schema(description = "产品折扣") |
| 110 | 113 | private Integer discountPercent; | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | +import cn.hutool.core.util.ObjUtil; | |
| 5 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; | |
| 6 | 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | 9 | import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; |
| 8 | 10 | 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 |
| 10 | 12 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; |
| 11 | 13 | import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; |
| 12 | 14 | import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; |
| 15 | +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; | |
| 13 | 16 | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| 17 | +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; | |
| 14 | 18 | import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; |
| 15 | 19 | import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; |
| 16 | 20 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 17 | 21 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 18 | 22 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 19 | 23 | import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; |
| 24 | +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; | |
| 25 | +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; | |
| 26 | +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | |
| 20 | 27 | import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; |
| 21 | 28 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 22 | 29 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 30 | +import cn.iocoder.yudao.module.crm.service.product.CrmProductService; | |
| 31 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 23 | 32 | import com.mzt.logapi.context.LogRecordContext; |
| 24 | 33 | import com.mzt.logapi.service.impl.DiffParseFunction; |
| 25 | 34 | import com.mzt.logapi.starter.annotation.LogRecord; |
| ... | ... | @@ -30,10 +39,14 @@ import org.springframework.validation.annotation.Validated; |
| 30 | 39 | |
| 31 | 40 | import java.util.Collection; |
| 32 | 41 | import java.util.List; |
| 42 | +import java.util.Map; | |
| 43 | +import java.util.Set; | |
| 33 | 44 | |
| 34 | 45 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 35 | -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS; | |
| 46 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 47 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | |
| 36 | 48 | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; |
| 49 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; | |
| 37 | 50 | |
| 38 | 51 | /** |
| 39 | 52 | * CRM 合同 Service 实现类 |
| ... | ... | @@ -53,16 +66,25 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 53 | 66 | private CrmPermissionService crmPermissionService; |
| 54 | 67 | @Resource |
| 55 | 68 | private CrmBusinessProductService businessProductService; |
| 56 | - | |
| 69 | + @Resource | |
| 70 | + private CrmProductService productService; | |
| 57 | 71 | @Resource |
| 58 | 72 | private BpmProcessInstanceApi bpmProcessInstanceApi; |
| 73 | + @Resource | |
| 74 | + private CrmCustomerService customerService; | |
| 75 | + @Resource | |
| 76 | + private CrmContactService contactService; | |
| 77 | + @Resource | |
| 78 | + private CrmBusinessService businessService; | |
| 79 | + @Resource | |
| 80 | + private AdminUserApi adminUserApi; | |
| 59 | 81 | |
| 60 | 82 | @Override |
| 61 | 83 | @Transactional(rollbackFor = Exception.class) |
| 62 | 84 | @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}", |
| 63 | 85 | success = CRM_CONTRACT_CREATE_SUCCESS) |
| 64 | 86 | public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) { |
| 65 | - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO | |
| 87 | + validateRelationDataExists(createReqVO); | |
| 66 | 88 | // 插入合同 |
| 67 | 89 | CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); |
| 68 | 90 | contractMapper.insert(contract); |
| ... | ... | @@ -71,6 +93,10 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 71 | 93 | crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) |
| 72 | 94 | .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId()) |
| 73 | 95 | .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); |
| 96 | + | |
| 97 | + // 插入商机关联商品 | |
| 98 | + List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(createReqVO); | |
| 99 | + businessProductService.insertBatch(businessProduct); | |
| 74 | 100 | // 4. 记录操作日志上下文 |
| 75 | 101 | LogRecordContext.putVariable("contract", contract); |
| 76 | 102 | return contract.getId(); |
| ... | ... | @@ -83,12 +109,21 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 83 | 109 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 84 | 110 | public void updateContract(CrmContractSaveReqVO updateReqVO) { |
| 85 | 111 | // TODO @合同待定:只有草稿、审批中,可以编辑; |
| 112 | + if (ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) || | |
| 113 | + ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { | |
| 114 | + throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); | |
| 115 | + } | |
| 116 | + validateRelationDataExists(updateReqVO); | |
| 86 | 117 | // 校验存在 |
| 87 | 118 | CrmContractDO oldContract = validateContractExists(updateReqVO.getId()); |
| 88 | 119 | // 更新合同 |
| 89 | 120 | CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class); |
| 90 | 121 | contractMapper.updateById(updateObj); |
| 91 | - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO | |
| 122 | + | |
| 123 | + // TODO puhui999: @芋艿:合同变更关联的商机后商品怎么处理? | |
| 124 | + //List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(updateReqVO); | |
| 125 | + //businessProductService.selectListByBusinessId() | |
| 126 | + //diffList() | |
| 92 | 127 | |
| 93 | 128 | // 3. 记录操作日志上下文 |
| 94 | 129 | LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class)); |
| ... | ... | @@ -97,8 +132,55 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 97 | 132 | |
| 98 | 133 | // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum |
| 99 | 134 | |
| 100 | - // TODO @合同待定:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum | |
| 135 | + private List<CrmBusinessProductDO> convertBusinessProductList(CrmContractSaveReqVO reqVO) { | |
| 136 | + // 校验商品存在 | |
| 137 | + Set<Long> productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId); | |
| 138 | + List<CrmProductDO> productList = productService.getProductList(productIds); | |
| 139 | + if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { | |
| 140 | + throw exception(PRODUCT_NOT_EXISTS); | |
| 141 | + } | |
| 142 | + Map<Long, CrmProductDO> productMap = convertMap(productList, CrmProductDO::getId); | |
| 143 | + return convertList(reqVO.getProductItems(), productItem -> { | |
| 144 | + CrmBusinessProductDO businessProduct = BeanUtils.toBean(productMap.get(productItem.getId()), CrmBusinessProductDO.class); | |
| 145 | + businessProduct.setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()) | |
| 146 | + .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()).setTotalPrice(calculator(businessProduct)); | |
| 147 | + return businessProduct; | |
| 148 | + }); | |
| 149 | + } | |
| 101 | 150 | |
| 151 | + /** | |
| 152 | + * 计算商品总价 | |
| 153 | + * | |
| 154 | + * @param businessProduct 关联商品 | |
| 155 | + * @return 商品总价 | |
| 156 | + */ | |
| 157 | + private Integer calculator(CrmBusinessProductDO businessProduct) { | |
| 158 | + int price = businessProduct.getPrice() * businessProduct.getCount(); | |
| 159 | + if (businessProduct.getDiscountPercent() == null) { | |
| 160 | + return price; | |
| 161 | + } | |
| 162 | + return MoneyUtils.calculateRatePriceFloor(price, (double) (businessProduct.getDiscountPercent() / 100)); | |
| 163 | + } | |
| 164 | + | |
| 165 | + /** | |
| 166 | + * 校验关联数据是否存在 | |
| 167 | + * | |
| 168 | + * @param reqVO 请求 | |
| 169 | + */ | |
| 170 | + private void validateRelationDataExists(CrmContractSaveReqVO reqVO) { | |
| 171 | + // 1. 校验客户 | |
| 172 | + if (reqVO.getCustomerId() != null && customerService.getCustomer(reqVO.getCustomerId()) == null) { | |
| 173 | + throw exception(CUSTOMER_NOT_EXISTS); | |
| 174 | + } | |
| 175 | + // 2. 校验负责人 | |
| 176 | + if (reqVO.getOwnerUserId() != null && adminUserApi.getUser(reqVO.getOwnerUserId()) == null) { | |
| 177 | + throw exception(USER_NOT_EXISTS); | |
| 178 | + } | |
| 179 | + // 4. 如果有关联商机,则需要校验存在 | |
| 180 | + if (reqVO.getBusinessId() != null && businessService.getBusiness(reqVO.getBusinessId()) == null) { | |
| 181 | + throw exception(BUSINESS_NOT_EXISTS); | |
| 182 | + } | |
| 183 | + } | |
| 102 | 184 | |
| 103 | 185 | @Override |
| 104 | 186 | @Transactional(rollbackFor = Exception.class) |
| ... | ... | @@ -151,6 +233,7 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 151 | 233 | } |
| 152 | 234 | |
| 153 | 235 | @Override |
| 236 | + @Transactional(rollbackFor = Exception.class) | |
| 154 | 237 | public void handleApprove(Long id, Long userId) { |
| 155 | 238 | // 创建合同审批流程实例 |
| 156 | 239 | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java