Commit c6041da3c41b639db5e4a0ca364a42a2cbda31cb

Authored by YunaiV
2 parents c40ea1ea 51b53d6e

Merge branch 'develop' of https://gitee.com/puhui999/ruoyi-vue-pro into develop

# Conflicts:
#	yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java
Showing 31 changed files with 435 additions and 505 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
... ... @@ -93,6 +93,8 @@ public interface LogRecordConstants {
93 93 String CRM_CONTRACT_DELETE_SUCCESS = "删除了合同【{{#contractName}}】";
94 94 String CRM_CONTRACT_TRANSFER_SUB_TYPE = "转移合同";
95 95 String CRM_CONTRACT_TRANSFER_SUCCESS = "将合同【{{#contract.name}}】的负责人从【{getAdminUserById{#contract.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
  96 + String CRM_CONTRACT_SUBMIT_SUB_TYPE = "提交合同审批";
  97 + String CRM_CONTRACT_SUBMIT_SUCCESS = "提交合同【{{#contractName}}】审批成功";
96 98  
97 99 // ======================= CRM_PRODUCT 产品 =======================
98 100  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java
... ... @@ -14,8 +14,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusiness
14 14 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;
15 15 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;
16 16 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;
17   -import cn.iocoder.yudao.module.crm.convert.businessstatus.CrmBusinessStatusConvert;
18   -import cn.iocoder.yudao.module.crm.convert.businessstatustype.CrmBusinessStatusTypeConvert;
  17 +import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusConvert;
  18 +import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusTypeConvert;
19 19 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
20 20 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
21 21 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
2 2  
3 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
4   -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO;
5 4 import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus;
6 5 import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction;
7 6 import com.mzt.logapi.starter.annotation.DiffLogField;
8 7 import io.swagger.v3.oas.annotations.media.Schema;
9 8 import jakarta.validation.constraints.NotNull;
  9 +import lombok.AllArgsConstructor;
10 10 import lombok.Data;
  11 +import lombok.NoArgsConstructor;
11 12 import org.springframework.format.annotation.DateTimeFormat;
12 13  
13 14 import java.math.BigDecimal;
14 15 import java.time.LocalDateTime;
15   -import java.util.ArrayList;
16 16 import java.util.List;
17 17  
18 18 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
... ... @@ -58,7 +58,6 @@ public class CrmBusinessSaveReqVO {
58 58 @DiffLogField(name = "商机金额")
59 59 private Integer price;
60 60  
61   - // TODO @lzxhqs:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题
62 61 @Schema(description = "整单折扣")
63 62 @DiffLogField(name = "整单折扣")
64 63 private Integer discountPercent;
... ... @@ -75,11 +74,29 @@ public class CrmBusinessSaveReqVO {
75 74 @InEnum(CrmBizEndStatus.class)
76 75 private Integer endStatus;
77 76  
78   - // TODO @lzxhqs:不设置默认 new ArrayList<>();一般 pojo 不设置默认值哈
79   - @Schema(description = "商机产品列表")
80   - private List<CrmBusinessProductSaveReqVO> products = new ArrayList<>();
81   -
82 77 @Schema(description = "联系人编号", example = "110")
83 78 private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段
84 79  
  80 + @Schema(description = "产品列表")
  81 + private List<CrmBusinessProductItem> productItems;
  82 +
  83 + @Schema(description = "产品列表")
  84 + @Data
  85 + @NoArgsConstructor
  86 + @AllArgsConstructor
  87 + public static class CrmBusinessProductItem {
  88 +
  89 + @Schema(description = "产品编号", example = "20529")
  90 + @NotNull(message = "产品编号不能为空")
  91 + private Long id;
  92 +
  93 + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
  94 + @NotNull(message = "产品数量不能为空")
  95 + private Integer count;
  96 +
  97 + @Schema(description = "产品折扣")
  98 + private Integer discountPercent;
  99 +
  100 + }
  101 +
85 102 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductPageReqVO.java deleted
1   -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product;
2   -
3   -import cn.iocoder.yudao.framework.common.pojo.PageParam;
4   -import io.swagger.v3.oas.annotations.media.Schema;
5   -import lombok.Data;
6   -import lombok.EqualsAndHashCode;
7   -import lombok.ToString;
8   -
9   -// TODO @lzxhqs:这个类,如果没用到,可以考虑删除哈
10   -@Schema(description = "管理后台 - 商机产品分页 Request VO")
11   -@Data
12   -@EqualsAndHashCode(callSuper = true)
13   -@ToString(callSuper = true)
14   -public class CrmBusinessProductPageReqVO extends PageParam {
15   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductRespVO.java deleted
1   -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product;
2   -
3   -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
4   -import io.swagger.v3.oas.annotations.media.Schema;
5   -import lombok.Data;
6   -
7   -@Schema(description = "管理后台 - 商机产品关联 Response VO")
8   -@Data
9   -@ExcelIgnoreUnannotated
10   -public class CrmBusinessProductRespVO {
11   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java deleted
1   -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product;
2   -
3   -import io.swagger.v3.oas.annotations.media.Schema;
4   -import jakarta.validation.constraints.NotEmpty;
5   -import jakarta.validation.constraints.NotNull;
6   -import lombok.Data;
7   -
8   -import java.math.BigDecimal;
9   -
10   -@Schema(description = "管理后台 - CRM 商机产品关联表 创建/更新 Request VO")
11   -@Data
12   -public class CrmBusinessProductSaveReqVO {
13   -
14   - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
15   - private Long id;
16   -
17   - @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
18   - @NotNull(message = "商机编号不能为空")
19   - private Long businessId;
20   -
21   - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
22   - @NotNull(message = "产品编号不能为空")
23   - private Long productId;
24   -
25   - @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
26   - @NotNull(message = "产品单价不能为空")
27   - private BigDecimal price;
28   -
29   - @Schema(description = "销售价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
30   - @NotNull(message = "销售价格不能为空")
31   - private BigDecimal salesPrice;
32   -
33   - @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
34   - @NotNull(message = "数量不能为空")
35   - private BigDecimal num;
36   -
37   - @Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
38   - @NotNull(message = "折扣不能为空")
39   - private BigDecimal discount;
40   -
41   - @Schema(description = "小计(折扣后价格)", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
42   - @NotNull(message = "小计(折扣后价格)不能为空")
43   - private BigDecimal subtotal;
44   -
45   - @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
46   - @NotEmpty(message = "单位不能为空")
47   - private String unit;
48   -
49   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
... ... @@ -8,15 +8,17 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
9 9 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
10 10 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
11   -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
  11 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
  12 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractRespVO;
  13 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
  14 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
12 15 import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert;
13 16 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
14   -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
15 17 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
16 18 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
  19 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;
17 20 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
18 21 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
19   -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService;
20 22 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
21 23 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
22 24 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
... ... @@ -30,7 +32,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
30 32 import jakarta.annotation.Resource;
31 33 import jakarta.servlet.http.HttpServletResponse;
32 34 import jakarta.validation.Valid;
33   -import org.springframework.context.annotation.Lazy;
34 35 import org.springframework.security.access.prepost.PreAuthorize;
35 36 import org.springframework.validation.annotation.Validated;
36 37 import org.springframework.web.bind.annotation.*;
... ... @@ -43,7 +44,6 @@ import java.util.stream.Stream;
43 44  
44 45 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
45 46 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
46   -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
47 47 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
48 48 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
49 49  
... ... @@ -62,11 +62,7 @@ public class CrmContractController {
62 62 @Resource
63 63 private CrmBusinessService businessService;
64 64 @Resource
65   - @Lazy
66   - private CrmBusinessProductService businessProductService;
67   - @Resource
68 65 private CrmProductService productService;
69   -
70 66 @Resource
71 67 private AdminUserApi adminUserApi;
72 68  
... ... @@ -105,22 +101,9 @@ public class CrmContractController {
105 101 return success(null);
106 102 }
107 103  
108   - // 2.1 拼接合同信息
  104 + // 2. 拼接合同信息
109 105 List<CrmContractRespVO> respVOList = buildContractDetailList(Collections.singletonList(contract));
110   - // 2.2 拼接产品信息
111   - // TODO @puhui999:下面这块也可以搞到 convert 里哈;可以在 ContractDetailList 加个开关,是不是查询商品信息;ps:jdk21 的方法不太能去用,因为 jdk8 项目要兼容;
112   - CrmContractRespVO respVO = respVOList.get(0);
113   - List<CrmBusinessProductDO> businessProductList = businessProductService.getBusinessProductListByContractId(id);
114   - Map<Long, CrmBusinessProductDO> businessProductMap = convertMap(businessProductList, CrmBusinessProductDO::getProductId);
115   - List<CrmProductDO> productList = productService.getProductListByIds(convertSet(businessProductList, CrmBusinessProductDO::getProductId));
116   - respVO.setProductItems(convertList(productList, product -> {
117   - CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class);
118   - findAndThen(businessProductMap, product.getId(), businessProduct -> {
119   - productItemRespVO.setCount(businessProduct.getCount()).setDiscountPercent(businessProduct.getDiscountPercent());
120   - });
121   - return productItemRespVO;
122   - }));
123   - return success(respVO);
  106 + return success(respVOList.get(0));
124 107 }
125 108  
126 109 @GetMapping("/page")
... ... @@ -147,8 +130,24 @@ public class CrmContractController {
147 130 HttpServletResponse response) throws IOException {
148 131 PageResult<CrmContractDO> pageResult = contractService.getContractPage(exportReqVO, getLoginUserId());
149 132 // 导出 Excel
150   - ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class,
151   - BeanUtils.toBean(pageResult.getList(), CrmContractExcelVO.class));
  133 + ExcelUtils.write(response, "合同.xls", "数据", CrmContractRespVO.class,
  134 + BeanUtils.toBean(pageResult.getList(), CrmContractRespVO.class));
  135 + }
  136 +
  137 + @PutMapping("/transfer")
  138 + @Operation(summary = "合同转移")
  139 + @PreAuthorize("@ss.hasPermission('crm:contract:update')")
  140 + public CommonResult<Boolean> transferContract(@Valid @RequestBody CrmContractTransferReqVO reqVO) {
  141 + contractService.transferContract(reqVO, getLoginUserId());
  142 + return success(true);
  143 + }
  144 +
  145 + @PutMapping("/submit")
  146 + @Operation(summary = "提交合同审批")
  147 + @PreAuthorize("@ss.hasPermission('crm:contract:update')")
  148 + public CommonResult<Boolean> submitContract(@RequestParam("id") Long id) {
  149 + contractService.submitContract(id, getLoginUserId());
  150 + return success(true);
152 151 }
153 152  
154 153 /**
... ... @@ -173,23 +172,15 @@ public class CrmContractController {
173 172 // 4. 获取商机
174 173 Map<Long, CrmBusinessDO> businessMap = convertMap(businessService.getBusinessList(convertSet(contractList,
175 174 CrmContractDO::getBusinessId)), CrmBusinessDO::getId);
176   - return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap);
177   - }
178   -
179   - @PutMapping("/transfer")
180   - @Operation(summary = "合同转移")
181   - @PreAuthorize("@ss.hasPermission('crm:contract:update')")
182   - public CommonResult<Boolean> transferContract(@Valid @RequestBody CrmContractTransferReqVO reqVO) {
183   - contractService.transferContract(reqVO, getLoginUserId());
184   - return success(true);
185   - }
186   -
187   - @PutMapping("/submit")
188   - @Operation(summary = "提交合同审批")
189   - @PreAuthorize("@ss.hasPermission('crm:contract:update')")
190   - public CommonResult<Boolean> submitContract(@RequestParam("id") Long id) {
191   - contractService.submitContract(id, getLoginUserId());
192   - return success(true);
  175 + // 5. 获取合同关联的商品
  176 + Map<Long, CrmContractProductDO> contractProductMap = null;
  177 + List<CrmProductDO> productList = null;
  178 + if (contractList.size() == 1) {
  179 + List<CrmContractProductDO> contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId());
  180 + contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId);
  181 + productList = productService.getProductListByIds(convertSet(contractProductList, CrmContractProductDO::getProductId));
  182 + }
  183 + return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList);
193 184 }
194 185  
195 186 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java deleted
1   -package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
2   -
3   -import com.alibaba.excel.annotation.ExcelProperty;
4   -import lombok.Data;
5   -
6   -import java.time.LocalDateTime;
7   -
8   -// TODO @puhui999:合并到 RespVO 里哈;
9   -/**
10   - * CRM 合同 Excel VO
11   - *
12   - * @author dhb52
13   - */
14   -@Data
15   -public class CrmContractExcelVO {
16   -
17   - @ExcelProperty("合同编号")
18   - private Long id;
19   -
20   - @ExcelProperty("合同名称")
21   - private String name;
22   -
23   - @ExcelProperty("客户编号")
24   - private Long customerId;
25   -
26   - @ExcelProperty("商机编号")
27   - private Long businessId;
28   -
29   - @ExcelProperty("工作流编号")
30   - private Long processInstanceId;
31   -
32   - @ExcelProperty("下单日期")
33   - private LocalDateTime orderDate;
34   -
35   - @ExcelProperty("负责人的用户编号")
36   - private Long ownerUserId;
37   -
38   - @ExcelProperty("合同编号")
39   - private String no;
40   -
41   - @ExcelProperty("开始时间")
42   - private LocalDateTime startTime;
43   -
44   - @ExcelProperty("结束时间")
45   - private LocalDateTime endTime;
46   -
47   - @ExcelProperty("合同金额")
48   - private Integer price;
49   -
50   - @ExcelProperty("整单折扣")
51   - private Integer discountPercent;
52   -
53   - @ExcelProperty("产品总金额")
54   - private Integer productPrice;
55   -
56   - @ExcelProperty("联系人编号")
57   - private Long contactId;
58   -
59   - @ExcelProperty("公司签约人")
60   - private Long signUserId;
61   -
62   - @ExcelProperty("最后跟进时间")
63   - private LocalDateTime contactLastTime;
64   -
65   - @ExcelProperty("备注")
66   - private String remark;
67   -
68   - @ExcelProperty("创建时间")
69   - private LocalDateTime createTime;
70   -
71   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
... ... @@ -21,7 +21,6 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
21 21 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
22 22 import io.swagger.v3.oas.annotations.Operation;
23 23 import io.swagger.v3.oas.annotations.Parameter;
24   -import io.swagger.v3.oas.annotations.Parameters;
25 24 import io.swagger.v3.oas.annotations.tags.Tag;
26 25 import jakarta.annotation.Resource;
27 26 import jakarta.servlet.http.HttpServletResponse;
... ... @@ -30,7 +29,6 @@ import org.mapstruct.ap.internal.util.Collections;
30 29 import org.springframework.security.access.prepost.PreAuthorize;
31 30 import org.springframework.validation.annotation.Validated;
32 31 import org.springframework.web.bind.annotation.*;
33   -import org.springframework.web.multipart.MultipartFile;
34 32  
35 33 import java.io.IOException;
36 34 import java.time.LocalDateTime;
... ... @@ -218,19 +216,13 @@ public class CrmCustomerController {
218 216 ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list);
219 217 }
220 218  
221   - // TODO @puhui999:updateSupport 要不改成前端必须传递;哈哈哈,代码排版看着有点乱;
222   - // TODO @puhui999:加一个选择负责人;允许空,空就进入公海;
223 219 @PostMapping("/import")
224 220 @Operation(summary = "导入客户")
225   - @Parameters({
226   - @Parameter(name = "file", description = "Excel 文件", required = true),
227   - @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
228   - })
229 221 @PreAuthorize("@ss.hasPermission('system:customer:import')")
230   - public CommonResult<CrmCustomerImportRespVO> importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport)
  222 + public CommonResult<CrmCustomerImportRespVO> importExcel(@Valid @RequestBody CrmCustomerImportReqVO importReqVO)
231 223 throws Exception {
232   - List<CrmCustomerImportExcelVO> list = ExcelUtils.read(file, CrmCustomerImportExcelVO.class);
233   - return success(customerService.importCustomerList(list, updateSupport, getLoginUserId()));
  224 + List<CrmCustomerImportExcelVO> list = ExcelUtils.read(importReqVO.getFile(), CrmCustomerImportExcelVO.class);
  225 + return success(customerService.importCustomerList(list, importReqVO));
234 226 }
235 227  
236 228 @PutMapping("/transfer")
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotNull;
  5 +import lombok.Builder;
  6 +import lombok.Data;
  7 +import org.springframework.web.multipart.MultipartFile;
  8 +
  9 +@Schema(description = "管理后台 - 客户导入 Request VO")
  10 +@Data
  11 +@Builder
  12 +public class CrmCustomerImportReqVO {
  13 +
  14 + @Schema(description = "Excel 文件", requiredMode = Schema.RequiredMode.REQUIRED)
  15 + @NotNull(message = "Excel 文件不能为空")
  16 + private MultipartFile file;
  17 +
  18 + @Schema(description = "是否支持更新", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  19 + @NotNull(message = "是否支持更新不能为空")
  20 + private Boolean updateSupport;
  21 +
  22 + @Schema(description = "负责人", example = "1")
  23 + private Long ownerUserId; // 为 null 则客户进入公海
  24 +
  25 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java
1   -package cn.iocoder.yudao.module.crm.convert.businessstatus;
  1 +package cn.iocoder.yudao.module.crm.convert.business;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java
1   -package cn.iocoder.yudao.module.crm.convert.businessstatustype;
  1 +package cn.iocoder.yudao.module.crm.convert.business;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessproduct/CrmBusinessProductConvert.java deleted
1   -package cn.iocoder.yudao.module.crm.convert.businessproduct;
2   -
3   -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO;
4   -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
5   -import org.mapstruct.Mapper;
6   -import org.mapstruct.factory.Mappers;
7   -
8   -// TODO @lzxhqs:看看是不是用 BeanUtils 替代了
9   -/**
10   - * @author lzxhqs
11   - * @version 1.0
12   - * @title CrmBusinessProductConvert
13   - * @description
14   - * @create 2024/1/12
15   - */
16   -@Mapper
17   -public interface CrmBusinessProductConvert {
18   - CrmBusinessProductConvert INSTANCE = Mappers.getMapper(CrmBusinessProductConvert.class);
19   -
20   - CrmBusinessProductDO convert(CrmBusinessProductSaveReqVO product);
21   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java
1 1 package cn.iocoder.yudao.module.crm.convert.contract;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
3 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 6 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractRespVO;
5 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
6 8 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
7 9 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
8 10 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
  11 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;
9 12 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  13 +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
10 14 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
11 15 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
12 16 import org.mapstruct.Mapper;
... ... @@ -34,7 +38,8 @@ public interface CrmContractConvert {
34 38  
35 39 default List<CrmContractRespVO> convertList(List<CrmContractDO> contractList, Map<Long, AdminUserRespDTO> userMap,
36 40 List<CrmCustomerDO> customerList, Map<Long, CrmContactDO> contactMap,
37   - Map<Long, CrmBusinessDO> businessMap) {
  41 + Map<Long, CrmBusinessDO> businessMap, Map<Long, CrmContractProductDO> contractProductMap,
  42 + List<CrmProductDO> productList) {
38 43 List<CrmContractRespVO> respVOList = BeanUtils.toBean(contractList, CrmContractRespVO.class);
39 44 // 拼接关联字段
40 45 Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
... ... @@ -46,7 +51,21 @@ public interface CrmContractConvert {
46 51 findAndThen(contactMap, contract.getContactId(), contact -> contract.setContactName(contact.getName()));
47 52 findAndThen(businessMap, contract.getBusinessId(), business -> contract.setBusinessName(business.getName()));
48 53 });
  54 + if (CollUtil.isNotEmpty(respVOList) && respVOList.size() == 1) {
  55 + setContractRespVOProductItems(respVOList.get(0), contractProductMap, productList);
  56 + }
49 57 return respVOList;
50 58 }
51 59  
  60 + default void setContractRespVOProductItems(CrmContractRespVO respVO, Map<Long, CrmContractProductDO> contractProductMap,
  61 + List<CrmProductDO> productList) {
  62 + respVO.setProductItems(CollectionUtils.convertList(productList, product -> {
  63 + CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class);
  64 + findAndThen(contractProductMap, product.getId(), contractProduct -> {
  65 + productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent());
  66 + });
  67 + return productItemRespVO;
  68 + }));
  69 + }
  70 +
52 71 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
1 1 package cn.iocoder.yudao.module.crm.dal.dataobject.business;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4   -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
5 4 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
6   -import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
7 5 import com.baomidou.mybatisplus.annotation.KeySequence;
8 6 import com.baomidou.mybatisplus.annotation.TableId;
9 7 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -41,19 +39,10 @@ public class CrmBusinessProductDO extends BaseDO {
41 39 * 关联 {@link CrmProductDO#getId()}
42 40 */
43 41 private Long productId;
44   - // TODO 芋艿:需要在看下 CRM
45   - /**
46   - * 合同编号
47   - *
48   - * 关联 {@link CrmContractDO#getId()}
49   - */
50   - private Long contractId;
51   -
52 42 /**
53 43 * 产品单价
54 44 */
55 45 private Integer price;
56   -
57 46 /**
58 47 * 销售价格, 单位:分
59 48 */
... ... @@ -71,11 +60,4 @@ public class CrmBusinessProductDO extends BaseDO {
71 60 */
72 61 private Integer totalPrice;
73 62  
74   - /**
75   - * 单位
76   - *
77   - * 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT}
78   - */
79   - private Integer unit;
80   -
81 63 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.dal.dataobject.contract;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
  5 +import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +/**
  11 + * 合同产品关联表 DO
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@TableName("crm_contract_product")
  16 +@KeySequence("crm_contract_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class CrmContractProductDO extends BaseDO {
  24 +
  25 + /**
  26 + * 主键
  27 + */
  28 + @TableId
  29 + private Long id;
  30 + /**
  31 + * 产品编号
  32 + *
  33 + * 关联 {@link CrmProductDO#getId()}
  34 + */
  35 + private Long productId;
  36 + /**
  37 + * 合同编号
  38 + *
  39 + * 关联 {@link CrmContractDO#getId()}
  40 + */
  41 + private Long contractId;
  42 + /**
  43 + * 产品单价
  44 + */
  45 + private Integer price;
  46 + /**
  47 + * 销售价格, 单位:分
  48 + */
  49 + private Integer salesPrice;
  50 + /**
  51 + * 数量
  52 + */
  53 + private Integer count;
  54 + /**
  55 + * 折扣
  56 + */
  57 + private Integer discountPercent;
  58 + /**
  59 + * 总计价格(折扣后价格)
  60 + */
  61 + private Integer totalPrice;
  62 +
  63 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java deleted
1   -/**
2   - * 合同
3   - */
4   -package cn.iocoder.yudao.module.crm.dal.dataobject.contract;
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java
... ... @@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business;
2 2  
3 3  
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 6 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
6 7 import org.apache.ibatis.annotations.Mapper;
7 8  
  9 +import java.util.List;
  10 +
8 11 /**
9 12 * 商机产品 Mapper
10 13 *
... ... @@ -21,4 +24,8 @@ public interface CrmBusinessProductMapper extends BaseMapperX&lt;CrmBusinessProduct
21 24 return selectOne(CrmBusinessProductDO::getBusinessId, id);
22 25 }
23 26  
  27 + default List<CrmBusinessProductDO> selectListByBusinessId(Long businessId) {
  28 + return selectList(new LambdaQueryWrapperX<CrmBusinessProductDO>().eq(CrmBusinessProductDO::getBusinessId, businessId));
  29 + }
  30 +
24 31 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.dal.mysql.contract;
  2 +
  3 +
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;
  7 +import org.apache.ibatis.annotations.Mapper;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * 合同产品 Mapper
  13 + *
  14 + * @author HUIHUI
  15 + */
  16 +@Mapper
  17 +public interface CrmContractProductMapper extends BaseMapperX<CrmContractProductDO> {
  18 +
  19 + default void deleteByContractId(Long contractId) { // TODO @lzxhqs:第一个方法,和类之间最好空一行;
  20 + delete(CrmContractProductDO::getContractId, contractId);
  21 + }
  22 +
  23 + default CrmContractProductDO selectByContractId(Long contractId) {
  24 + return selectOne(CrmContractProductDO::getContractId, contractId);
  25 + }
  26 +
  27 + default List<CrmContractProductDO> selectListByContractId(Long contractId) {
  28 + return selectList(new LambdaQueryWrapperX<CrmContractProductDO>().eq(CrmContractProductDO::getContractId, contractId));
  29 + }
  30 +
  31 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java
... ... @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.dal.mysql.product;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5   -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 5 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
7 6 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
8 7 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
... ... @@ -10,9 +9,6 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
10 9 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
11 10 import org.apache.ibatis.annotations.Mapper;
12 11  
13   -import java.util.Collection;
14   -import java.util.List;
15   -
16 12 /**
17 13 * CRM 产品 Mapper
18 14 *
... ... @@ -38,9 +34,4 @@ public interface CrmProductMapper extends BaseMapperX&lt;CrmProductDO&gt; {
38 34 return selectOne(CrmProductDO::getNo, no);
39 35 }
40 36  
41   - // TODO @puhui999:selectBatchIds
42   - default List<CrmProductDO> selectListByIds(Collection<Long> ids) {
43   - return selectList(new LambdaQueryWrapperX<CrmProductDO>().in(CrmProductDO::getId, ids));
44   - }
45   -
46 37 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java deleted
1   -package cn.iocoder.yudao.module.crm.service.business;
2   -
3   -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
4   -
5   -import java.util.List;
6   -
7   -/**
8   - * 商机产品关联表 Service 接口
9   - *
10   - * @author lzxhqs
11   - */
12   -public interface CrmBusinessProductService {
13   -
14   - /**
15   - * 批量新增商机产品关联数据
16   - *
17   - * @param list 商机产品集合
18   - */
19   - void createBusinessProductBatch(List<CrmBusinessProductDO> list);
20   -
21   - /**
22   - * 批量更新商机产品表
23   - *
24   - * @param list 商机产品数据集合
25   - */
26   - void updateBusinessProductBatch(List<CrmBusinessProductDO> list);
27   -
28   - /**
29   - * 批量删除
30   - *
31   - * @param list 需要删除的商机产品集合
32   - */
33   - void deleteBusinessProductBatch(List<CrmBusinessProductDO> list);
34   -
35   - /**
36   - * 根据商机编号,删除商机产品关联数据
37   - *
38   - * @param businessId 商机id
39   - */
40   - void deleteBusinessProductByBusinessId(Long businessId);
41   -
42   - /**
43   - * 根据商机编号,获取商机产品关联数据集合
44   - *
45   - * @param businessId 商机编号
46   - */
47   - List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId);
48   -
49   - /**
50   - * 根据合同编号,获得合同关联的商品列表
51   - *
52   - * @param contractId 合同编号
53   - * @return 关联的商品列表
54   - */
55   - List<CrmBusinessProductDO> getBusinessProductListByContractId(Long contractId);
56   -
57   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.crm.service.business;
2   -
3   -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4   -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
5   -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
6   -import jakarta.annotation.Resource;
7   -import org.springframework.stereotype.Service;
8   -import org.springframework.validation.annotation.Validated;
9   -
10   -import java.util.List;
11   -
12   -/**
13   - * 商机产品关联表 Service 实现类
14   - *
15   - * @author lzxhqs
16   - */
17   -@Service
18   -@Validated
19   -public class CrmBusinessProductServiceImpl implements CrmBusinessProductService {
20   -
21   - @Resource
22   - private CrmBusinessProductMapper businessProductMapper;
23   -
24   - @Override
25   - public void createBusinessProductBatch(List<CrmBusinessProductDO> list) {
26   - businessProductMapper.insertBatch(list);
27   - }
28   -
29   - @Override
30   - public void updateBusinessProductBatch(List<CrmBusinessProductDO> list) {
31   - businessProductMapper.updateBatch(list);
32   - }
33   -
34   - // TODO @puhui999:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了;
35   - @Override
36   - public void deleteBusinessProductBatch(List<CrmBusinessProductDO> list) {
37   - businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list, CrmBusinessProductDO::getId));
38   - }
39   -
40   - @Override
41   - public void deleteBusinessProductByBusinessId(Long businessId) {
42   - businessProductMapper.deleteByBusinessId(businessId);
43   - }
44   -
45   - @Override
46   - public List<CrmBusinessProductDO> getBusinessProductListByContractId(Long contractId) {
47   - return businessProductMapper.selectList(CrmBusinessProductDO::getContractId, contractId);
48   - }
49   -
50   - @Override
51   - public List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId) {
52   - return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId);
53   - }
54   -
55   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
... ... @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi
7 7 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
9 9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  10 +import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
10 11 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
11 12 import jakarta.validation.Valid;
12 13  
... ... @@ -51,6 +52,21 @@ public interface CrmBusinessService {
51 52 void deleteBusiness(Long id);
52 53  
53 54 /**
  55 + * 商机转移
  56 + *
  57 + * @param reqVO 请求
  58 + * @param userId 用户编号
  59 + */
  60 + void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId);
  61 +
  62 + /**
  63 + * 更新商机关联商品
  64 + *
  65 + * @param updateProductReqBO 请求
  66 + */
  67 + void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO);
  68 +
  69 + /**
54 70 * 获得商机
55 71 *
56 72 * @param id 编号
... ... @@ -106,14 +122,6 @@ public interface CrmBusinessService {
106 122 PageResult<CrmBusinessDO> getBusinessPageByContact(CrmBusinessPageReqVO pageReqVO);
107 123  
108 124 /**
109   - * 商机转移
110   - *
111   - * @param reqVO 请求
112   - * @param userId 用户编号
113   - */
114   - void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId);
115   -
116   - /**
117 125 * 获取关联客户的商机数量
118 126 *
119 127 * @param customerId 客户编号
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
... ... @@ -5,25 +5,28 @@ import cn.hutool.core.collection.ListUtil;
5 5 import cn.hutool.core.util.ObjectUtil;
6 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  8 +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
8 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
9 10 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
10 11 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
11 12 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
12   -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO;
13 13 import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
14   -import cn.iocoder.yudao.module.crm.convert.businessproduct.CrmBusinessProductConvert;
15 14 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
16 15 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
17 16 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
  17 +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
18 18 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
  19 +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
19 20 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
20 21 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
21 22 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
  23 +import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
22 24 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
23 25 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
24 26 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
25 27 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
26 28 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  29 +import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
27 30 import com.mzt.logapi.context.LogRecordContext;
28 31 import com.mzt.logapi.service.impl.DiffParseFunction;
29 32 import com.mzt.logapi.starter.annotation.LogRecord;
... ... @@ -35,11 +38,12 @@ import org.springframework.validation.annotation.Validated;
35 38  
36 39 import java.util.Collection;
37 40 import java.util.List;
  41 +import java.util.Map;
  42 +import java.util.Set;
38 43  
39 44 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
40   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
41   -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS;
42   -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
  45 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  46 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
43 47 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
44 48  
45 49 /**
... ... @@ -53,9 +57,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
53 57  
54 58 @Resource
55 59 private CrmBusinessMapper businessMapper;
56   -
57 60 @Resource
58   - private CrmBusinessProductService businessProductService;
  61 + private CrmBusinessProductMapper businessProductMapper;
  62 +
59 63 @Resource
60 64 @Lazy // 延迟加载,避免循环依赖
61 65 private CrmContractService contractService;
... ... @@ -63,6 +67,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
63 67 private CrmPermissionService permissionService;
64 68 @Resource
65 69 private CrmContactBusinessService contactBusinessService;
  70 + @Resource
  71 + private CrmProductService productService;
66 72  
67 73 @Override
68 74 @Transactional(rollbackFor = Exception.class)
... ... @@ -71,12 +77,15 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
71 77 public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) {
72 78 createReqVO.setId(null);
73 79 // 1. 插入商机
74   - CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class)
75   - .setOwnerUserId(userId);
  80 + CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId);
76 81 businessMapper.insert(business);
77   - // TODO 商机待定:插入商机与产品的关联表;校验商品存在
78   - if (CollUtil.isNotEmpty(createReqVO.getProducts())) {
79   - createBusinessProducts(createReqVO.getProducts(), business.getId(), false);
  82 + // 1.2 插入商机关联商品
  83 + if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话
  84 + List<CrmBusinessProductDO> productList = convertBusinessProductList(createReqVO.getProductItems(), business.getId());
  85 + businessProductMapper.insertBatch(productList);
  86 + // 更新合同商品总金额
  87 + businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice(
  88 + getSumValue(productList, CrmBusinessProductDO::getTotalPrice, Integer::sum)));
80 89 }
81 90 // TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表
82 91 createContactBusiness(business.getId(), createReqVO.getContactId());
... ... @@ -92,13 +101,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
92 101 }
93 102  
94 103 // TODO @lzxhqs:CrmContactBusinessService 调用这个;这样逻辑才能收敛哈;
95   - /**
96   - * @param businessId 商机id
97   - * @param contactId 联系人id
98   - * @throws
99   - * @description 联系人与商机的关联
100   - * @author lzxhqs
101   - */
102 104 private void createContactBusiness(Long businessId, Long contactId) {
103 105 CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO();
104 106 contactBusiness.setBusinessId(businessId);
... ... @@ -106,37 +108,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
106 108 contactBusinessService.insert(contactBusiness);
107 109 }
108 110  
109   - // TODO @lzxhqs:这个方法注释格式不对;删除@description,然后把 插入商机产品关联表 作为方法注释;
110   - /**
111   - * 插入商机产品关联表
112   - *
113   - * @param products 产品集合
114   - * @param businessId 商机id
115   - * @param updateFlag 更新标识 true 代表更新
116   - * @author lzxhqs
117   - */
118   - private void createBusinessProducts(List<CrmBusinessProductSaveReqVO> products, Long businessId, Boolean updateFlag) {
119   - List<CrmBusinessProductDO> list = CollectionUtils.convertList(products, product ->
120   - CrmBusinessProductConvert.INSTANCE.convert(product).setBusinessId(businessId));
121   - if (Boolean.TRUE.equals(updateFlag)) {
122   -// 根据商机 id从商机产品关联表中获取已存在的数据集合
123   - List<CrmBusinessProductDO> oldProducts = businessProductService.getBusinessProductListByBusinessId(businessId);
124   - List<List<CrmBusinessProductDO>> diffList = CollectionUtils.diffList(oldProducts, list, (oldValue, newValue) ->
125   - ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId()));
126   - if (CollUtil.isNotEmpty(diffList.getFirst())) {
127   - businessProductService.createBusinessProductBatch(diffList.getFirst());
128   - }
129   - if (CollUtil.isNotEmpty(diffList.get(1))) {
130   - businessProductService.updateBusinessProductBatch(diffList.get(1));
131   - }
132   - if (CollUtil.isNotEmpty(diffList.get(2))) {
133   - businessProductService.deleteBusinessProductBatch(diffList.get(2));
134   - }
135   - } else {
136   - businessProductService.createBusinessProductBatch(list);
137   - }
138   - }
139   -
140 111 @Override
141 112 @Transactional(rollbackFor = Exception.class)
142 113 @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
... ... @@ -146,16 +117,12 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
146 117 // 1. 校验存在
147 118 CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId());
148 119  
149   - // 2. 更新商机
  120 + // 2.1 更新商机
150 121 CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class);
151 122 businessMapper.updateById(updateObj);
152   - // TODO 商机待定:插入商机与产品的关联表;校验商品存在
153   - // TODO @lzxhqs:createBusinessProducts 可以抽成两个方法,一个新增;一个修改,修改需要把 businessProductService.deleteByBusinessId(updateReqVO.getId()); 一起处理进去;
154   - if (CollUtil.isNotEmpty(updateReqVO.getProducts())) {
155   - createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId(), true);
156   - } else {
157   - businessProductService.deleteBusinessProductByBusinessId(updateReqVO.getId());
158   - }
  123 + // 2.2 更新商机关联商品
  124 + List<CrmBusinessProductDO> productList = convertBusinessProductList(updateReqVO.getProductItems(), updateObj.getId());
  125 + updateBusinessProduct(productList, updateObj.getId());
159 126  
160 127 // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
161 128 // 3. 记录操作日志上下文
... ... @@ -188,6 +155,43 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
188 155 LogRecordContext.putVariable("businessName", business.getName());
189 156 }
190 157  
  158 + private void updateBusinessProduct(List<CrmBusinessProductDO> newProductList, Long businessId) {
  159 + List<CrmBusinessProductDO> oldProducts = businessProductMapper.selectListByBusinessId(businessId);
  160 + List<List<CrmBusinessProductDO>> diffList = CollectionUtils.diffList(oldProducts, newProductList, (oldValue, newValue) -> {
  161 + boolean condition = ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId());
  162 + if (condition) {
  163 + newValue.setId(oldValue.getId()); // 更新需要原始编号
  164 + }
  165 + return condition;
  166 + });
  167 + if (CollUtil.isNotEmpty(diffList.get(0))) {
  168 + businessProductMapper.insertBatch(diffList.get(0));
  169 + }
  170 + if (CollUtil.isNotEmpty(diffList.get(1))) {
  171 + businessProductMapper.updateBatch(diffList.get(1));
  172 + }
  173 + if (CollUtil.isNotEmpty(diffList.get(2))) {
  174 + businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId));
  175 + }
  176 + }
  177 +
  178 + private List<CrmBusinessProductDO> convertBusinessProductList(List<CrmBusinessSaveReqVO.CrmBusinessProductItem> productItems, Long businessId) {
  179 + // 校验商品存在
  180 + Set<Long> productIds = convertSet(productItems, CrmBusinessSaveReqVO.CrmBusinessProductItem::getId);
  181 + List<CrmProductDO> productList = productService.getProductList(productIds);
  182 + if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) {
  183 + throw exception(PRODUCT_NOT_EXISTS);
  184 + }
  185 + Map<Long, CrmProductDO> productMap = convertMap(productList, CrmProductDO::getId);
  186 + return convertList(productItems, productItem -> {
  187 + CrmProductDO product = productMap.get(productItem.getId());
  188 + return BeanUtils.toBean(product, CrmBusinessProductDO.class)
  189 + .setId(null).setProductId(productItem.getId()).setBusinessId(businessId)
  190 + .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent())
  191 + .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent()));
  192 + });
  193 + }
  194 +
191 195 /**
192 196 * 删除校验合同是关联合同
193 197 *
... ... @@ -228,6 +232,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
228 232 LogRecordContext.putVariable("business", business);
229 233 }
230 234  
  235 + @Override
  236 + public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) {
  237 + // 更新商机关联商品
  238 + List<CrmBusinessProductDO> productList = convertBusinessProductList(
  239 + BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.CrmBusinessProductItem.class), updateProductReqBO.getId());
  240 + updateBusinessProduct(productList, updateProductReqBO.getId());
  241 + }
  242 +
231 243 //======================= 查询相关 =======================
232 244  
233 245 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.business.bo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.Data;
  8 +import lombok.NoArgsConstructor;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 更新商机商品 Update Req BO
  14 + *
  15 + * @author HUIHUI
  16 + */
  17 +@Data
  18 +public class CrmBusinessUpdateProductReqBO {
  19 +
  20 + /**
  21 + * 商机编号
  22 + */
  23 + @NotNull(message = "商机编号不能为空")
  24 + private Long id;
  25 +
  26 + @NotEmpty(message = "产品列表不能为空")
  27 + private List<CrmBusinessProductItem> productItems;
  28 +
  29 + @Schema(description = "产品列表")
  30 + @Data
  31 + @NoArgsConstructor
  32 + @AllArgsConstructor
  33 + public static class CrmBusinessProductItem {
  34 +
  35 + @Schema(description = "产品编号", example = "20529")
  36 + @NotNull(message = "产品编号不能为空")
  37 + private Long id;
  38 +
  39 + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
  40 + @NotNull(message = "产品数量不能为空")
  41 + private Integer count;
  42 +
  43 + @Schema(description = "产品折扣")
  44 + private Integer discountPercent;
  45 +
  46 + }
  47 +
  48 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
... ... @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR
6 6 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
7 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;
9 10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
10 11 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
11 12 import jakarta.validation.Valid;
... ... @@ -134,4 +135,12 @@ public interface CrmContractService {
134 135 */
135 136 Long getContractCountByBusinessId(Long businessId);
136 137  
  138 + /**
  139 + * 获取合同商品列表
  140 + *
  141 + * @param contactId 合同编号
  142 + * @return 合同商品列表
  143 + */
  144 + List<CrmContractProductDO> getContractProductListByContractId(Long contactId);
  145 +
137 146 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
... ... @@ -11,20 +11,22 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
11 11 import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO;
12 12 import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
13 13 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
  14 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
14 15 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
15 16 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
16 17 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
17 18 import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert;
18   -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
19 19 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
  20 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;
20 21 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
21 22 import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
  23 +import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractProductMapper;
22 24 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
23 25 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
24 26 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
25 27 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
26   -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService;
27 28 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
  29 +import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
28 30 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
29 31 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
30 32 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
... ... @@ -63,12 +65,12 @@ public class CrmContractServiceImpl implements CrmContractService {
63 65  
64 66 @Resource
65 67 private CrmContractMapper contractMapper;
  68 + @Resource
  69 + private CrmContractProductMapper contractProductMapper;
66 70  
67 71 @Resource
68 72 private CrmPermissionService crmPermissionService;
69 73 @Resource
70   - private CrmBusinessProductService businessProductService;
71   - @Resource
72 74 private CrmProductService productService;
73 75 @Resource
74 76 private CrmCustomerService customerService;
... ... @@ -89,11 +91,18 @@ public class CrmContractServiceImpl implements CrmContractService {
89 91 // 1.1 插入合同
90 92 CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null);
91 93 contractMapper.insert(contract);
92   - // 1.2 插入商机关联商品
  94 + // 1.2 插入合同关联商品
93 95 if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话
94   - List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(createReqVO, contract.getId());
95   - businessProductService.createBusinessProductBatch(businessProduct);
  96 + List<CrmContractProductDO> productList = convertContractProductList(createReqVO, contract.getId());
  97 + contractProductMapper.insertBatch(productList);
96 98 // 更新合同商品总金额
  99 + contractMapper.updateById(new CrmContractDO().setId(contract.getId()).setProductPrice(
  100 + getSumValue(productList, CrmContractProductDO::getTotalPrice, Integer::sum)));
  101 + // 如果存在合同关联了商机则更新商机商品关联
  102 + if (contract.getBusinessId() != null) {
  103 + businessService.updateBusinessProduct(new CrmBusinessUpdateProductReqBO().setId(contract.getBusinessId())
  104 + .setProductItems(BeanUtils.toBean(createReqVO.getProductItems(), CrmBusinessUpdateProductReqBO.CrmBusinessProductItem.class)));
  105 + }
97 106 }
98 107  
99 108 // 2. 创建数据权限
... ... @@ -137,29 +146,29 @@ public class CrmContractServiceImpl implements CrmContractService {
137 146 if (CollUtil.isEmpty(updateReqVO.getProductItems())) {
138 147 return;
139 148 }
140   - List<CrmBusinessProductDO> newProductList = convertBusinessProductList(updateReqVO, contractId);
141   - List<CrmBusinessProductDO> oldProductList = businessProductService.getBusinessProductListByContractId(contractId);
142   - List<List<CrmBusinessProductDO>> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> {
143   - if (ObjUtil.notEqual(oldObj.getProductId(), newObj.getProductId())) {
144   - return false;
  149 + List<CrmContractProductDO> newProductList = convertContractProductList(updateReqVO, contractId);
  150 + List<CrmContractProductDO> oldProductList = contractProductMapper.selectListByContractId(contractId);
  151 + List<List<CrmContractProductDO>> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> {
  152 + boolean equal = ObjUtil.equal(oldObj.getProductId(), newObj.getProductId());
  153 + if (equal) {
  154 + newObj.setId(oldObj.getId()); // 设置一下老的编号更新时需要使用
145 155 }
146   - newObj.setId(oldObj.getId()); // 设置一下老的编号更新时需要使用
147   - return true;
  156 + return equal;
148 157 });
149   - if (CollUtil.isNotEmpty(diffList.getFirst())) {
150   - businessProductService.createBusinessProductBatch(diffList.getFirst());
  158 + if (CollUtil.isNotEmpty(diffList.get(0))) {
  159 + contractProductMapper.insertBatch(diffList.get(0));
151 160 }
152 161 if (CollUtil.isNotEmpty(diffList.get(1))) {
153   - businessProductService.updateBusinessProductBatch(diffList.get(1));
  162 + contractProductMapper.updateBatch(diffList.get(1));
154 163 }
155 164 if (CollUtil.isNotEmpty(diffList.get(2))) {
156   - businessProductService.deleteBusinessProductBatch(diffList.get(2));
  165 + contractProductMapper.deleteBatchIds(convertList(diffList.get(2), CrmContractProductDO::getId));
157 166 }
158 167 }
159 168  
160 169 // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum
161 170  
162   - private List<CrmBusinessProductDO> convertBusinessProductList(CrmContractSaveReqVO reqVO, Long contractId) {
  171 + private List<CrmContractProductDO> convertContractProductList(CrmContractSaveReqVO reqVO, Long contractId) {
163 172 // 校验商品存在
164 173 Set<Long> productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId);
165 174 List<CrmProductDO> productList = productService.getProductList(productIds);
... ... @@ -169,8 +178,8 @@ public class CrmContractServiceImpl implements CrmContractService {
169 178 Map<Long, CrmProductDO> productMap = convertMap(productList, CrmProductDO::getId);
170 179 return convertList(reqVO.getProductItems(), productItem -> {
171 180 CrmProductDO product = productMap.get(productItem.getId());
172   - return BeanUtils.toBean(product, CrmBusinessProductDO.class)
173   - .setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()).setContractId(contractId)
  181 + return BeanUtils.toBean(product, CrmContractProductDO.class)
  182 + .setId(null).setProductId(productItem.getId()).setContractId(contractId)
174 183 .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent())
175 184 .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent()));
176 185 });
... ... @@ -248,7 +257,8 @@ public class CrmContractServiceImpl implements CrmContractService {
248 257  
249 258 @Override
250 259 @Transactional(rollbackFor = Exception.class)
251   - // TODO @puhui999:操作日志;
  260 + @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_SUBMIT_SUB_TYPE, bizNo = "{{#id}}",
  261 + success = CRM_CONTRACT_SUBMIT_SUCCESS)
252 262 public void submitContract(Long id, Long userId) {
253 263 // 1. 校验合同是否在审批
254 264 CrmContractDO contract = validateContractExists(id);
... ... @@ -263,15 +273,43 @@ public class CrmContractServiceImpl implements CrmContractService {
263 273 // 3. 更新合同工作流编号
264 274 contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId)
265 275 .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus()));
  276 +
  277 + // 3. 记录日志
  278 + LogRecordContext.putVariable("contractName", contract.getName());
266 279 }
267 280  
268 281 @Override
269 282 public void updateContractAuditStatus(BpmResultListenerRespDTO event) {
270   - // TODO @puhui999:可能要判断下状态是否符合预期
  283 + // 判断下状态是否符合预期
  284 + if (!isEndResult(event.getResult())) {
  285 + return;
  286 + }
  287 + // 状态转换
  288 + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) {
  289 + event.setResult(CrmAuditStatusEnum.APPROVE.getStatus());
  290 + }
  291 + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) {
  292 + event.setResult(CrmAuditStatusEnum.REJECT.getStatus());
  293 + }
  294 + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) {
  295 + event.setResult(CrmAuditStatusEnum.CANCEL.getStatus());
  296 + }
  297 + // 更新合同状态
271 298 contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey()))
272 299 .setAuditStatus(event.getResult()));
273 300 }
274 301  
  302 + /**
  303 + * 判断该结果是否处于 End 最终结果
  304 + *
  305 + * @param result 结果
  306 + * @return 是否
  307 + */
  308 + public static boolean isEndResult(Integer result) {
  309 + return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(),
  310 + BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult());
  311 + }
  312 +
275 313 //======================= 查询相关 =======================
276 314  
277 315 @Override
... ... @@ -313,5 +351,11 @@ public class CrmContractServiceImpl implements CrmContractService {
313 351 public Long getContractCountByBusinessId(Long businessId) {
314 352 return contractMapper.selectCountByBusinessId(businessId);
315 353 }
  354 +
  355 + @Override
  356 + public List<CrmContractProductDO> getContractProductListByContractId(Long contactId) {
  357 + return contractProductMapper.selectListByContractId(contactId);
  358 + }
  359 +
316 360 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
317 361 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java
1 1 package cn.iocoder.yudao.module.crm.service.contract.listener;
2 2  
3   -import cn.hutool.core.util.ObjUtil;
4   -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
5 3 import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi;
6 4 import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO;
7   -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
8   -import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
9 5 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
10 6 import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl;
11 7 import jakarta.annotation.Resource;
... ... @@ -30,31 +26,7 @@ public class CrmContractResultListener implements BpmResultListenerApi {
30 26  
31 27 @Override
32 28 public void onEvent(BpmResultListenerRespDTO event) {
33   - boolean currentTaskFinish = isEndResult(event.getResult());
34   - if (!currentTaskFinish) {
35   - return;
36   - }
37   - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) {
38   - event.setResult(CrmAuditStatusEnum.APPROVE.getStatus());
39   - }
40   - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) {
41   - event.setResult(CrmAuditStatusEnum.REJECT.getStatus());
42   - }
43   - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) {
44   - event.setResult(CrmAuditStatusEnum.CANCEL.getStatus());
45   - }
46 29 contractService.updateContractAuditStatus(event);
47 30 }
48 31  
49   - /**
50   - * 判断该结果是否处于 End 最终结果
51   - *
52   - * @param result 结果
53   - * @return 是否
54   - */
55   - public static boolean isEndResult(Integer result) {
56   - return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(),
57   - BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult());
58   - }
59   -
60 32 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
... ... @@ -110,11 +110,10 @@ public interface CrmCustomerService {
110 110 * 批量导入客户
111 111 *
112 112 * @param importCustomers 导入客户列表
113   - * @param isUpdateSupport 是否支持更新
114   - * @param userId 用户编号
  113 + * @param importReqVO 请求
115 114 * @return 导入结果
116 115 */
117   - CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers, Boolean isUpdateSupport, Long userId);
  116 + CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers, CrmCustomerImportReqVO importReqVO);
118 117  
119 118 // ==================== 公海相关操作 ====================
120 119  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
... ... @@ -108,7 +108,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
108 108 /**
109 109 * 初始化客户的通用字段
110 110 *
111   - * @param customer 客户信息
  111 + * @param customer 客户信息
112 112 * @param ownerUserId 负责人编号
113 113 * @return 客户信息 DO
114 114 */
... ... @@ -244,8 +244,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
244 244 }
245 245  
246 246 @Override
247   - public CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers,
248   - Boolean isUpdateSupport, Long userId) {
  247 + public CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers, CrmCustomerImportReqVO importReqVO) {
249 248 if (CollUtil.isEmpty(importCustomers)) {
250 249 throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY);
251 250 }
... ... @@ -264,19 +263,21 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
264 263 CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName());
265 264 if (existCustomer == null) {
266 265 // 1.1 插入客户信息
267   - CrmCustomerDO customer = initCustomer(importCustomer, userId);
  266 + CrmCustomerDO customer = initCustomer(importCustomer, importReqVO.getOwnerUserId());
268 267 customerMapper.insert(customer);
269 268 respVO.getCreateCustomerNames().add(importCustomer.getName());
270   - // 1.2 创建数据权限
271   - permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
272   - .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
  269 + if (importReqVO.getOwnerUserId() != null) {
  270 + // 1.2 创建数据权限
  271 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
  272 + .setBizId(customer.getId()).setUserId(importReqVO.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
  273 + }
273 274 // 1.3 记录操作日志
274 275 getSelf().importCustomerLog(customer, false);
275 276 return;
276 277 }
277 278  
278 279 // 情况二:如果存在,判断是否允许更新
279   - if (!isUpdateSupport) {
  280 + if (!importReqVO.getUpdateSupport()) {
280 281 respVO.getFailureCustomerNames().put(importCustomer.getName(),
281 282 StrUtil.format(CUSTOMER_NAME_EXISTS.getMsg(), importCustomer.getName()));
282 283 return;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
... ... @@ -160,7 +160,7 @@ public class CrmProductServiceImpl implements CrmProductService {
160 160 if (CollUtil.isEmpty(ids)) {
161 161 return Collections.emptyList();
162 162 }
163   - return productMapper.selectListByIds(ids);
  163 + return productMapper.selectBatchIds(ids);
164 164 }
165 165  
166 166 }
... ...