Commit 1ad5602a19a7f8080e89aea6254f2b031ace46ca

Authored by puhui999
2 parents 02b63de8 77f98c4d

Merge remote-tracking branch 'yudao/develop' into develop

# Conflicts:
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
Showing 47 changed files with 925 additions and 1134 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
@@ -22,8 +22,6 @@ public interface ErrorCodeConstants { @@ -22,8 +22,6 @@ public interface ErrorCodeConstants {
22 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); 22 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
23 ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除"); 23 ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除");
24 24
25 - // TODO @lilleo:商机状态、商机类型,都单独错误码段  
26 -  
27 // ========== 联系人管理 1-020-003-000 ========== 25 // ========== 联系人管理 1-020-003-000 ==========
28 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); 26 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
29 ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); 27 ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在");
@@ -68,6 +66,7 @@ public interface ErrorCodeConstants { @@ -68,6 +66,7 @@ public interface ErrorCodeConstants {
68 // ========== 产品 1_020_008_000 ========== 66 // ========== 产品 1_020_008_000 ==========
69 ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_020_008_000, "产品不存在"); 67 ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_020_008_000, "产品不存在");
70 ErrorCode PRODUCT_NO_EXISTS = new ErrorCode(1_020_008_001, "产品编号已存在"); 68 ErrorCode PRODUCT_NO_EXISTS = new ErrorCode(1_020_008_001, "产品编号已存在");
  69 + ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_020_008_002, "产品【{}】已禁用");
71 70
72 // ========== 产品分类 1_020_009_000 ========== 71 // ========== 产品分类 1_020_009_000 ==========
73 ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_020_009_000, "产品分类不存在"); 72 ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_020_009_000, "产品分类不存在");
@@ -77,12 +76,11 @@ public interface ErrorCodeConstants { @@ -77,12 +76,11 @@ public interface ErrorCodeConstants {
77 ErrorCode PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_020_009_004, "父分类不能是二级分类"); 76 ErrorCode PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_020_009_004, "父分类不能是二级分类");
78 ErrorCode product_CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_020_009_005, "存在子分类,无法删除"); 77 ErrorCode product_CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_020_009_005, "存在子分类,无法删除");
79 78
80 - // ========== 商机状态类型 1_020_010_000 ==========  
81 - ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_010_000, "商机状态类型不存在");  
82 - ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态类型名称已存在");  
83 -  
84 - // ========== 商机状态 1_020_011_000 ==========  
85 - ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_011_000, "商机状态不存在"); 79 + // ========== 商机状态 1_020_010_000 ==========
  80 + ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_010_000, "商机状态组不存在");
  81 + ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态组的名称已存在");
  82 + ErrorCode BUSINESS_STATUS_UPDATE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行更新");
  83 + ErrorCode BUSINESS_STATUS_DELETE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行删除");
86 84
87 // ========== 客户公海规则设置 1_020_012_000 ========== 85 // ========== 客户公海规则设置 1_020_012_000 ==========
88 ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用"); 86 ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用");
@@ -92,6 +90,4 @@ public interface ErrorCodeConstants { @@ -92,6 +90,4 @@ public interface ErrorCodeConstants {
92 ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在"); 90 ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在");
93 ErrorCode FOLLOW_UP_RECORD_DELETE_DENIED = new ErrorCode(1_020_013_001, "删除跟进记录失败,原因:没有权限"); 91 ErrorCode FOLLOW_UP_RECORD_DELETE_DENIED = new ErrorCode(1_020_013_001, "删除跟进记录失败,原因:没有权限");
94 92
95 - // ========== 待办消息 1_020_014_000 ==========  
96 -  
97 } 93 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http deleted
1 -### 请求 /transfer  
2 -PUT {{baseUrl}}/crm/business/transfer  
3 -Content-Type: application/json  
4 -Authorization: Bearer {{token}}  
5 -tenant-id: {{adminTenentId}}  
6 -  
7 -{  
8 - "id": 1,  
9 - "ownerUserId": 2,  
10 - "transferType": 2,  
11 - "permissionType": 2  
12 -}  
13 -  
14 -### 请求 /update  
15 -PUT {{baseUrl}}/crm/business/update  
16 -Content-Type: application/json  
17 -Authorization: Bearer {{token}}  
18 -tenant-id: {{adminTenentId}}  
19 -  
20 -{  
21 - "id": 1,  
22 - "name": "2",  
23 - "statusTypeId": 2,  
24 - "statusId": 2,  
25 - "customerId": 1  
26 -}  
27 -  
28 -### 请求 /get  
29 -GET {{baseUrl}}/crm/business/get?id=1024  
30 -Content-Type: application/json  
31 -Authorization: Bearer {{token}}  
32 -tenant-id: {{adminTenentId}}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.business; @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.business;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  7 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 9 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
8 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 10 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
@@ -10,15 +12,20 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi @@ -10,15 +12,20 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi
10 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; 12 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
11 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; 13 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
12 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; 14 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
13 -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;  
14 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; 15 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
  16 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
15 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; 17 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
16 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; 18 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
17 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 19 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  20 +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
18 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; 21 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
19 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService; 22 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
20 -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService;  
21 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 23 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
  24 +import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
  25 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  26 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  27 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  28 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
22 import io.swagger.v3.oas.annotations.Operation; 29 import io.swagger.v3.oas.annotations.Operation;
23 import io.swagger.v3.oas.annotations.Parameter; 30 import io.swagger.v3.oas.annotations.Parameter;
24 import io.swagger.v3.oas.annotations.tags.Tag; 31 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -30,13 +37,15 @@ import org.springframework.validation.annotation.Validated; @@ -30,13 +37,15 @@ import org.springframework.validation.annotation.Validated;
30 import org.springframework.web.bind.annotation.*; 37 import org.springframework.web.bind.annotation.*;
31 38
32 import java.io.IOException; 39 import java.io.IOException;
  40 +import java.util.Collections;
33 import java.util.List; 41 import java.util.List;
  42 +import java.util.Map;
  43 +import java.util.stream.Stream;
34 44
35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 45 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
36 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 46 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
37 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; 47 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
38 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
39 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 48 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
40 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 49 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
41 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 50 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
42 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; 51 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
@@ -52,9 +61,16 @@ public class CrmBusinessController { @@ -52,9 +61,16 @@ public class CrmBusinessController {
52 @Resource 61 @Resource
53 private CrmCustomerService customerService; 62 private CrmCustomerService customerService;
54 @Resource 63 @Resource
55 - private CrmBusinessStatusTypeService businessStatusTypeService; 64 + private CrmBusinessStatusService businessStatusTypeService;
56 @Resource 65 @Resource
57 private CrmBusinessStatusService businessStatusService; 66 private CrmBusinessStatusService businessStatusService;
  67 + @Resource
  68 + private CrmProductService productService;
  69 +
  70 + @Resource
  71 + private AdminUserApi adminUserApi;
  72 + @Resource
  73 + private DeptApi deptApi;
58 74
59 @PostMapping("/create") 75 @PostMapping("/create")
60 @Operation(summary = "创建商机") 76 @Operation(summary = "创建商机")
@@ -86,9 +102,25 @@ public class CrmBusinessController { @@ -86,9 +102,25 @@ public class CrmBusinessController {
86 @PreAuthorize("@ss.hasPermission('crm:business:query')") 102 @PreAuthorize("@ss.hasPermission('crm:business:query')")
87 public CommonResult<CrmBusinessRespVO> getBusiness(@RequestParam("id") Long id) { 103 public CommonResult<CrmBusinessRespVO> getBusiness(@RequestParam("id") Long id) {
88 CrmBusinessDO business = businessService.getBusiness(id); 104 CrmBusinessDO business = businessService.getBusiness(id);
89 - return success(BeanUtils.toBean(business, CrmBusinessRespVO.class)); 105 + return success(buildBusinessDetail(business));
  106 + }
  107 +
  108 + private CrmBusinessRespVO buildBusinessDetail(CrmBusinessDO business) {
  109 + if (business == null) {
  110 + return null;
  111 + }
  112 + CrmBusinessRespVO businessVO = buildBusinessDetailList(Collections.singletonList(business)).get(0);
  113 + // 拼接产品项
  114 + List<CrmBusinessProductDO> businessProducts = businessService.getBusinessProductListByBusinessId(businessVO.getId());
  115 + Map<Long, CrmProductDO> productMap = productService.getProductMap(
  116 + convertSet(businessProducts, CrmBusinessProductDO::getProductId));
  117 + businessVO.setProducts(BeanUtils.toBean(businessProducts, CrmBusinessRespVO.Product.class, businessProductVO ->
  118 + MapUtils.findAndThen(productMap, businessProductVO.getProductId(),
  119 + product -> businessProductVO.setProductNo(product.getNo()).setProductUnit(product.getUnit()))));
  120 + return businessVO;
90 } 121 }
91 122
  123 + // TODO 芋艿:处理下
92 @GetMapping("/list-by-ids") 124 @GetMapping("/list-by-ids")
93 @Operation(summary = "获得商机列表") 125 @Operation(summary = "获得商机列表")
94 @Parameter(name = "ids", description = "编号", required = true, example = "[1024]") 126 @Parameter(name = "ids", description = "编号", required = true, example = "[1024]")
@@ -97,6 +129,7 @@ public class CrmBusinessController { @@ -97,6 +129,7 @@ public class CrmBusinessController {
97 return success(BeanUtils.toBean(businessService.getBusinessList(ids, getLoginUserId()), CrmBusinessRespVO.class)); 129 return success(BeanUtils.toBean(businessService.getBusinessList(ids, getLoginUserId()), CrmBusinessRespVO.class));
98 } 130 }
99 131
  132 + // TODO 芋艿:处理下
100 @GetMapping("/simple-all-list") 133 @GetMapping("/simple-all-list")
101 @Operation(summary = "获得联系人的精简列表") 134 @Operation(summary = "获得联系人的精简列表")
102 @PreAuthorize("@ss.hasPermission('crm:contact:query')") 135 @PreAuthorize("@ss.hasPermission('crm:contact:query')")
@@ -113,7 +146,7 @@ public class CrmBusinessController { @@ -113,7 +146,7 @@ public class CrmBusinessController {
113 @PreAuthorize("@ss.hasPermission('crm:business:query')") 146 @PreAuthorize("@ss.hasPermission('crm:business:query')")
114 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPage(@Valid CrmBusinessPageReqVO pageVO) { 147 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPage(@Valid CrmBusinessPageReqVO pageVO) {
115 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(pageVO, getLoginUserId()); 148 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(pageVO, getLoginUserId());
116 - return success(buildBusinessDetailPageResult(pageResult)); 149 + return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal()));
117 } 150 }
118 151
119 @GetMapping("/page-by-customer") 152 @GetMapping("/page-by-customer")
@@ -123,7 +156,7 @@ public class CrmBusinessController { @@ -123,7 +156,7 @@ public class CrmBusinessController {
123 throw exception(CUSTOMER_NOT_EXISTS); 156 throw exception(CUSTOMER_NOT_EXISTS);
124 } 157 }
125 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); 158 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);
126 - return success(buildBusinessDetailPageResult(pageResult)); 159 + return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal()));
127 } 160 }
128 161
129 @GetMapping("/page-by-contact") 162 @GetMapping("/page-by-contact")
@@ -131,7 +164,7 @@ public class CrmBusinessController { @@ -131,7 +164,7 @@ public class CrmBusinessController {
131 @PreAuthorize("@ss.hasPermission('crm:business:query')") 164 @PreAuthorize("@ss.hasPermission('crm:business:query')")
132 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessContactPage(@Valid CrmBusinessPageReqVO pageReqVO) { 165 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessContactPage(@Valid CrmBusinessPageReqVO pageReqVO) {
133 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByContact(pageReqVO); 166 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByContact(pageReqVO);
134 - return success(buildBusinessDetailPageResult(pageResult)); 167 + return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal()));
135 } 168 }
136 169
137 @GetMapping("/export-excel") 170 @GetMapping("/export-excel")
@@ -141,29 +174,43 @@ public class CrmBusinessController { @@ -141,29 +174,43 @@ public class CrmBusinessController {
141 public void exportBusinessExcel(@Valid CrmBusinessPageReqVO exportReqVO, 174 public void exportBusinessExcel(@Valid CrmBusinessPageReqVO exportReqVO,
142 HttpServletResponse response) throws IOException { 175 HttpServletResponse response) throws IOException {
143 exportReqVO.setPageSize(PAGE_SIZE_NONE); 176 exportReqVO.setPageSize(PAGE_SIZE_NONE);
144 - PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(exportReqVO, getLoginUserId()); 177 + List<CrmBusinessDO> list = businessService.getBusinessPage(exportReqVO, getLoginUserId()).getList();
145 // 导出 Excel 178 // 导出 Excel
146 ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessRespVO.class, 179 ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessRespVO.class,
147 - buildBusinessDetailPageResult(pageResult).getList()); 180 + buildBusinessDetailList(list));
148 } 181 }
149 182
150 - /**  
151 - * 构建详细的商机分页结果  
152 - *  
153 - * @param pageResult 简单的商机分页结果  
154 - * @return 详细的商机分页结果  
155 - */  
156 - private PageResult<CrmBusinessRespVO> buildBusinessDetailPageResult(PageResult<CrmBusinessDO> pageResult) {  
157 - if (CollUtil.isEmpty(pageResult.getList())) {  
158 - return PageResult.empty(pageResult.getTotal()); 183 + private List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) {
  184 + if (CollUtil.isEmpty(list)) {
  185 + return Collections.emptyList();
159 } 186 }
160 - List<CrmBusinessStatusTypeDO> statusTypeList = businessStatusTypeService.getBusinessStatusTypeList(  
161 - convertSet(pageResult.getList(), CrmBusinessDO::getStatusTypeId));  
162 - List<CrmBusinessStatusDO> statusList = businessStatusService.getBusinessStatusList(  
163 - convertSet(pageResult.getList(), CrmBusinessDO::getStatusId));  
164 - List<CrmCustomerDO> customerList = customerService.getCustomerList(  
165 - convertSet(pageResult.getList(), CrmBusinessDO::getCustomerId));  
166 - return CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList); 187 + // 1.1 获取客户列表
  188 + Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap(
  189 + convertSet(list, CrmBusinessDO::getCustomerId));
  190 + // 1.2 获取创建人、负责人列表
  191 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(list,
  192 + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
  193 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  194 + // 1.3 获得商机状态组
  195 + Map<Long, CrmBusinessStatusTypeDO> statusTypeMap = businessStatusTypeService.getBusinessStatusTypeMap(
  196 + convertSet(list, CrmBusinessDO::getStatusTypeId));
  197 + Map<Long, CrmBusinessStatusDO> statusMap = businessStatusService.getBusinessStatusMap(
  198 + convertSet(list, CrmBusinessDO::getStatusId));
  199 + // 2. 拼接数据
  200 + return BeanUtils.toBean(list, CrmBusinessRespVO.class, businessVO -> {
  201 + // 2.1 设置客户名称
  202 + MapUtils.findAndThen(customerMap, businessVO.getCustomerId(), customer -> businessVO.setCustomerName(customer.getName()));
  203 + // 2.2 设置创建人、负责人名称
  204 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(businessVO.getCreator()),
  205 + user -> businessVO.setCreatorName(user.getNickname()));
  206 + MapUtils.findAndThen(userMap, businessVO.getOwnerUserId(), user -> {
  207 + businessVO.setOwnerUserName(user.getNickname());
  208 + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> businessVO.setOwnerUserDeptName(dept.getName()));
  209 + });
  210 + // 2.3 设置商机状态
  211 + MapUtils.findAndThen(statusTypeMap, businessVO.getStatusTypeId(), statusType -> businessVO.setStatusTypeName(statusType.getName()));
  212 + MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(status.getName()));
  213 + });
167 } 214 }
168 215
169 @PutMapping("/transfer") 216 @PutMapping("/transfer")
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.business;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  8 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  9 +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;
  10 +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
  11 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
  12 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
  13 +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
  14 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  15 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  16 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  17 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  18 +import io.swagger.v3.oas.annotations.Operation;
  19 +import io.swagger.v3.oas.annotations.Parameter;
  20 +import io.swagger.v3.oas.annotations.tags.Tag;
  21 +import jakarta.annotation.Resource;
  22 +import jakarta.validation.Valid;
  23 +import org.springframework.security.access.prepost.PreAuthorize;
  24 +import org.springframework.validation.annotation.Validated;
  25 +import org.springframework.web.bind.annotation.*;
  26 +
  27 +import java.util.Collection;
  28 +import java.util.List;
  29 +import java.util.Map;
  30 +
  31 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  32 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  33 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  34 +
  35 +@Tag(name = "管理后台 - CRM 商机状态")
  36 +@RestController
  37 +@RequestMapping("/crm/business-status")
  38 +@Validated
  39 +public class CrmBusinessStatusController {
  40 +
  41 + @Resource
  42 + private CrmBusinessStatusService businessStatusTypeService;
  43 +
  44 + @Resource
  45 + private AdminUserApi adminUserApi;
  46 + @Resource
  47 + private DeptApi deptApi;
  48 +
  49 + @PostMapping("/create")
  50 + @Operation(summary = "创建商机状态")
  51 + @PreAuthorize("@ss.hasPermission('crm:business-status:create')")
  52 + public CommonResult<Long> createBusinessStatus(@Valid @RequestBody CrmBusinessStatusSaveReqVO createReqVO) {
  53 + return success(businessStatusTypeService.createBusinessStatus(createReqVO));
  54 + }
  55 +
  56 + @PutMapping("/update")
  57 + @Operation(summary = "更新商机状态")
  58 + @PreAuthorize("@ss.hasPermission('crm:business-status:update')")
  59 + public CommonResult<Boolean> updateBusinessStatus(@Valid @RequestBody CrmBusinessStatusSaveReqVO updateReqVO) {
  60 + businessStatusTypeService.updateBusinessStatus(updateReqVO);
  61 + return success(true);
  62 + }
  63 +
  64 + @DeleteMapping("/delete")
  65 + @Operation(summary = "删除商机状态")
  66 + @Parameter(name = "id", description = "编号", required = true)
  67 + @PreAuthorize("@ss.hasPermission('crm:business-status:delete')")
  68 + public CommonResult<Boolean> deleteBusinessStatusType(@RequestParam("id") Long id) {
  69 + businessStatusTypeService.deleteBusinessStatusType(id);
  70 + return success(true);
  71 + }
  72 +
  73 + @GetMapping("/get")
  74 + @Operation(summary = "获得商机状态")
  75 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  76 + @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
  77 + public CommonResult<CrmBusinessStatusRespVO> getBusinessStatusType(@RequestParam("id") Long id) {
  78 + CrmBusinessStatusTypeDO statusType = businessStatusTypeService.getBusinessStatusType(id);
  79 + if (statusType == null) {
  80 + return success(null);
  81 + }
  82 + List<CrmBusinessStatusDO> statuses = businessStatusTypeService.getBusinessStatusListByTypeId(id);
  83 + return success(BeanUtils.toBean(statusType, CrmBusinessStatusRespVO.class,
  84 + statusTypeVO -> statusTypeVO.setStatuses(BeanUtils.toBean(statuses, CrmBusinessStatusRespVO.Status.class))));
  85 + }
  86 +
  87 + @GetMapping("/page")
  88 + @Operation(summary = "获得商机状态分页")
  89 + @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
  90 + public CommonResult<PageResult<CrmBusinessStatusRespVO>> getBusinessStatusPage(@Valid PageParam pageReqVO) {
  91 + // 1. 查询数据
  92 + PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);
  93 + if (CollUtil.isEmpty(pageResult.getList())) {
  94 + return success(PageResult.empty(pageResult.getTotal()));
  95 + }
  96 + // 2. 拼接数据
  97 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  98 + convertSet(pageResult.getList(), statusType -> Long.parseLong(statusType.getCreator())));
  99 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
  100 + convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds, Collection::stream));
  101 + return success(BeanUtils.toBean(pageResult, CrmBusinessStatusRespVO.class, statusTypeVO -> {
  102 + statusTypeVO.setCreator(userMap.get(NumberUtils.parseLong(statusTypeVO.getCreator())).getNickname());
  103 + statusTypeVO.setDeptNames(convertList(statusTypeVO.getDeptIds(),
  104 + deptId -> deptMap.containsKey(deptId) ? deptMap.get(deptId).getName() : null));
  105 + }));
  106 + }
  107 +
  108 + @GetMapping("/type-simple-list")
  109 + @Operation(summary = "获得商机状态组列表")
  110 + public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusTypeSimpleList() {
  111 + List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypeList();
  112 + // 过滤掉部门不匹配的
  113 + Long deptId = adminUserApi.getUser(getLoginUserId()).getDeptId();
  114 + list.removeIf(statusType -> CollUtil.isNotEmpty(statusType.getDeptIds()) && !statusType.getDeptIds().contains(deptId));
  115 + return success(BeanUtils.toBean(list, CrmBusinessStatusRespVO.class));
  116 + }
  117 +
  118 + @GetMapping("/status-simple-list")
  119 + @Operation(summary = "获得商机状态列表")
  120 + @Parameter(name = "typeId", description = "商机状态组", required = true, example = "1024")
  121 + public CommonResult<List<CrmBusinessStatusRespVO.Status>> getBusinessStatusSimpleList(@RequestParam("typeId") Long typeId) {
  122 + List<CrmBusinessStatusDO> list = businessStatusTypeService.getBusinessStatusListByTypeId(typeId);
  123 + return success(BeanUtils.toBean(list, CrmBusinessStatusRespVO.Status.class));
  124 + }
  125 +
  126 +}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business;  
2 -  
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
5 -import cn.iocoder.yudao.framework.common.pojo.PageParam;  
6 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
9 -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;  
10 -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;  
11 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;  
12 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;  
13 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO;  
14 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;  
15 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;  
16 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;  
17 -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusConvert;  
18 -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusTypeConvert;  
19 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;  
20 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;  
21 -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;  
22 -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService;  
23 -import cn.iocoder.yudao.module.system.api.dept.DeptApi;  
24 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
25 -import io.swagger.v3.oas.annotations.Operation;  
26 -import io.swagger.v3.oas.annotations.Parameter;  
27 -import io.swagger.v3.oas.annotations.tags.Tag;  
28 -import jakarta.annotation.Resource;  
29 -import jakarta.servlet.http.HttpServletResponse;  
30 -import jakarta.validation.Valid;  
31 -import org.springframework.security.access.prepost.PreAuthorize;  
32 -import org.springframework.validation.annotation.Validated;  
33 -import org.springframework.web.bind.annotation.*;  
34 -  
35 -import java.io.IOException;  
36 -import java.util.Collection;  
37 -import java.util.List;  
38 -import java.util.Set;  
39 -  
40 -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;  
41 -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;  
42 -  
43 -@Tag(name = "管理后台 - CRM 商机状态类型")  
44 -@RestController  
45 -@RequestMapping("/crm/business-status-type")  
46 -@Validated  
47 -public class CrmBusinessStatusTypeController {  
48 -  
49 - @Resource  
50 - private CrmBusinessStatusTypeService businessStatusTypeService;  
51 -  
52 - @Resource  
53 - private CrmBusinessStatusService businessStatusService;  
54 -  
55 - @Resource  
56 - private DeptApi deptApi;  
57 -  
58 - @PostMapping("/create")  
59 - @Operation(summary = "创建商机状态类型")  
60 - @PreAuthorize("@ss.hasPermission('crm:business-status-type:create')")  
61 - public CommonResult<Long> createBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO createReqVO) {  
62 - return success(businessStatusTypeService.createBusinessStatusType(createReqVO));  
63 - }  
64 -  
65 - @PutMapping("/update")  
66 - @Operation(summary = "更新商机状态类型")  
67 - @PreAuthorize("@ss.hasPermission('crm:business-status-type:update')")  
68 - public CommonResult<Boolean> updateBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO updateReqVO) {  
69 - businessStatusTypeService.updateBusinessStatusType(updateReqVO);  
70 - return success(true);  
71 - }  
72 -  
73 - @DeleteMapping("/delete")  
74 - @Operation(summary = "删除商机状态类型")  
75 - @Parameter(name = "id", description = "编号", required = true)  
76 - @PreAuthorize("@ss.hasPermission('crm:business-status-type:delete')")  
77 - public CommonResult<Boolean> deleteBusinessStatusType(@RequestParam("id") Long id) {  
78 - businessStatusTypeService.deleteBusinessStatusType(id);  
79 - return success(true);  
80 - }  
81 -  
82 - @GetMapping("/get")  
83 - @Operation(summary = "获得商机状态类型")  
84 - @Parameter(name = "id", description = "编号", required = true, example = "1024")  
85 - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")  
86 - public CommonResult<CrmBusinessStatusTypeRespVO> getBusinessStatusType(@RequestParam("id") Long id) {  
87 - CrmBusinessStatusTypeDO statusType = businessStatusTypeService.getBusinessStatusType(id);  
88 - // 处理状态回显  
89 - // TODO @lzxhqs:可以在 businessStatusService 加个 getBusinessStatusListByTypeId 方法,直接返回 List<CrmBusinessStatusDO> 哈,常用的,尽量封装个简单易懂的方法,不用追求绝对通用哈;  
90 - CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();  
91 - queryVO.setTypeId(id);  
92 - List<CrmBusinessStatusDO> statusList = businessStatusService.selectList(queryVO);  
93 - return success(CrmBusinessStatusTypeConvert.INSTANCE.convert(statusType, statusList));  
94 - }  
95 -  
96 - @GetMapping("/page")  
97 - @Operation(summary = "获得商机状态类型分页")  
98 - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")  
99 - public CommonResult<PageResult<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypePage(@Valid CrmBusinessStatusTypePageReqVO pageReqVO) {  
100 - PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);  
101 - // 处理部门回显  
102 - Set<Long> deptIds = CollectionUtils.convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds,Collection::stream);  
103 - List<DeptRespDTO> deptList = deptApi.getDeptList(deptIds);  
104 - return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult, deptList));  
105 - }  
106 -  
107 - @GetMapping("/export-excel")  
108 - @Operation(summary = "导出商机状态类型 Excel")  
109 - @PreAuthorize("@ss.hasPermission('crm:business-status-type:export')")  
110 - @OperateLog(type = EXPORT)  
111 - public void exportBusinessStatusTypeExcel(@Valid CrmBusinessStatusTypePageReqVO pageReqVO,  
112 - HttpServletResponse response) throws IOException {  
113 - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);  
114 - List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO).getList();  
115 - // 导出 Excel  
116 - ExcelUtils.write(response, "商机状态类型.xls", "数据", CrmBusinessStatusTypeRespVO.class,  
117 - BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class));  
118 - }  
119 -  
120 - @GetMapping("/get-simple-list")  
121 - @Operation(summary = "获得商机状态类型列表")  
122 - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")  
123 - public CommonResult<List<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypeList() {  
124 - CrmBusinessStatusTypeQueryVO queryVO = new CrmBusinessStatusTypeQueryVO();  
125 - queryVO.setStatus(CommonStatusEnum.ENABLE.getStatus());  
126 - List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.selectList(queryVO);  
127 - return success(BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class));  
128 - }  
129 -  
130 - // TODO @ljlleo 这个接口,是不是可以和 getBusinessStatusTypeList 合并成一个?  
131 - @GetMapping("/get-status-list")  
132 - @Operation(summary = "获得商机状态列表")  
133 - @PreAuthorize("@ss.hasPermission('crm:business-status:query')")  
134 - public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusListByTypeId(@RequestParam("typeId") Long typeId) {  
135 - CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();  
136 - queryVO.setTypeId(typeId);  
137 - List<CrmBusinessStatusDO> list = businessStatusService.selectList(queryVO);  
138 - return success(CrmBusinessStatusConvert.INSTANCE.convertList(list));  
139 - }  
140 -  
141 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessExcelVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;  
2 -  
3 -import com.alibaba.excel.annotation.ExcelProperty;  
4 -import lombok.Data;  
5 -  
6 -import java.math.BigDecimal;  
7 -import java.time.LocalDateTime;  
8 -import java.util.Set;  
9 -  
10 -/**  
11 - * 商机 Excel VO  
12 - *  
13 - * @author ljlleo  
14 - */  
15 -@Data  
16 -public class CrmBusinessExcelVO {  
17 -  
18 - @ExcelProperty("主键")  
19 - private Long id;  
20 -  
21 - @ExcelProperty("商机名称")  
22 - private String name;  
23 -  
24 - @ExcelProperty("商机状态类型编号")  
25 - private Long statusTypeId;  
26 -  
27 - @ExcelProperty("商机状态编号")  
28 - private Long statusId;  
29 -  
30 - @ExcelProperty("下次联系时间")  
31 - private LocalDateTime contactNextTime;  
32 -  
33 - @ExcelProperty("客户编号")  
34 - private Long customerId;  
35 -  
36 - @ExcelProperty("预计成交日期")  
37 - private LocalDateTime dealTime;  
38 -  
39 - @ExcelProperty("商机金额")  
40 - private BigDecimal price;  
41 -  
42 - @ExcelProperty("整单折扣")  
43 - private BigDecimal discountPercent;  
44 -  
45 - @ExcelProperty("产品总金额")  
46 - private BigDecimal productPrice;  
47 -  
48 - @ExcelProperty("备注")  
49 - private String remark;  
50 -  
51 - @ExcelProperty("负责人的用户编号")  
52 - private Long ownerUserId;  
53 -  
54 - @ExcelProperty("创建时间")  
55 - private LocalDateTime createTime;  
56 -  
57 - @ExcelProperty("只读权限的用户编号数组")  
58 - private Set<Long> roUserIds;  
59 -  
60 - @ExcelProperty("读写权限的用户编号数组")  
61 - private Set<Long> rwUserIds;  
62 -  
63 - @ExcelProperty("1赢单2输单3无效")  
64 - private Integer endStatus;  
65 -  
66 - @ExcelProperty("结束时的备注")  
67 - private String endRemark;  
68 -  
69 - @ExcelProperty("最后跟进时间")  
70 - private LocalDateTime contactLastTime;  
71 -  
72 - @ExcelProperty("跟进状态")  
73 - private Integer followUpStatus;  
74 -  
75 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; 1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
2 2
  3 +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
  4 +import com.alibaba.excel.annotation.ExcelProperty;
3 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
4 -import jakarta.validation.constraints.NotNull; 6 +import lombok.AllArgsConstructor;
5 import lombok.Data; 7 import lombok.Data;
6 -import org.springframework.format.annotation.DateTimeFormat; 8 +import lombok.NoArgsConstructor;
7 9
8 import java.math.BigDecimal; 10 import java.math.BigDecimal;
9 import java.time.LocalDateTime; 11 import java.time.LocalDateTime;
  12 +import java.util.List;
10 13
11 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;  
12 -  
13 -@Schema(description = "管理后台 - 商机 Response VO") 14 +@Schema(description = "管理后台 - CRM 商机 Response VO")
14 @Data 15 @Data
  16 +@ExcelIgnoreUnannotated
15 public class CrmBusinessRespVO { 17 public class CrmBusinessRespVO {
16 18
17 - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") 19 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
  20 + @ExcelProperty("编号")
18 private Long id; 21 private Long id;
19 22
20 @Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") 23 @Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
21 - @NotNull(message = "商机名称不能为空") 24 + @ExcelProperty("商机名称")
22 private String name; 25 private String name;
23 26
24 - @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")  
25 - @NotNull(message = "商机状态类型不能为空") 27 + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")
  28 + private Long customerId;
  29 + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
  30 + @ExcelProperty("客户名称")
  31 + private String customerName;
  32 +
  33 + @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example ="true")
  34 + @ExcelProperty("跟进状态")
  35 + private Boolean followUpStatus;
  36 +
  37 + @Schema(description = "最后跟进时间")
  38 + @ExcelProperty("最后跟进时间")
  39 + private LocalDateTime contactLastTime;
  40 +
  41 + @Schema(description = "下次联系时间")
  42 + @ExcelProperty("下次联系时间")
  43 + private LocalDateTime contactNextTime;
  44 +
  45 + @Schema(description = "负责人的用户编号", example = "25682")
  46 + @ExcelProperty("负责人的用户编号")
  47 + private Long ownerUserId;
  48 + @Schema(description = "负责人名字", example = "25682")
  49 + @ExcelProperty("负责人名字")
  50 + private String ownerUserName;
  51 + @Schema(description = "负责人部门")
  52 + @ExcelProperty("负责人部门")
  53 + private String ownerUserDeptName;
  54 +
  55 + @Schema(description = "商机状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
26 private Long statusTypeId; 56 private Long statusTypeId;
  57 + @Schema(description = "商机状组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中")
  58 + @ExcelProperty("商机状态组")
  59 + private String statusTypeName;
27 60
28 @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") 61 @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
29 - @NotNull(message = "商机状态不能为空")  
30 private Long statusId; 62 private Long statusId;
  63 + @Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "跟进中")
  64 + @ExcelProperty("商机状态")
  65 + private String statusName;
31 66
32 - @Schema(description = "下次联系时间")  
33 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
34 - private LocalDateTime contactNextTime; 67 + @Schema
  68 + @ExcelProperty("1赢单2输单3无效")
  69 + private Integer endStatus;
35 70
36 - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")  
37 - @NotNull(message = "客户不能为空")  
38 - private Long customerId; 71 + @ExcelProperty("结束时的备注")
  72 + private String endRemark;
39 73
40 @Schema(description = "预计成交日期") 74 @Schema(description = "预计成交日期")
41 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 75 + @ExcelProperty("预计成交日期")
42 private LocalDateTime dealTime; 76 private LocalDateTime dealTime;
43 77
44 - @Schema(description = "商机金额", example = "12371")  
45 - private Integer price; 78 + @Schema(description = "产品总金额", example = "12025")
  79 + @ExcelProperty("产品总金额")
  80 + private BigDecimal totalProductPrice;
46 81
47 - // TODO @ljileo:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题  
48 @Schema(description = "整单折扣") 82 @Schema(description = "整单折扣")
49 - private Integer discountPercent; 83 + @ExcelProperty("整单折扣")
  84 + private BigDecimal discountPercent;
50 85
51 - @Schema(description = "产品总金额", example = "12025")  
52 - private BigDecimal productPrice; 86 + @Schema(description = "商机总金额", example = "12371")
  87 + @ExcelProperty("商机总金额")
  88 + private BigDecimal totalPrice;
53 89
54 @Schema(description = "备注", example = "随便") 90 @Schema(description = "备注", example = "随便")
  91 + @ExcelProperty("备注")
55 private String remark; 92 private String remark;
56 93
  94 + @Schema(description = "创建人", example = "1024")
  95 + @ExcelProperty("创建人")
  96 + private String creator;
  97 + @Schema(description = "创建人名字", example = "芋道源码")
  98 + @ExcelProperty("创建人名字")
  99 + private String creatorName;
  100 +
57 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 101 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  102 + @ExcelProperty("创建时间")
58 private LocalDateTime createTime; 103 private LocalDateTime createTime;
59 104
60 - @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")  
61 - private String customerName; 105 + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
  106 + @ExcelProperty("更新时间")
  107 + private LocalDateTime updateTime;
62 108
63 - @Schema(description = "状态类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中")  
64 - private String statusTypeName; 109 + @Schema(description = "产品列表")
  110 + private List<Product> products;
65 111
66 - @Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "跟进中")  
67 - private String statusName; 112 + @Schema(description = "产品列表")
  113 + @Data
  114 + @NoArgsConstructor
  115 + @AllArgsConstructor
  116 + public static class Product {
  117 +
  118 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
  119 + private Long id;
  120 +
  121 + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
  122 + private Long productId;
  123 + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
  124 + private String productName;
  125 + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
  126 + private String productNo;
  127 + @Schema(description = "产品单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
  128 + private Integer productUnit;
  129 +
  130 + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
  131 + private BigDecimal productPrice;
  132 +
  133 + @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
  134 + private BigDecimal businessPrice;
  135 +
  136 + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
  137 + private Integer count;
  138 +
  139 + @Schema(description = "总计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
  140 + private BigDecimal totalPrice;
  141 +
  142 + }
68 143
69 } 144 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; 1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
2 2
3 -import cn.iocoder.yudao.framework.common.validation.InEnum;  
4 -import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus;  
5 import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction; 3 import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction;
  4 +import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFunction;
6 import com.mzt.logapi.starter.annotation.DiffLogField; 5 import com.mzt.logapi.starter.annotation.DiffLogField;
7 import io.swagger.v3.oas.annotations.media.Schema; 6 import io.swagger.v3.oas.annotations.media.Schema;
8 import jakarta.validation.constraints.NotNull; 7 import jakarta.validation.constraints.NotNull;
@@ -29,74 +28,68 @@ public class CrmBusinessSaveReqVO { @@ -29,74 +28,68 @@ public class CrmBusinessSaveReqVO {
29 @NotNull(message = "商机名称不能为空") 28 @NotNull(message = "商机名称不能为空")
30 private String name; 29 private String name;
31 30
32 - @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")  
33 - @DiffLogField(name = "商机状态")  
34 - @NotNull(message = "商机状态类型不能为空")  
35 - private Long statusTypeId;  
36 -  
37 - @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")  
38 - @DiffLogField(name = "商机状态")  
39 - @NotNull(message = "商机状态不能为空")  
40 - private Long statusId; 31 + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")
  32 + @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
  33 + @NotNull(message = "客户不能为空")
  34 + private Long customerId;
41 35
42 @Schema(description = "下次联系时间") 36 @Schema(description = "下次联系时间")
43 @DiffLogField(name = "下次联系时间") 37 @DiffLogField(name = "下次联系时间")
44 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 38 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
45 private LocalDateTime contactNextTime; 39 private LocalDateTime contactNextTime;
46 40
47 - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")  
48 - @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)  
49 - @NotNull(message = "客户不能为空")  
50 - private Long customerId; 41 + @Schema(description = "负责人用户编号", example = "14334")
  42 + @NotNull(message = "负责人不能为空")
  43 + @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME)
  44 + private Long ownerUserId;
  45 +
  46 + @Schema(description = "商机状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
  47 + @DiffLogField(name = "商机状态组")
  48 + @NotNull(message = "商机状态组不能为空")
  49 + private Long statusTypeId;
51 50
52 @Schema(description = "预计成交日期") 51 @Schema(description = "预计成交日期")
53 @DiffLogField(name = "预计成交日期") 52 @DiffLogField(name = "预计成交日期")
54 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 53 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
55 private LocalDateTime dealTime; 54 private LocalDateTime dealTime;
56 55
57 - @Schema(description = "商机金额", example = "12371")  
58 - @DiffLogField(name = "商机金额")  
59 - private Integer price;  
60 -  
61 @Schema(description = "整单折扣") 56 @Schema(description = "整单折扣")
62 @DiffLogField(name = "整单折扣") 57 @DiffLogField(name = "整单折扣")
63 - private Integer discountPercent;  
64 -  
65 - @Schema(description = "产品总金额", example = "12025")  
66 - @DiffLogField(name = "产品总金额")  
67 - private BigDecimal productPrice; 58 + @NotNull(message = "整单折扣不能为空")
  59 + private BigDecimal discountPercent;
68 60
69 @Schema(description = "备注", example = "随便") 61 @Schema(description = "备注", example = "随便")
70 @DiffLogField(name = "备注") 62 @DiffLogField(name = "备注")
71 private String remark; 63 private String remark;
72 64
73 - @Schema(description = "结束状态", example = "1")  
74 - @InEnum(CrmBizEndStatus.class)  
75 - private Integer endStatus;  
76 -  
77 @Schema(description = "联系人编号", example = "110") 65 @Schema(description = "联系人编号", example = "110")
78 private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段 66 private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段
79 67
80 @Schema(description = "产品列表") 68 @Schema(description = "产品列表")
81 - private List<Item> items; 69 + private List<Product> products;
82 70
83 @Schema(description = "产品列表") 71 @Schema(description = "产品列表")
84 @Data 72 @Data
85 @NoArgsConstructor 73 @NoArgsConstructor
86 @AllArgsConstructor 74 @AllArgsConstructor
87 - public static class Item { 75 + public static class Product {
88 76
89 @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") 77 @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
90 @NotNull(message = "产品编号不能为空") 78 @NotNull(message = "产品编号不能为空")
91 - private Long id; 79 + private Long productId;
  80 +
  81 + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
  82 + @NotNull(message = "产品单价不能为空")
  83 + private BigDecimal productPrice;
  84 +
  85 + @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
  86 + @NotNull(message = "合同价格不能为空")
  87 + private BigDecimal businessPrice;
92 88
93 @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") 89 @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
94 @NotNull(message = "产品数量不能为空") 90 @NotNull(message = "产品数量不能为空")
95 private Integer count; 91 private Integer count;
96 92
97 - @Schema(description = "产品折扣")  
98 - private Integer discountPercent;  
99 -  
100 } 93 }
101 94
102 } 95 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusPageReqVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;  
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 -@Schema(description = "管理后台 - 商机状态分页 Request VO")  
10 -@Data  
11 -@EqualsAndHashCode(callSuper = true)  
12 -@ToString(callSuper = true)  
13 -public class CrmBusinessStatusPageReqVO extends PageParam {  
14 -  
15 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusQueryVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import lombok.ToString;  
6 -  
7 -import java.util.Collection;  
8 -  
9 -@Schema(description = "管理后台 - 商机状态 Query VO")  
10 -@Data  
11 -@ToString(callSuper = true)  
12 -public class CrmBusinessStatusQueryVO {  
13 -  
14 - @Schema(description = "主键集合")  
15 - private Collection<Long> idList;  
16 -  
17 - @Schema(description = "状态类型编号")  
18 - private Long typeId;  
19 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusRespVO.java
1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status; 1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
2 2
3 -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;  
4 -import com.alibaba.excel.annotation.ExcelProperty;  
5 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.Data; 4 import lombok.Data;
7 5
  6 +import java.math.BigDecimal;
  7 +import java.time.LocalDateTime;
  8 +import java.util.List;
  9 +
8 @Schema(description = "管理后台 - 商机状态 Response VO") 10 @Schema(description = "管理后台 - 商机状态 Response VO")
9 @Data 11 @Data
10 -@ExcelIgnoreUnannotated  
11 public class CrmBusinessStatusRespVO { 12 public class CrmBusinessStatusRespVO {
12 13
13 - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899")  
14 - @ExcelProperty("主键") 14 + @Schema(description = "状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
15 private Long id; 15 private Long id;
16 16
17 - @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139")  
18 - @ExcelProperty("状态类型编号")  
19 - private Long typeId;  
20 -  
21 - @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")  
22 - @ExcelProperty("状态名") 17 + @Schema(description = "状态组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
23 private String name; 18 private String name;
24 19
25 - @Schema(description = "赢单率")  
26 - @ExcelProperty("赢单率")  
27 - private String percent; 20 + @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)
  21 + private List<Long> deptIds;
  22 + @Schema(description = "使用的部门名称", requiredMode = Schema.RequiredMode.REQUIRED)
  23 + private List<String> deptNames;
  24 +
  25 + @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED)
  26 + private String creator;
  27 +
  28 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  29 + private LocalDateTime createTime;
  30 +
  31 + @Schema(description = "状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
  32 + private List<Status> statuses;
  33 +
  34 + @Data
  35 + public static class Status {
  36 +
  37 + @Schema(description = "状态编号", example = "23899")
  38 + private Long id;
  39 +
  40 + @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
  41 + private String name;
  42 +
  43 + @Schema(description = "赢单率", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
  44 + private BigDecimal percent;
  45 +
  46 + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  47 + private Integer sort;
28 48
29 - @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
30 - @ExcelProperty("排序")  
31 - private Integer sort; 49 + }
32 50
33 } 51 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java
1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status; 1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 -import lombok.Data;  
5 - 4 +import jakarta.validation.Valid;
6 import jakarta.validation.constraints.NotEmpty; 5 import jakarta.validation.constraints.NotEmpty;
7 import jakarta.validation.constraints.NotNull; 6 import jakarta.validation.constraints.NotNull;
  7 +import lombok.Data;
8 8
9 -@Schema(description = "管理后台 - 商机状态新增/修改 Request VO") 9 +import java.math.BigDecimal;
  10 +import java.util.List;
  11 +
  12 +@Schema(description = "管理后台 - 商机状态组新增/修改 Request VO")
10 @Data 13 @Data
11 public class CrmBusinessStatusSaveReqVO { 14 public class CrmBusinessStatusSaveReqVO {
12 15
13 - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899") 16 + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
14 private Long id; 17 private Long id;
15 18
16 - @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139")  
17 - @NotNull(message = "状态类型编号不能为空")  
18 - private Long typeId;  
19 -  
20 - @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")  
21 - @NotEmpty(message = "状态名不能为空") 19 + @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
  20 + @NotEmpty(message = "状态类型名不能为空")
22 private String name; 21 private String name;
23 22
24 - // TODO @lzxhqs::percent 应该是 Integer;  
25 - @Schema(description = "赢单率")  
26 - private String percent; 23 + @Schema(description = "使用的部门编号")
  24 + private List<Long> deptIds;
  25 +
  26 + @Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
  27 + @NotEmpty(message = "商机状态集合不能为空")
  28 + @Valid
  29 + private List<Status> statuses;
  30 +
  31 + @Data
  32 + public static class Status {
  33 +
  34 + @Schema(description = "状态编号", example = "23899")
  35 + private Long id;
  36 +
  37 + @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
  38 + @NotEmpty(message = "状态名不能为空")
  39 + private String name;
  40 +
  41 + @Schema(description = "赢单率", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
  42 + @NotNull(message = "赢单率不能为空")
  43 + private BigDecimal percent;
  44 +
  45 + @Schema(description = "排序", hidden = true, example = "1")
  46 + private Integer sort;
27 47
28 - // TODO @lzxhqs:这个是不是不用前端新增和修改的时候传递,交给顺序计算出来,存储起来就好了;  
29 - @Schema(description = "排序")  
30 - private Integer sort; 48 + }
31 49
32 } 50 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypePageReqVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;  
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 -@Schema(description = "管理后台 - 商机状态类型分页 Request VO")  
10 -@Data  
11 -@EqualsAndHashCode(callSuper = true)  
12 -@ToString(callSuper = true)  
13 -public class CrmBusinessStatusTypePageReqVO extends PageParam {  
14 -  
15 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeQueryVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import lombok.ToString;  
6 -  
7 -import java.util.Collection;  
8 -  
9 -@Schema(description = "管理后台 - 商机状态类型 Query VO")  
10 -@Data  
11 -@ToString(callSuper = true)  
12 -public class CrmBusinessStatusTypeQueryVO {  
13 -  
14 - @Schema(description = "主键集合")  
15 - private Collection<Long> idList;  
16 -  
17 - @Schema(description = "状态")  
18 - private Integer status;  
19 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeRespVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;  
2 -  
3 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;  
4 -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;  
5 -import com.alibaba.excel.annotation.ExcelProperty;  
6 -import io.swagger.v3.oas.annotations.media.Schema;  
7 -import lombok.Data;  
8 -  
9 -import java.time.LocalDateTime;  
10 -import java.util.List;  
11 -  
12 -@Schema(description = "管理后台 - 商机状态类型 Response VO")  
13 -@Data  
14 -@ExcelIgnoreUnannotated  
15 -public class CrmBusinessStatusTypeRespVO {  
16 -  
17 - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")  
18 - @ExcelProperty("主键")  
19 - private Long id;  
20 -  
21 - @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")  
22 - @ExcelProperty("状态类型名")  
23 - private String name;  
24 -  
25 - @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)  
26 - @ExcelProperty("使用的部门编号")  
27 - private List<Long> deptIds;  
28 - @Schema(description = "使用的部门名称", requiredMode = Schema.RequiredMode.REQUIRED)  
29 - @ExcelProperty("使用的部门名称")  
30 - private List<String> deptNames;  
31 -  
32 - @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED)  
33 - @ExcelProperty("创建人")  
34 - private String creator;  
35 -  
36 - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)  
37 - @ExcelProperty("创建时间")  
38 - private LocalDateTime createTime;  
39 -  
40 - // TODO @ljlleo 字段后缀改成 statuses,保持和 deptIds 风格一致;CrmBusinessStatusDO 改成 VO 哈;一般不使用 do 直接返回  
41 - @Schema(description = "状态集合", requiredMode = Schema.RequiredMode.REQUIRED)  
42 - private List<CrmBusinessStatusDO> statusList;  
43 -  
44 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;  
2 -  
3 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;  
4 -import com.google.common.collect.Lists;  
5 -import io.swagger.v3.oas.annotations.media.Schema;  
6 -import lombok.Data;  
7 -  
8 -import jakarta.validation.constraints.NotEmpty;  
9 -import java.util.List;  
10 -  
11 -@Schema(description = "管理后台 - 商机状态类型新增/修改 Request VO")  
12 -@Data  
13 -public class CrmBusinessStatusTypeSaveReqVO {  
14 -  
15 - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")  
16 - private Long id;  
17 -  
18 - @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")  
19 - @NotEmpty(message = "状态类型名不能为空")  
20 - private String name;  
21 -  
22 - // TODO @lzxhqs: VO 里面,我们不使用默认值哈。这里 Lists.newArrayList() 看看怎么去掉。上面 deptIds 也是类似噢  
23 - @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)  
24 - private List<Long> deptIds = Lists.newArrayList();  
25 -  
26 - @Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED)  
27 - private List<CrmBusinessStatusSaveReqVO> statusList;  
28 -  
29 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
@@ -179,7 +179,7 @@ public class CrmContractController { @@ -179,7 +179,7 @@ public class CrmContractController {
179 if (contractList.size() == 1) { 179 if (contractList.size() == 1) {
180 List<CrmContractProductDO> contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId()); 180 List<CrmContractProductDO> contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId());
181 contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId); 181 contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId);
182 - productList = productService.getProductListByIds(convertSet(contractProductList, CrmContractProductDO::getProductId)); 182 + productList = productService.getProductList(convertSet(contractProductList, CrmContractProductDO::getProductId));
183 } 183 }
184 return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList); 184 return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList);
185 } 185 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java
1 package cn.iocoder.yudao.module.crm.controller.admin.product; 1 package cn.iocoder.yudao.module.crm.controller.admin.product;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.framework.common.pojo.PageParam; 6 import cn.iocoder.yudao.framework.common.pojo.PageParam;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 -import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 8 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  9 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 10 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
9 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 11 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
10 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; 12 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
11 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO; 13 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO;
12 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO; 14 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO;
13 -import cn.iocoder.yudao.module.crm.convert.product.CrmProductConvert;  
14 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; 15 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
15 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; 16 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
16 import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService; 17 import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService;
@@ -34,10 +35,9 @@ import java.util.Map; @@ -34,10 +35,9 @@ import java.util.Map;
34 import java.util.stream.Stream; 35 import java.util.stream.Stream;
35 36
36 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 37 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
37 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
38 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; 38 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
39 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 39 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
40 -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 40 +import static java.util.Collections.singletonList;
41 41
42 @Tag(name = "管理后台 - CRM 产品") 42 @Tag(name = "管理后台 - CRM 产品")
43 @RestController 43 @RestController
@@ -49,6 +49,7 @@ public class CrmProductController { @@ -49,6 +49,7 @@ public class CrmProductController {
49 private CrmProductService productService; 49 private CrmProductService productService;
50 @Resource 50 @Resource
51 private CrmProductCategoryService productCategoryService; 51 private CrmProductCategoryService productCategoryService;
  52 +
52 @Resource 53 @Resource
53 private AdminUserApi adminUserApi; 54 private AdminUserApi adminUserApi;
54 55
@@ -82,21 +83,30 @@ public class CrmProductController { @@ -82,21 +83,30 @@ public class CrmProductController {
82 @PreAuthorize("@ss.hasPermission('crm:product:query')") 83 @PreAuthorize("@ss.hasPermission('crm:product:query')")
83 public CommonResult<CrmProductRespVO> getProduct(@RequestParam("id") Long id) { 84 public CommonResult<CrmProductRespVO> getProduct(@RequestParam("id") Long id) {
84 CrmProductDO product = productService.getProduct(id); 85 CrmProductDO product = productService.getProduct(id);
  86 + return success(buildProductDetail(product));
  87 + }
  88 +
  89 + private CrmProductRespVO buildProductDetail(CrmProductDO product) {
85 if (product == null) { 90 if (product == null) {
86 - return success(null); 91 + return null;
87 } 92 }
88 - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(  
89 - SetUtils.asSet(Long.valueOf(product.getCreator()), product.getOwnerUserId()));  
90 - CrmProductCategoryDO category = productCategoryService.getProductCategory(product.getCategoryId());  
91 - return success(CrmProductConvert.INSTANCE.convert(product, userMap, category)); 93 + return buildProductDetailList(singletonList(product)).get(0);
  94 + }
  95 +
  96 + @GetMapping("/simple-list")
  97 + @Operation(summary = "获得产品精简列表", description = "只包含被开启的产品,主要用于前端的下拉选项")
  98 + public CommonResult<List<CrmProductRespVO>> getProductSimpleList() {
  99 + List<CrmProductDO> list = productService.getProductListByStatus(CommonStatusEnum.ENABLE.getStatus());
  100 + return success(convertList(list, product -> new CrmProductRespVO().setId(product.getId()).setName(product.getName())
  101 + .setUnit(product.getUnit()).setNo(product.getNo()).setPrice(product.getPrice())));
92 } 102 }
93 103
94 @GetMapping("/page") 104 @GetMapping("/page")
95 @Operation(summary = "获得产品分页") 105 @Operation(summary = "获得产品分页")
96 @PreAuthorize("@ss.hasPermission('crm:product:query')") 106 @PreAuthorize("@ss.hasPermission('crm:product:query')")
97 public CommonResult<PageResult<CrmProductRespVO>> getProductPage(@Valid CrmProductPageReqVO pageVO) { 107 public CommonResult<PageResult<CrmProductRespVO>> getProductPage(@Valid CrmProductPageReqVO pageVO) {
98 - PageResult<CrmProductDO> pageResult = productService.getProductPage(pageVO, getLoginUserId());  
99 - return success(new PageResult<>(getProductDetailList(pageResult.getList()), pageResult.getTotal())); 108 + PageResult<CrmProductDO> pageResult = productService.getProductPage(pageVO);
  109 + return success(new PageResult<>(buildProductDetailList(pageResult.getList()), pageResult.getTotal()));
100 } 110 }
101 111
102 @GetMapping("/export-excel") 112 @GetMapping("/export-excel")
@@ -106,21 +116,30 @@ public class CrmProductController { @@ -106,21 +116,30 @@ public class CrmProductController {
106 public void exportProductExcel(@Valid CrmProductPageReqVO exportReqVO, 116 public void exportProductExcel(@Valid CrmProductPageReqVO exportReqVO,
107 HttpServletResponse response) throws IOException { 117 HttpServletResponse response) throws IOException {
108 exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); 118 exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
109 - List<CrmProductDO> list = productService.getProductPage(exportReqVO, getLoginUserId()).getList(); 119 + List<CrmProductDO> list = productService.getProductPage(exportReqVO).getList();
110 // 导出 Excel 120 // 导出 Excel
111 ExcelUtils.write(response, "产品.xls", "数据", CrmProductRespVO.class, 121 ExcelUtils.write(response, "产品.xls", "数据", CrmProductRespVO.class,
112 - getProductDetailList(list)); 122 + buildProductDetailList(list));
113 } 123 }
114 124
115 - private List<CrmProductRespVO> getProductDetailList(List<CrmProductDO> list) { 125 + private List<CrmProductRespVO> buildProductDetailList(List<CrmProductDO> list) {
116 if (CollUtil.isEmpty(list)) { 126 if (CollUtil.isEmpty(list)) {
117 return Collections.emptyList(); 127 return Collections.emptyList();
118 } 128 }
  129 + // 1.1 获得用户信息
119 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( 130 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
120 convertSetByFlatMap(list, user -> Stream.of(Long.valueOf(user.getCreator()), user.getOwnerUserId()))); 131 convertSetByFlatMap(list, user -> Stream.of(Long.valueOf(user.getCreator()), user.getOwnerUserId())));
121 - List<CrmProductCategoryDO> productCategoryList = productCategoryService.getProductCategoryList( 132 + // 1.2 获得分类信息
  133 + Map<Long, CrmProductCategoryDO> categoryMap = productCategoryService.getProductCategoryMap(
122 convertSet(list, CrmProductDO::getCategoryId)); 134 convertSet(list, CrmProductDO::getCategoryId));
123 - return CrmProductConvert.INSTANCE.convertList(list, userMap, productCategoryList); 135 + // 2. 拼接数据
  136 + return BeanUtils.toBean(list, CrmProductRespVO.class, productVO -> {
  137 + // 2.1 设置用户信息
  138 + MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname()));
  139 + MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname()));
  140 + // 2.2 设置分类名称
  141 + MapUtils.findAndThen(categoryMap, productVO.getCategoryId(), category -> productVO.setCategoryName(category.getName()));
  142 + });
124 } 143 }
125 144
126 } 145 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java
@@ -8,6 +8,7 @@ import com.alibaba.excel.annotation.ExcelProperty; @@ -8,6 +8,7 @@ import com.alibaba.excel.annotation.ExcelProperty;
8 import io.swagger.v3.oas.annotations.media.Schema; 8 import io.swagger.v3.oas.annotations.media.Schema;
9 import lombok.Data; 9 import lombok.Data;
10 10
  11 +import java.math.BigDecimal;
11 import java.time.LocalDateTime; 12 import java.time.LocalDateTime;
12 13
13 @Schema(description = "管理后台 - CRM 产品 Response VO") 14 @Schema(description = "管理后台 - CRM 产品 Response VO")
@@ -34,7 +35,7 @@ public class CrmProductRespVO { @@ -34,7 +35,7 @@ public class CrmProductRespVO {
34 35
35 @Schema(description = "价格, 单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") 36 @Schema(description = "价格, 单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
36 @ExcelProperty("价格,单位:分") 37 @ExcelProperty("价格,单位:分")
37 - private Long price; 38 + private BigDecimal price;
38 39
39 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架") 40 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架")
40 @ExcelProperty(value = "单位", converter = DictConvert.class) 41 @ExcelProperty(value = "单位", converter = DictConvert.class)
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductSaveReqVO.java
@@ -7,6 +7,8 @@ import io.swagger.v3.oas.annotations.media.Schema; @@ -7,6 +7,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
7 import jakarta.validation.constraints.NotNull; 7 import jakarta.validation.constraints.NotNull;
8 import lombok.Data; 8 import lombok.Data;
9 9
  10 +import java.math.BigDecimal;
  11 +
10 @Schema(description = "管理后台 - CRM 产品创建/修改 Request VO") 12 @Schema(description = "管理后台 - CRM 产品创建/修改 Request VO")
11 @Data 13 @Data
12 public class CrmProductSaveReqVO { 14 public class CrmProductSaveReqVO {
@@ -28,10 +30,10 @@ public class CrmProductSaveReqVO { @@ -28,10 +30,10 @@ public class CrmProductSaveReqVO {
28 @DiffLogField(name = "单位", function = CrmProductUnitParseFunction.NAME) 30 @DiffLogField(name = "单位", function = CrmProductUnitParseFunction.NAME)
29 private Integer unit; 31 private Integer unit;
30 32
31 - @Schema(description = "价格, 单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") 33 + @Schema(description = "价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
32 @NotNull(message = "价格不能为空") 34 @NotNull(message = "价格不能为空")
33 @DiffLogField(name = "价格") 35 @DiffLogField(name = "价格")
34 - private Long price; 36 + private BigDecimal price;
35 37
36 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架") 38 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架")
37 @NotNull(message = "状态不能为空") 39 @NotNull(message = "状态不能为空")
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java
1 package cn.iocoder.yudao.module.crm.convert.business; 1 package cn.iocoder.yudao.module.crm.convert.business;
2 2
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 3 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
6 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;  
7 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; 4 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; 5 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
9 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;  
10 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;  
11 -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;  
12 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; 6 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
13 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; 7 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
14 import org.mapstruct.Mapper; 8 import org.mapstruct.Mapper;
@@ -16,9 +10,6 @@ import org.mapstruct.Mapping; @@ -16,9 +10,6 @@ import org.mapstruct.Mapping;
16 import org.mapstruct.factory.Mappers; 10 import org.mapstruct.factory.Mappers;
17 11
18 import java.util.List; 12 import java.util.List;
19 -import java.util.Map;  
20 -  
21 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
22 13
23 /** 14 /**
24 * 商机 Convert 15 * 商机 Convert
@@ -33,20 +24,6 @@ public interface CrmBusinessConvert { @@ -33,20 +24,6 @@ public interface CrmBusinessConvert {
33 @Mapping(target = "bizId", source = "reqVO.id") 24 @Mapping(target = "bizId", source = "reqVO.id")
34 CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId); 25 CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
35 26
36 - default PageResult<CrmBusinessRespVO> convertPage(PageResult<CrmBusinessDO> pageResult, List<CrmCustomerDO> customerList,  
37 - List<CrmBusinessStatusTypeDO> statusTypeList, List<CrmBusinessStatusDO> statusList) {  
38 - PageResult<CrmBusinessRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmBusinessRespVO.class);  
39 - // 拼接关联字段  
40 - Map<Long, String> customerMap = convertMap(customerList, CrmCustomerDO::getId, CrmCustomerDO::getName);  
41 - Map<Long, String> statusTypeMap = convertMap(statusTypeList, CrmBusinessStatusTypeDO::getId, CrmBusinessStatusTypeDO::getName);  
42 - Map<Long, String> statusMap = convertMap(statusList, CrmBusinessStatusDO::getId, CrmBusinessStatusDO::getName);  
43 - voPageResult.getList().forEach(type -> type  
44 - .setCustomerName(customerMap.get(type.getCustomerId()))  
45 - .setStatusTypeName(statusTypeMap.get(type.getStatusTypeId()))  
46 - .setStatusName(statusMap.get(type.getStatusId())));  
47 - return voPageResult;  
48 - }  
49 -  
50 @Mapping(target = "id", source = "reqBO.bizId") 27 @Mapping(target = "id", source = "reqBO.bizId")
51 CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO); 28 CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO);
52 29
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java deleted
1 -package cn.iocoder.yudao.module.crm.convert.business;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;  
5 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;  
6 -import org.mapstruct.Mapper;  
7 -import org.mapstruct.factory.Mappers;  
8 -  
9 -import java.util.List;  
10 -  
11 -/**  
12 - * 商机状态 Convert  
13 - *  
14 - * @author ljlleo  
15 - */  
16 -@Mapper  
17 -public interface CrmBusinessStatusConvert {  
18 -  
19 - CrmBusinessStatusConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusConvert.class);  
20 -  
21 - List<CrmBusinessStatusRespVO> convertList(List<CrmBusinessStatusDO> list);  
22 -  
23 - PageResult<CrmBusinessStatusRespVO> convertPage(PageResult<CrmBusinessStatusDO> page);  
24 -  
25 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java deleted
1 -package cn.iocoder.yudao.module.crm.convert.business;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;  
5 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;  
6 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;  
7 -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;  
8 -import org.mapstruct.Mapper;  
9 -import org.mapstruct.factory.Mappers;  
10 -  
11 -import java.util.List;  
12 -import java.util.Map;  
13 -  
14 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
15 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
16 -  
17 -// TODO @lzxhqs:看看是不是用 BeanUtils 替代了  
18 -/**  
19 - * 商机状态类型 Convert  
20 - *  
21 - * @author ljlleo  
22 - */  
23 -@Mapper  
24 -public interface CrmBusinessStatusTypeConvert {  
25 -  
26 - CrmBusinessStatusTypeConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusTypeConvert.class);  
27 -  
28 - CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean);  
29 -  
30 - PageResult<CrmBusinessStatusTypeRespVO> convertPage(PageResult<CrmBusinessStatusTypeDO> page);  
31 -  
32 - default PageResult<CrmBusinessStatusTypeRespVO> convertPage(PageResult<CrmBusinessStatusTypeDO> page, List<DeptRespDTO> deptList) {  
33 - PageResult<CrmBusinessStatusTypeRespVO> pageResult = convertPage(page);  
34 - // 拼接关联字段  
35 - Map<Long, String> deptMap = convertMap(deptList, DeptRespDTO::getId, DeptRespDTO::getName);  
36 - pageResult.getList().forEach(type -> type.setDeptNames(convertList(type.getDeptIds(), deptMap::get)));  
37 - return pageResult;  
38 - }  
39 -  
40 - default CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean, List<CrmBusinessStatusDO> statusList) {  
41 - return convert(bean).setStatusList(statusList);  
42 - }  
43 -  
44 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/product/CrmProductConvert.java deleted
1 -package cn.iocoder.yudao.module.crm.convert.product;  
2 -  
3 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
4 -import cn.iocoder.yudao.framework.common.util.collection.MapUtils;  
5 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
6 -import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO;  
7 -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;  
8 -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;  
9 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
10 -import org.mapstruct.Mapper;  
11 -import org.mapstruct.factory.Mappers;  
12 -  
13 -import java.util.List;  
14 -import java.util.Map;  
15 -import java.util.Optional;  
16 -  
17 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;  
18 -  
19 -/**  
20 - * 产品 Convert  
21 - *  
22 - * @author ZanGe丶  
23 - */  
24 -@Mapper  
25 -public interface CrmProductConvert {  
26 -  
27 - CrmProductConvert INSTANCE = Mappers.getMapper(CrmProductConvert.class);  
28 -  
29 - default List<CrmProductRespVO> convertList(List<CrmProductDO> list,  
30 - Map<Long, AdminUserRespDTO> userMap,  
31 - List<CrmProductCategoryDO> categoryList) {  
32 - Map<Long, CrmProductCategoryDO> categoryMap = convertMap(categoryList, CrmProductCategoryDO::getId);  
33 - return CollectionUtils.convertList(list,  
34 - product -> convert(product, userMap, categoryMap.get(product.getCategoryId())));  
35 - }  
36 -  
37 - default CrmProductRespVO convert(CrmProductDO product,  
38 - Map<Long, AdminUserRespDTO> userMap, CrmProductCategoryDO category) {  
39 - CrmProductRespVO productVO = BeanUtils.toBean(product, CrmProductRespVO.class);  
40 - Optional.ofNullable(category).ifPresent(c -> productVO.setCategoryName(c.getName()));  
41 - MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname()));  
42 - MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname()));  
43 - return productVO;  
44 - }  
45 -  
46 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java
@@ -8,10 +8,11 @@ import com.baomidou.mybatisplus.annotation.TableId; @@ -8,10 +8,11 @@ import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
9 import lombok.*; 9 import lombok.*;
10 10
  11 +import java.math.BigDecimal;
11 import java.time.LocalDateTime; 12 import java.time.LocalDateTime;
12 13
13 /** 14 /**
14 - * 商机 DO 15 + * CRM 商机 DO
15 * 16 *
16 * @author ljlleo 17 * @author ljlleo
17 */ 18 */
@@ -26,7 +27,7 @@ import java.time.LocalDateTime; @@ -26,7 +27,7 @@ import java.time.LocalDateTime;
26 public class CrmBusinessDO extends BaseDO { 27 public class CrmBusinessDO extends BaseDO {
27 28
28 /** 29 /**
29 - * 主键 30 + * 编号
30 */ 31 */
31 @TableId 32 @TableId
32 private Long id; 33 private Long id;
@@ -35,50 +36,44 @@ public class CrmBusinessDO extends BaseDO { @@ -35,50 +36,44 @@ public class CrmBusinessDO extends BaseDO {
35 */ 36 */
36 private String name; 37 private String name;
37 /** 38 /**
38 - * 商机状态类型编号 39 + * 客户编号
39 * 40 *
40 - * 关联 {@link CrmBusinessStatusTypeDO#getId()} 41 + * 关联 {@link CrmCustomerDO#getId()}
41 */ 42 */
42 - private Long statusTypeId; 43 + private Long customerId;
  44 +
43 /** 45 /**
44 - * 商机状态编号  
45 - *  
46 - * 关联 {@link CrmBusinessStatusDO#getId()} 46 + * 跟进状态
47 */ 47 */
48 - private Long statusId; 48 + private Boolean followUpStatus;
  49 + /**
  50 + * 最后跟进时间
  51 + */
  52 + private LocalDateTime contactLastTime;
49 /** 53 /**
50 * 下次联系时间 54 * 下次联系时间
51 */ 55 */
52 private LocalDateTime contactNextTime; 56 private LocalDateTime contactNextTime;
  57 +
53 /** 58 /**
54 - * 客户编号 59 + * 负责人的用户编号
55 * 60 *
56 - * TODO @ljileo:这个字段,后续要写下关联的实体哈  
57 - * 关联 {@link CrmCustomerDO#getId()}  
58 - */  
59 - private Long customerId;  
60 - /**  
61 - * 预计成交日期 61 + * 关联 AdminUserDO 的 id 字段
62 */ 62 */
63 - private LocalDateTime dealTime; 63 + private Long ownerUserId;
  64 +
64 /** 65 /**
65 - * 商机金额 66 + * 商机状态组编号
66 * 67 *
  68 + * 关联 {@link CrmBusinessStatusTypeDO#getId()}
67 */ 69 */
68 - private Integer price; 70 + private Long statusTypeId;
69 /** 71 /**
70 - * 整单折扣 72 + * 商机状态编号
71 * 73 *
  74 + * 关联 {@link CrmBusinessStatusDO#getId()}
72 */ 75 */
73 - private Integer discountPercent;  
74 - /**  
75 - * 产品总金额,单位:分  
76 - */  
77 - private Integer productPrice;  
78 - /**  
79 - * 备注  
80 - */  
81 - private String remark; 76 + private Long statusId;
82 /** 77 /**
83 * 结束状态 78 * 结束状态
84 * 79 *
@@ -89,20 +84,28 @@ public class CrmBusinessDO extends BaseDO { @@ -89,20 +84,28 @@ public class CrmBusinessDO extends BaseDO {
89 * 结束时的备注 84 * 结束时的备注
90 */ 85 */
91 private String endRemark; 86 private String endRemark;
  87 +
92 /** 88 /**
93 - * 最后跟进时间 89 + * 预计成交日期
94 */ 90 */
95 - private LocalDateTime contactLastTime; 91 + private LocalDateTime dealTime;
96 /** 92 /**
97 - * 跟进状态 93 + * 产品总金额,单位:元
  94 + *
  95 + * productPrice = ∑({@link CrmBusinessProductDO#getTotalPrice()})
98 */ 96 */
99 - private Boolean followUpStatus;  
100 - 97 + private BigDecimal totalProductPrice;
101 /** 98 /**
102 - * 负责人的用户编号  
103 - *  
104 - * 关联 AdminUserDO 的 id 字段 99 + * 整单折扣,百分比
105 */ 100 */
106 - private Long ownerUserId; 101 + private BigDecimal discountPercent;
  102 + /**
  103 + * 商机总金额,单位:元
  104 + */
  105 + private BigDecimal totalPrice;
  106 + /**
  107 + * 备注
  108 + */
  109 + private String remark;
107 110
108 } 111 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
@@ -7,9 +7,13 @@ import com.baomidou.mybatisplus.annotation.TableId; @@ -7,9 +7,13 @@ import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 7 import com.baomidou.mybatisplus.annotation.TableName;
8 import lombok.*; 8 import lombok.*;
9 9
  10 +import java.math.BigDecimal;
  11 +
10 /** 12 /**
11 * 商机产品关联表 DO 13 * 商机产品关联表 DO
12 * 14 *
  15 + * CrmBusinessDO : CrmBusinessProductDO = 1 : N
  16 + *
13 * @author lzxhqs 17 * @author lzxhqs
14 */ 18 */
15 @TableName("crm_business_product") 19 @TableName("crm_business_product")
@@ -40,24 +44,24 @@ public class CrmBusinessProductDO extends BaseDO { @@ -40,24 +44,24 @@ public class CrmBusinessProductDO extends BaseDO {
40 */ 44 */
41 private Long productId; 45 private Long productId;
42 /** 46 /**
43 - * 产品单价 47 + * 产品单价,单位:元
  48 + *
  49 + * 冗余 {@link CrmProductDO#getPrice()}
44 */ 50 */
45 - private Integer price; 51 + private BigDecimal productPrice;
46 /** 52 /**
47 - * 销售价格, 单位:分 53 + * 合同价格, 单位:元
48 */ 54 */
49 - private Integer salesPrice; 55 + private BigDecimal businessPrice;
50 /** 56 /**
51 * 数量 57 * 数量
52 */ 58 */
53 - private Integer count; 59 + private BigDecimal count;
54 /** 60 /**
55 - * 折扣  
56 - */  
57 - private Integer discountPercent;  
58 - /**  
59 - * 总计价格(折扣后价格) 61 + * 总计价格,单位:元
  62 + *
  63 + * totalPrice = businessPrice * count
60 */ 64 */
61 - private Integer totalPrice; 65 + private BigDecimal totalPrice;
62 66
63 } 67 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java
1 package cn.iocoder.yudao.module.crm.dal.dataobject.business; 1 package cn.iocoder.yudao.module.crm.dal.dataobject.business;
2 2
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; 4 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
6 import com.baomidou.mybatisplus.annotation.KeySequence; 5 import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -12,7 +11,7 @@ import lombok.*; @@ -12,7 +11,7 @@ import lombok.*;
12 import java.util.List; 11 import java.util.List;
13 12
14 /** 13 /**
15 - * 商机状态类型 DO 14 + * 商机状态组 DO
16 * 15 *
17 * @author ljlleo 16 * @author ljlleo
18 */ 17 */
@@ -35,17 +34,11 @@ public class CrmBusinessStatusTypeDO extends BaseDO { @@ -35,17 +34,11 @@ public class CrmBusinessStatusTypeDO extends BaseDO {
35 * 状态类型名 34 * 状态类型名
36 */ 35 */
37 private String name; 36 private String name;
  37 +
38 /** 38 /**
39 * 使用的部门编号 39 * 使用的部门编号
40 */ 40 */
41 @TableField(typeHandler = LongListTypeHandler.class) 41 @TableField(typeHandler = LongListTypeHandler.class)
42 private List<Long> deptIds; 42 private List<Long> deptIds;
43 - /**  
44 - * 开启状态  
45 - *  
46 - * TODO 改成 Integer,关联 CommonStatus  
47 - * 枚举 {@link CommonStatusEnum}  
48 - */  
49 - private Boolean status;  
50 43
51 } 44 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java
@@ -11,7 +11,7 @@ import lombok.*; @@ -11,7 +11,7 @@ import lombok.*;
11 import java.time.LocalDateTime; 11 import java.time.LocalDateTime;
12 12
13 /** 13 /**
14 - * 线索 DO 14 + * CRM 线索 DO
15 * 15 *
16 * @author Wanwan 16 * @author Wanwan
17 */ 17 */
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java
@@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableId; @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
9 import lombok.*; 9 import lombok.*;
10 10
  11 +import java.math.BigDecimal;
  12 +
11 /** 13 /**
12 * CRM 产品 DO 14 * CRM 产品 DO
13 * 15 *
@@ -43,9 +45,9 @@ public class CrmProductDO extends BaseDO { @@ -43,9 +45,9 @@ public class CrmProductDO extends BaseDO {
43 */ 45 */
44 private Integer unit; 46 private Integer unit;
45 /** 47 /**
46 - * 价格,单位:分 48 + * 价格,单位:元
47 */ 49 */
48 - private Integer price; 50 + private BigDecimal price;
49 /** 51 /**
50 * 状态 52 * 状态
51 * 53 *
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
@@ -63,4 +63,8 @@ public interface CrmBusinessMapper extends BaseMapperX&lt;CrmBusinessDO&gt; { @@ -63,4 +63,8 @@ public interface CrmBusinessMapper extends BaseMapperX&lt;CrmBusinessDO&gt; {
63 return selectJoinList(CrmBusinessDO.class, query); 63 return selectJoinList(CrmBusinessDO.class, query);
64 } 64 }
65 65
  66 + default Long selectCountByStatusTypeId(Long statusTypeId) {
  67 + return selectCount(CrmBusinessDO::getStatusTypeId, statusTypeId);
  68 + }
  69 +
66 } 70 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java
1 package cn.iocoder.yudao.module.crm.dal.mysql.business; 1 package cn.iocoder.yudao.module.crm.dal.mysql.business;
2 2
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 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.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO;  
7 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;  
8 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; 4 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
9 import org.apache.ibatis.annotations.Mapper; 5 import org.apache.ibatis.annotations.Mapper;
10 6
@@ -18,20 +14,12 @@ import java.util.List; @@ -18,20 +14,12 @@ import java.util.List;
18 @Mapper 14 @Mapper
19 public interface CrmBusinessStatusMapper extends BaseMapperX<CrmBusinessStatusDO> { 15 public interface CrmBusinessStatusMapper extends BaseMapperX<CrmBusinessStatusDO> {
20 16
21 - default PageResult<CrmBusinessStatusDO> selectPage(CrmBusinessStatusPageReqVO reqVO) {  
22 - return selectPage(reqVO, new LambdaQueryWrapperX<CrmBusinessStatusDO>()  
23 - .orderByDesc(CrmBusinessStatusDO::getId));  
24 - }  
25 -  
26 - default List<CrmBusinessStatusDO> selectList(CrmBusinessStatusQueryVO queryVO) {  
27 - return selectList(new LambdaQueryWrapperX<CrmBusinessStatusDO>()  
28 - .eqIfPresent(CrmBusinessStatusDO::getTypeId, queryVO.getTypeId())  
29 - .inIfPresent(CrmBusinessStatusDO::getId, queryVO.getIdList())  
30 - .orderByDesc(CrmBusinessStatusDO::getId)); 17 + default int deleteByTypeId(Long typeId) {
  18 + return delete(CrmBusinessStatusDO::getTypeId, typeId);
31 } 19 }
32 20
33 - default int delete(Long typeId) {  
34 - return delete(CrmBusinessStatusDO::getTypeId, typeId); 21 + default List<CrmBusinessStatusDO> selectListByTypeId(Long typeId) {
  22 + return selectList(CrmBusinessStatusDO::getTypeId, typeId);
35 } 23 }
36 24
37 } 25 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java
1 package cn.iocoder.yudao.module.crm.dal.mysql.business; 1 package cn.iocoder.yudao.module.crm.dal.mysql.business;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO;  
7 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;  
8 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
9 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
10 9
11 -import java.util.List;  
12 -  
13 /** 10 /**
14 - * 商机状态类型 Mapper 11 + * 商机状态组 Mapper
15 * 12 *
16 * @author ljlleo 13 * @author ljlleo
17 */ 14 */
18 @Mapper 15 @Mapper
19 public interface CrmBusinessStatusTypeMapper extends BaseMapperX<CrmBusinessStatusTypeDO> { 16 public interface CrmBusinessStatusTypeMapper extends BaseMapperX<CrmBusinessStatusTypeDO> {
20 17
21 - default PageResult<CrmBusinessStatusTypeDO> selectPage(CrmBusinessStatusTypePageReqVO reqVO) { 18 + default PageResult<CrmBusinessStatusTypeDO> selectPage(PageParam reqVO) {
22 return selectPage(reqVO, new LambdaQueryWrapperX<CrmBusinessStatusTypeDO>() 19 return selectPage(reqVO, new LambdaQueryWrapperX<CrmBusinessStatusTypeDO>()
23 .orderByDesc(CrmBusinessStatusTypeDO::getId)); 20 .orderByDesc(CrmBusinessStatusTypeDO::getId));
24 } 21 }
25 22
26 - default List<CrmBusinessStatusTypeDO> selectList(CrmBusinessStatusTypeQueryVO queryVO) {  
27 - return selectList(new LambdaQueryWrapperX<CrmBusinessStatusTypeDO>()  
28 - .eqIfPresent(CrmBusinessStatusTypeDO::getStatus, queryVO.getStatus())  
29 - .inIfPresent(CrmBusinessStatusTypeDO::getId, queryVO.getIdList()));  
30 - }  
31 -  
32 - // TODO @lzxhqs:这个可以改成 selectByName。业务上基于在判断 id 匹配;这样更通用一些;mapper 尽量通用,不关注或者特别关联业务;  
33 - /**  
34 - * 根据ID和name查询  
35 - *  
36 - * @param id 商机状态类型id  
37 - * @param name 状态类型名  
38 - * @return result  
39 - */  
40 - default CrmBusinessStatusTypeDO selectByIdAndName(Long id, String name) {  
41 - return selectOne(CrmBusinessStatusTypeDO::getId, id, CrmBusinessStatusTypeDO::getName, name); 23 + default CrmBusinessStatusTypeDO selectByName(String name) {
  24 + return selectOne(CrmBusinessStatusTypeDO::getName, name);
42 } 25 }
43 26
44 } 27 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java deleted
1 -/**  
2 - * 商机(销售机会)  
3 - */  
4 -package cn.iocoder.yudao.module.crm.dal.mysql.business;  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java deleted
1 -/**  
2 - * 联系人  
3 - */  
4 -package cn.iocoder.yudao.module.crm.dal.mysql.contact;  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java
@@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
6 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
7 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
8 -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;  
9 -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;  
10 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
11 9
  10 +import java.util.List;
  11 +
12 /** 12 /**
13 * CRM 产品 Mapper 13 * CRM 产品 Mapper
14 * 14 *
@@ -17,21 +17,23 @@ import org.apache.ibatis.annotations.Mapper; @@ -17,21 +17,23 @@ import org.apache.ibatis.annotations.Mapper;
17 @Mapper 17 @Mapper
18 public interface CrmProductMapper extends BaseMapperX<CrmProductDO> { 18 public interface CrmProductMapper extends BaseMapperX<CrmProductDO> {
19 19
20 - default PageResult<CrmProductDO> selectPage(CrmProductPageReqVO reqVO, Long userId) {  
21 - MPJLambdaWrapperX<CrmProductDO> query = new MPJLambdaWrapperX<>();  
22 - // 拼接数据权限的查询条件  
23 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_PRODUCT.getType(),  
24 - CrmProductDO::getId, userId, null, Boolean.FALSE);  
25 - // 拼接自身的查询条件  
26 - query.selectAll(CrmProductDO.class) 20 + default PageResult<CrmProductDO> selectPage(CrmProductPageReqVO reqVO) {
  21 + return selectPage(reqVO, new MPJLambdaWrapperX<CrmProductDO>()
27 .likeIfPresent(CrmProductDO::getName, reqVO.getName()) 22 .likeIfPresent(CrmProductDO::getName, reqVO.getName())
28 .eqIfPresent(CrmProductDO::getStatus, reqVO.getStatus()) 23 .eqIfPresent(CrmProductDO::getStatus, reqVO.getStatus())
29 - .orderByDesc(CrmProductDO::getId);  
30 - return selectJoinPage(reqVO, CrmProductDO.class, query); 24 + .orderByDesc(CrmProductDO::getId));
31 } 25 }
32 26
33 default CrmProductDO selectByNo(String no) { 27 default CrmProductDO selectByNo(String no) {
34 return selectOne(CrmProductDO::getNo, no); 28 return selectOne(CrmProductDO::getNo, no);
35 } 29 }
36 30
  31 + default Long selectCountByCategoryId(Long categoryId) {
  32 + return selectCount(CrmProductDO::getCategoryId, categoryId);
  33 + }
  34 +
  35 + default List<CrmProductDO> selectListByStatus(Integer status) {
  36 + return selectList(CrmProductDO::getStatus, status);
  37 + }
  38 +
37 } 39 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi
5 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; 5 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
6 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
7 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
10 import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; 11 import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
@@ -91,6 +92,14 @@ public interface CrmBusinessService { @@ -91,6 +92,14 @@ public interface CrmBusinessService {
91 List<CrmBusinessDO> getBusinessList(Collection<Long> ids); 92 List<CrmBusinessDO> getBusinessList(Collection<Long> ids);
92 93
93 /** 94 /**
  95 + * 获得指定商机编号的产品列表
  96 + *
  97 + * @param businessId 商机编号
  98 + * @return 商机产品列表
  99 + */
  100 + List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId);
  101 +
  102 + /**
94 * 获得商机分页 103 * 获得商机分页
95 * 104 *
96 * 数据权限:基于 {@link CrmBusinessDO} 105 * 数据权限:基于 {@link CrmBusinessDO}
@@ -129,4 +138,12 @@ public interface CrmBusinessService { @@ -129,4 +138,12 @@ public interface CrmBusinessService {
129 */ 138 */
130 Long getBusinessCountByCustomerId(Long customerId); 139 Long getBusinessCountByCustomerId(Long customerId);
131 140
  141 + /**
  142 + * 获得使用指定商机状态组的商机数量
  143 + *
  144 + * @param statusTypeId 商机状态组编号
  145 + * @return 数量
  146 + */
  147 + Long getBusinessCountByStatusTypeId(Long statusTypeId);
  148 +
132 } 149 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
@@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.crm.service.business; @@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.crm.service.business;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.ListUtil; 4 import cn.hutool.core.collection.ListUtil;
5 -import cn.hutool.core.util.ObjectUtil;  
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 6 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
@@ -14,7 +12,6 @@ import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; @@ -14,7 +12,6 @@ import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
14 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; 12 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
15 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; 13 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
16 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; 14 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
17 -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;  
18 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; 15 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
19 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; 16 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
20 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 17 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
@@ -22,11 +19,14 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; @@ -22,11 +19,14 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
22 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; 19 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
23 import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; 20 import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
24 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; 21 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
  22 +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
25 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; 23 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
  24 +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
26 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; 25 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
27 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 26 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
28 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; 27 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
29 import cn.iocoder.yudao.module.crm.service.product.CrmProductService; 28 import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
  29 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
30 import com.mzt.logapi.context.LogRecordContext; 30 import com.mzt.logapi.context.LogRecordContext;
31 import com.mzt.logapi.service.impl.DiffParseFunction; 31 import com.mzt.logapi.service.impl.DiffParseFunction;
32 import com.mzt.logapi.starter.annotation.LogRecord; 32 import com.mzt.logapi.starter.annotation.LogRecord;
@@ -36,14 +36,14 @@ import org.springframework.stereotype.Service; @@ -36,14 +36,14 @@ import org.springframework.stereotype.Service;
36 import org.springframework.transaction.annotation.Transactional; 36 import org.springframework.transaction.annotation.Transactional;
37 import org.springframework.validation.annotation.Validated; 37 import org.springframework.validation.annotation.Validated;
38 38
  39 +import java.math.BigDecimal;
39 import java.util.Collection; 40 import java.util.Collection;
40 import java.util.List; 41 import java.util.List;
41 -import java.util.Map;  
42 -import java.util.Set;  
43 42
44 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
45 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 44 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
46 -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; 45 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS;
  46 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
47 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; 47 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
48 48
49 /** 49 /**
@@ -61,40 +61,53 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -61,40 +61,53 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
61 private CrmBusinessProductMapper businessProductMapper; 61 private CrmBusinessProductMapper businessProductMapper;
62 62
63 @Resource 63 @Resource
  64 + private CrmBusinessStatusService businessStatusService;
  65 + @Resource
64 @Lazy // 延迟加载,避免循环依赖 66 @Lazy // 延迟加载,避免循环依赖
65 private CrmContractService contractService; 67 private CrmContractService contractService;
66 @Resource 68 @Resource
  69 + private CrmCustomerService customerService;
  70 + @Resource
  71 + @Lazy // 延迟加载,避免循环依赖
  72 + private CrmContactService contactService;
  73 + @Resource
67 private CrmPermissionService permissionService; 74 private CrmPermissionService permissionService;
68 @Resource 75 @Resource
69 private CrmContactBusinessService contactBusinessService; 76 private CrmContactBusinessService contactBusinessService;
70 @Resource 77 @Resource
71 private CrmProductService productService; 78 private CrmProductService productService;
72 79
  80 + @Resource
  81 + private AdminUserApi adminUserApi;
  82 +
73 @Override 83 @Override
74 @Transactional(rollbackFor = Exception.class) 84 @Transactional(rollbackFor = Exception.class)
75 @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}", 85 @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}",
76 success = CRM_BUSINESS_CREATE_SUCCESS) 86 success = CRM_BUSINESS_CREATE_SUCCESS)
77 public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) { 87 public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) {
78 - createReqVO.setId(null);  
79 - // 1. 插入商机 88 + // 1.1 校验产品项的有效性
  89 + List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(createReqVO.getProducts());
  90 + // 1.2 校验关联字段
  91 + validateBusinessForCreate(createReqVO);
  92 +
  93 + // 2.1 插入商机
80 CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId); 94 CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId);
  95 + business.setStatusId(businessStatusService.getBusinessStatusListByTypeId(createReqVO.getStatusTypeId()).get(0).getId()); // 默认状态
  96 + calculateTotalPrice(business, businessProducts);
81 businessMapper.insert(business); 97 businessMapper.insert(business);
82 - // 1.2 插入商机关联商品  
83 - if (CollUtil.isNotEmpty(createReqVO.getItems())) { // 如果有的话  
84 - List<CrmBusinessProductDO> productList = buildBusinessProductList(createReqVO.getItems(), business.getId());  
85 - businessProductMapper.insertBatch(productList);  
86 - // 更新合同商品总金额  
87 - businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice(  
88 - getSumValue(productList, CrmBusinessProductDO::getTotalPrice, Integer::sum))); 98 + // 2.2 插入商机关联商品
  99 + if (CollUtil.isNotEmpty(businessProducts)) {
  100 + businessProducts.forEach(item -> item.setBusinessId(business.getId()));
  101 + businessProductMapper.insertBatch(businessProducts);
89 } 102 }
90 // 在联系人的详情页,如果直接【新建商机】,则需要关联下。 103 // 在联系人的详情页,如果直接【新建商机】,则需要关联下。
91 contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId()); 104 contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId());
92 - // 2. 创建数据权限 105 + // 3. 创建数据权限
93 // 设置当前操作的人为负责人 106 // 设置当前操作的人为负责人
94 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) 107 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
95 .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); 108 .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
96 109
97 - // 3. 记录操作日志上下文 110 + // 4. 记录操作日志上下文
98 LogRecordContext.putVariable("business", business); 111 LogRecordContext.putVariable("business", business);
99 return business.getId(); 112 return business.getId();
100 } 113 }
@@ -105,15 +118,20 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -105,15 +118,20 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
105 success = CRM_BUSINESS_UPDATE_SUCCESS) 118 success = CRM_BUSINESS_UPDATE_SUCCESS)
106 @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) 119 @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
107 public void updateBusiness(CrmBusinessSaveReqVO updateReqVO) { 120 public void updateBusiness(CrmBusinessSaveReqVO updateReqVO) {
108 - // 1. 校验存在 121 + updateReqVO.setOwnerUserId(null).setStatusTypeId(null); // 不允许更新的字段
  122 + // 1.1 校验存在
109 CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId()); 123 CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId());
  124 + // 1.2 校验产品项的有效性
  125 + List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(updateReqVO.getProducts());
  126 + // 1.3 校验关联字段
  127 + validateBusinessForCreate(updateReqVO);
110 128
111 // 2.1 更新商机 129 // 2.1 更新商机
112 CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); 130 CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class);
  131 + calculateTotalPrice(updateObj, businessProducts);
113 businessMapper.updateById(updateObj); 132 businessMapper.updateById(updateObj);
114 // 2.2 更新商机关联商品 133 // 2.2 更新商机关联商品
115 - List<CrmBusinessProductDO> productList = buildBusinessProductList(updateReqVO.getItems(), updateObj.getId());  
116 - updateBusinessProduct(productList, updateObj.getId()); 134 + updateBusinessProduct(updateObj.getId(), businessProducts);
117 135
118 // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 136 // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
119 // 3. 记录操作日志上下文 137 // 3. 记录操作日志上下文
@@ -121,6 +139,56 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -121,6 +139,56 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
121 LogRecordContext.putVariable("businessName", oldBusiness.getName()); 139 LogRecordContext.putVariable("businessName", oldBusiness.getName());
122 } 140 }
123 141
  142 + private void updateBusinessProduct(Long id, List<CrmBusinessProductDO> newList) {
  143 + List<CrmBusinessProductDO> oldList = businessProductMapper.selectListByBusinessId(id);
  144 + List<List<CrmBusinessProductDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录
  145 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId()));
  146 + if (CollUtil.isNotEmpty(diffList.get(0))) {
  147 + diffList.get(0).forEach(o -> o.setBusinessId(id));
  148 + businessProductMapper.insertBatch(diffList.get(0));
  149 + }
  150 + if (CollUtil.isNotEmpty(diffList.get(1))) {
  151 + businessProductMapper.updateBatch(diffList.get(1));
  152 + }
  153 + if (CollUtil.isNotEmpty(diffList.get(2))) {
  154 + businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId));
  155 + }
  156 + }
  157 +
  158 + private void validateBusinessForCreate(CrmBusinessSaveReqVO saveReqVO) {
  159 + // 校验商机状态
  160 + if (saveReqVO.getStatusTypeId() != null) {
  161 + businessStatusService.validateBusinessStatusType(saveReqVO.getStatusTypeId());
  162 + }
  163 + // 校验客户
  164 + if (saveReqVO.getCustomerId() != null) {
  165 + customerService.validateCustomer(saveReqVO.getCustomerId());
  166 + }
  167 + // 校验联系人
  168 + if (saveReqVO.getContactId() != null) {
  169 + contactService.validateContact(saveReqVO.getContactId());
  170 + }
  171 + // 校验负责人
  172 + if (saveReqVO.getOwnerUserId() != null) {
  173 + adminUserApi.validateUser(saveReqVO.getOwnerUserId());
  174 + }
  175 + }
  176 +
  177 + private List<CrmBusinessProductDO> validateBusinessProducts(List<CrmBusinessSaveReqVO.Product> list) {
  178 + // 1. 校验产品存在
  179 + productService.validProductList(convertSet(list, CrmBusinessSaveReqVO.Product::getProductId));
  180 + // 2. 转化为 CrmBusinessProductDO 列表
  181 + return convertList(list, o -> BeanUtils.toBean(o, CrmBusinessProductDO.class, item -> {
  182 + item.setTotalPrice(MoneyUtils.priceMultiply(item.getBusinessPrice(), item.getCount()));
  183 + }));
  184 + }
  185 +
  186 + private void calculateTotalPrice(CrmBusinessDO business, List<CrmBusinessProductDO> businessProducts) {
  187 + business.setTotalProductPrice(getSumValue(businessProducts, CrmBusinessProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO));
  188 + BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(business.getTotalProductPrice(), business.getDiscountPercent());
  189 + business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
  190 + }
  191 +
124 @Override 192 @Override
125 public void updateBusinessFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList) { 193 public void updateBusinessFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList) {
126 businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList)); 194 businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList));
@@ -146,43 +214,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -146,43 +214,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
146 LogRecordContext.putVariable("businessName", business.getName()); 214 LogRecordContext.putVariable("businessName", business.getName());
147 } 215 }
148 216
149 - private void updateBusinessProduct(List<CrmBusinessProductDO> newProductList, Long businessId) {  
150 - List<CrmBusinessProductDO> oldProducts = businessProductMapper.selectListByBusinessId(businessId);  
151 - List<List<CrmBusinessProductDO>> diffList = CollectionUtils.diffList(oldProducts, newProductList, (oldValue, newValue) -> {  
152 - boolean condition = ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId());  
153 - if (condition) {  
154 - newValue.setId(oldValue.getId()); // 更新需要原始编号  
155 - }  
156 - return condition;  
157 - });  
158 - if (CollUtil.isNotEmpty(diffList.get(0))) {  
159 - businessProductMapper.insertBatch(diffList.get(0));  
160 - }  
161 - if (CollUtil.isNotEmpty(diffList.get(1))) {  
162 - businessProductMapper.updateBatch(diffList.get(1));  
163 - }  
164 - if (CollUtil.isNotEmpty(diffList.get(2))) {  
165 - businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId));  
166 - }  
167 - }  
168 -  
169 - private List<CrmBusinessProductDO> buildBusinessProductList(List<CrmBusinessSaveReqVO.Item> productItems, Long businessId) {  
170 - // 校验商品存在  
171 - Set<Long> productIds = convertSet(productItems, CrmBusinessSaveReqVO.Item::getId);  
172 - List<CrmProductDO> productList = productService.getProductList(productIds);  
173 - if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) {  
174 - throw exception(PRODUCT_NOT_EXISTS);  
175 - }  
176 - Map<Long, CrmProductDO> productMap = convertMap(productList, CrmProductDO::getId);  
177 - return convertList(productItems, productItem -> {  
178 - CrmProductDO product = productMap.get(productItem.getId());  
179 - return BeanUtils.toBean(product, CrmBusinessProductDO.class)  
180 - .setId(null).setProductId(productItem.getId()).setBusinessId(businessId)  
181 - .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent())  
182 - .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent()));  
183 - });  
184 - }  
185 -  
186 /** 217 /**
187 * 删除校验合同是关联合同 218 * 删除校验合同是关联合同
188 * 219 *
@@ -225,10 +256,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -225,10 +256,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
225 256
226 @Override 257 @Override
227 public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) { 258 public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) {
228 - // 更新商机关联商品  
229 - List<CrmBusinessProductDO> productList = buildBusinessProductList(  
230 - BeanUtils.toBean(updateProductReqBO.getItems(), CrmBusinessSaveReqVO.Item.class), updateProductReqBO.getId());  
231 - updateBusinessProduct(productList, updateProductReqBO.getId()); 259 + // 更新商机关联商品 TODO yunai
  260 +// List<CrmBusinessProductDO> productList = buildBusinessProductList(
  261 +// BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.Product.class), updateProductReqBO.getId());
  262 +// updateBusinessProduct(productList, updateProductReqBO.getId());
232 } 263 }
233 264
234 //======================= 查询相关 ======================= 265 //======================= 查询相关 =======================
@@ -256,6 +287,11 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -256,6 +287,11 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
256 } 287 }
257 288
258 @Override 289 @Override
  290 + public List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId) {
  291 + return businessProductMapper.selectListByBusinessId(businessId);
  292 + }
  293 +
  294 + @Override
259 public PageResult<CrmBusinessDO> getBusinessPage(CrmBusinessPageReqVO pageReqVO, Long userId) { 295 public PageResult<CrmBusinessDO> getBusinessPage(CrmBusinessPageReqVO pageReqVO, Long userId) {
260 return businessMapper.selectPage(pageReqVO, userId); 296 return businessMapper.selectPage(pageReqVO, userId);
261 } 297 }
@@ -285,4 +321,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -285,4 +321,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
285 return businessMapper.selectCount(CrmBusinessDO::getCustomerId, customerId); 321 return businessMapper.selectCount(CrmBusinessDO::getCustomerId, customerId);
286 } 322 }
287 323
  324 + @Override
  325 + public Long getBusinessCountByStatusTypeId(Long statusTypeId) {
  326 + return businessMapper.selectCountByStatusTypeId(statusTypeId);
  327 + }
  328 +
288 } 329 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java
1 package cn.iocoder.yudao.module.crm.service.business; 1 package cn.iocoder.yudao.module.crm.service.business;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO;  
5 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;  
6 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO; 5 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
7 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; 6 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
8 - 7 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
9 import jakarta.validation.Valid; 8 import jakarta.validation.Valid;
10 9
11 import java.util.Collection; 10 import java.util.Collection;
12 import java.util.List; 11 import java.util.List;
  12 +import java.util.Map;
  13 +
  14 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
13 15
14 /** 16 /**
15 * 商机状态 Service 接口 17 * 商机状态 Service 接口
@@ -38,33 +40,63 @@ public interface CrmBusinessStatusService { @@ -38,33 +40,63 @@ public interface CrmBusinessStatusService {
38 * 40 *
39 * @param id 编号 41 * @param id 编号
40 */ 42 */
41 - void deleteBusinessStatus(Long id); 43 + void deleteBusinessStatusType(Long id);
  44 +
  45 + /**
  46 + * 获得商机状态组
  47 + *
  48 + * @param id 编号
  49 + * @return 商机状态组
  50 + */
  51 + CrmBusinessStatusTypeDO getBusinessStatusType(Long id);
42 52
43 /** 53 /**
44 - * 获得商机状态 54 + * 校验商机状态组
45 * 55 *
46 * @param id 编号 56 * @param id 编号
47 - * @return 商机状态  
48 */ 57 */
49 - CrmBusinessStatusDO getBusinessStatus(Long id); 58 + void validateBusinessStatusType(Long id);
50 59
51 /** 60 /**
52 - * 获得商机状态分页 61 + * 获得商机状态组列表
  62 + *
  63 + * @return 商机状态组列表
  64 + */
  65 + List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList();
  66 +
  67 + /**
  68 + * 获得商机状态组分页
53 * 69 *
54 * @param pageReqVO 分页查询 70 * @param pageReqVO 分页查询
55 - * @return 商机状态分页 71 + * @return 商机状态组分页
56 */ 72 */
57 - PageResult<CrmBusinessStatusDO> getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO); 73 + PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(PageParam pageReqVO);
58 74
59 - // TODO @ljlleo 常用的 ids 之类的查询,可以封装单独的方法,不用走类似 QueryVO,用起来更方便。  
60 - // TODO @ljlleo 方法名用 getBusinessStatusList  
61 /** 75 /**
62 - * 获得商机状态分页 76 + * 获得商机状态组列表
63 * 77 *
64 - * @param queryVO 查询参数  
65 - * @return 商机状态分页 78 + * @param ids 编号数组
  79 + * @return 商机状态组列表
66 */ 80 */
67 - List<CrmBusinessStatusDO> selectList(CrmBusinessStatusQueryVO queryVO); 81 + List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids);
  82 +
  83 + /**
  84 + * 获得商机状态组 Map
  85 + *
  86 + * @param ids 编号数组
  87 + * @return 商机状态组 Map
  88 + */
  89 + default Map<Long, CrmBusinessStatusTypeDO> getBusinessStatusTypeMap(Collection<Long> ids) {
  90 + return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId);
  91 + }
  92 +
  93 + /**
  94 + * 获得指定类型的商机状态列表
  95 + *
  96 + * @param typeId 商机状态组编号
  97 + * @return 商机状态列表
  98 + */
  99 + List<CrmBusinessStatusDO> getBusinessStatusListByTypeId(Long typeId);
68 100
69 /** 101 /**
70 * 获得商机状态列表 102 * 获得商机状态列表
@@ -74,4 +106,14 @@ public interface CrmBusinessStatusService { @@ -74,4 +106,14 @@ public interface CrmBusinessStatusService {
74 */ 106 */
75 List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids); 107 List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids);
76 108
  109 + /**
  110 + * 获得商机状态 Map
  111 + *
  112 + * @param ids 编号数组
  113 + * @return 商机状态 Map
  114 + */
  115 + default Map<Long, CrmBusinessStatusDO> getBusinessStatusMap(Collection<Long> ids) {
  116 + return convertMap(getBusinessStatusList(ids), CrmBusinessStatusDO::getId);
  117 + }
  118 +
77 } 119 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java
1 package cn.iocoder.yudao.module.crm.service.business; 1 package cn.iocoder.yudao.module.crm.service.business;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO;  
6 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;  
7 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO; 7 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; 8 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
9 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper; 10 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper;
  11 +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper;
  12 +import jakarta.annotation.Resource;
  13 +import org.springframework.context.annotation.Lazy;
10 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
  15 +import org.springframework.transaction.annotation.Transactional;
11 import org.springframework.validation.annotation.Validated; 16 import org.springframework.validation.annotation.Validated;
12 17
13 -import jakarta.annotation.Resource;  
14 -  
15 import java.util.Collection; 18 import java.util.Collection;
  19 +import java.util.Collections;
  20 +import java.util.Comparator;
16 import java.util.List; 21 import java.util.List;
17 22
18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_NOT_EXISTS; 24 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  25 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
  26 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
20 27
21 /** 28 /**
22 * 商机状态 Service 实现类 29 * 商机状态 Service 实现类
@@ -28,58 +35,146 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STAT @@ -28,58 +35,146 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STAT
28 public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { 35 public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService {
29 36
30 @Resource 37 @Resource
  38 + private CrmBusinessStatusTypeMapper businessStatusTypeMapper;
  39 + @Resource
31 private CrmBusinessStatusMapper businessStatusMapper; 40 private CrmBusinessStatusMapper businessStatusMapper;
32 41
  42 + @Resource
  43 + @Lazy // 延迟加载,避免循环依赖
  44 + private CrmBusinessService businessService;
  45 +
33 @Override 46 @Override
  47 + @Transactional(rollbackFor = Exception.class)
34 public Long createBusinessStatus(CrmBusinessStatusSaveReqVO createReqVO) { 48 public Long createBusinessStatus(CrmBusinessStatusSaveReqVO createReqVO) {
35 - // 插入  
36 - CrmBusinessStatusDO businessStatus = BeanUtils.toBean(createReqVO, CrmBusinessStatusDO.class);  
37 - businessStatusMapper.insert(businessStatus);  
38 - // 返回  
39 - return businessStatus.getId(); 49 + // 1.1 检验名称是否存在
  50 + validateBusinessStatusTypeNameUnique(createReqVO.getName(), null);
  51 + // 1.2 设置状态的排序
  52 + int sort = 0;
  53 + for (CrmBusinessStatusSaveReqVO.Status status : createReqVO.getStatuses()) {
  54 + status.setSort(sort++);
  55 + }
  56 +
  57 + // 2.1 插入类型
  58 + CrmBusinessStatusTypeDO statusType = BeanUtils.toBean(createReqVO, CrmBusinessStatusTypeDO.class);
  59 + businessStatusTypeMapper.insert(statusType);
  60 + // 2.2 插入状态
  61 + List<CrmBusinessStatusDO> statuses = BeanUtils.toBean(createReqVO.getStatuses(), CrmBusinessStatusDO.class,
  62 + status -> status.setTypeId(statusType.getId()));
  63 + businessStatusMapper.insertBatch(statuses);
  64 + return statusType.getId();
40 } 65 }
41 66
42 @Override 67 @Override
  68 + @Transactional(rollbackFor = Exception.class)
43 public void updateBusinessStatus(CrmBusinessStatusSaveReqVO updateReqVO) { 69 public void updateBusinessStatus(CrmBusinessStatusSaveReqVO updateReqVO) {
44 - // 校验存在  
45 - validateBusinessStatusExists(updateReqVO.getId());  
46 - // 更新  
47 - CrmBusinessStatusDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusDO.class);  
48 - businessStatusMapper.updateById(updateObj); 70 + // 1.1 校验存在
  71 + validateBusinessStatusTypeExists(updateReqVO.getId());
  72 + // 1.2 校验名称是否存在
  73 + validateBusinessStatusTypeNameUnique(updateReqVO.getName(), updateReqVO.getId());
  74 + // 1.3 设置状态的排序
  75 + int sort = 0;
  76 + for (CrmBusinessStatusSaveReqVO.Status status : updateReqVO.getStatuses()) {
  77 + status.setSort(sort++);
  78 + }
  79 + // 1.4 已经使用,无法更新
  80 + if (businessService.getBusinessCountByStatusTypeId(updateReqVO.getId()) > 0) {
  81 + throw exception(BUSINESS_STATUS_UPDATE_FAIL_USED);
  82 + }
  83 +
  84 + // 2.1 更新类型
  85 + CrmBusinessStatusTypeDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusTypeDO.class);
  86 + businessStatusTypeMapper.updateById(updateObj);
  87 + // 2.2 更新状态
  88 + updateBusinessStatus(updateReqVO.getId(), BeanUtils.toBean(updateReqVO.getStatuses(), CrmBusinessStatusDO.class));
49 } 89 }
50 90
51 - @Override  
52 - public void deleteBusinessStatus(Long id) {  
53 - // 校验存在  
54 - validateBusinessStatusExists(id);  
55 - // TODO @ljlleo 这里可以考虑,如果有商机在使用,不允许删除  
56 - // 删除  
57 - businessStatusMapper.deleteById(id); 91 + private void updateBusinessStatus(Long id, List<CrmBusinessStatusDO> newList) {
  92 + List<CrmBusinessStatusDO> oldList = businessStatusMapper.selectListByTypeId(id);
  93 + List<List<CrmBusinessStatusDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录
  94 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId()));
  95 + if (CollUtil.isNotEmpty(diffList.get(0))) {
  96 + diffList.get(0).forEach(o -> o.setTypeId(id));
  97 + businessStatusMapper.insertBatch(diffList.get(0));
  98 + }
  99 + if (CollUtil.isNotEmpty(diffList.get(1))) {
  100 + businessStatusMapper.updateBatch(diffList.get(1));
  101 + }
  102 + if (CollUtil.isNotEmpty(diffList.get(2))) {
  103 + businessStatusMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessStatusDO::getId));
  104 + }
  105 + }
  106 +
  107 + private void validateBusinessStatusTypeExists(Long id) {
  108 + if (businessStatusTypeMapper.selectById(id) == null) {
  109 + throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS);
  110 + }
58 } 111 }
59 112
60 - private void validateBusinessStatusExists(Long id) {  
61 - if (businessStatusMapper.selectById(id) == null) {  
62 - throw exception(BUSINESS_STATUS_NOT_EXISTS); 113 + private void validateBusinessStatusTypeNameUnique(String name, Long id) {
  114 + CrmBusinessStatusTypeDO statusType = businessStatusTypeMapper.selectByName(name);
  115 + if (statusType == null
  116 + || statusType.getId().equals(id)) {
  117 + return;
  118 + }
  119 + throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS);
  120 + }
  121 +
  122 + @Override
  123 + @Transactional(rollbackFor = Exception.class)
  124 + public void deleteBusinessStatusType(Long id) {
  125 + // 1.1 校验存在
  126 + validateBusinessStatusTypeExists(id);
  127 + // 1.2 已经使用,无法更新
  128 + if (businessService.getBusinessCountByStatusTypeId(id) > 0) {
  129 + throw exception(BUSINESS_STATUS_DELETE_FAIL_USED);
63 } 130 }
  131 +
  132 + // 2.1 删除类型
  133 + businessStatusTypeMapper.deleteById(id);
  134 + // 2.2 删除状态
  135 + businessStatusMapper.deleteByTypeId(id);
  136 + }
  137 +
  138 + @Override
  139 + public CrmBusinessStatusTypeDO getBusinessStatusType(Long id) {
  140 + return businessStatusTypeMapper.selectById(id);
64 } 141 }
65 142
66 @Override 143 @Override
67 - public CrmBusinessStatusDO getBusinessStatus(Long id) {  
68 - return businessStatusMapper.selectById(id); 144 + public void validateBusinessStatusType(Long id) {
  145 + validateBusinessStatusTypeExists(id);
69 } 146 }
70 147
71 @Override 148 @Override
72 - public PageResult<CrmBusinessStatusDO> getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO) {  
73 - return businessStatusMapper.selectPage(pageReqVO); 149 + public List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList() {
  150 + return businessStatusTypeMapper.selectList();
74 } 151 }
75 152
76 @Override 153 @Override
77 - public List<CrmBusinessStatusDO> selectList(CrmBusinessStatusQueryVO queryVO) {  
78 - return businessStatusMapper.selectList(queryVO); 154 + public PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(PageParam pageReqVO) {
  155 + return businessStatusTypeMapper.selectPage(pageReqVO);
  156 + }
  157 +
  158 + @Override
  159 + public List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids) {
  160 + if (CollUtil.isEmpty(ids)) {
  161 + return Collections.emptyList();
  162 + }
  163 + return businessStatusTypeMapper.selectBatchIds(ids);
  164 + }
  165 +
  166 + @Override
  167 + public List<CrmBusinessStatusDO> getBusinessStatusListByTypeId(Long typeId) {
  168 + List<CrmBusinessStatusDO> list = businessStatusMapper.selectListByTypeId(typeId);
  169 + list.sort(Comparator.comparingInt(CrmBusinessStatusDO::getSort));
  170 + return list;
79 } 171 }
80 172
81 @Override 173 @Override
82 public List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids) { 174 public List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids) {
  175 + if (CollUtil.isEmpty(ids)) {
  176 + return Collections.emptyList();
  177 + }
83 return businessStatusMapper.selectBatchIds(ids); 178 return businessStatusMapper.selectBatchIds(ids);
84 } 179 }
85 180
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java deleted
1 -package cn.iocoder.yudao.module.crm.service.business;  
2 -  
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO;  
5 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;  
6 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;  
7 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;  
8 -import jakarta.validation.Valid;  
9 -  
10 -import java.util.Collection;  
11 -import java.util.List;  
12 -  
13 -/**  
14 - * 商机状态类型 Service 接口  
15 - *  
16 - * @author ljlleo  
17 - */  
18 -public interface CrmBusinessStatusTypeService {  
19 -  
20 - /**  
21 - * 创建商机状态类型  
22 - *  
23 - * @param createReqVO 创建信息  
24 - * @return 编号  
25 - */  
26 - Long createBusinessStatusType(@Valid CrmBusinessStatusTypeSaveReqVO createReqVO);  
27 -  
28 - /**  
29 - * 更新商机状态类型  
30 - *  
31 - * @param updateReqVO 更新信息  
32 - */  
33 - void updateBusinessStatusType(@Valid CrmBusinessStatusTypeSaveReqVO updateReqVO);  
34 -  
35 - /**  
36 - * 删除商机状态类型  
37 - *  
38 - * @param id 编号  
39 - */  
40 - void deleteBusinessStatusType(Long id);  
41 -  
42 - /**  
43 - * 获得商机状态类型  
44 - *  
45 - * @param id 编号  
46 - * @return 商机状态类型  
47 - */  
48 - CrmBusinessStatusTypeDO getBusinessStatusType(Long id);  
49 -  
50 - /**  
51 - * 获得商机状态类型分页  
52 - *  
53 - * @param pageReqVO 分页查询  
54 - * @return 商机状态类型分页  
55 - */  
56 - PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO);  
57 -  
58 - // TODO @ljlleo 常用的 ids 之类的查询,可以封装单独的方法,不用走类似 QueryVO,用起来更方便。  
59 - /**  
60 - * 获得商机状态类型列表  
61 - *  
62 - * @param queryVO 查询参数  
63 - * @return 商机状态类型列表  
64 - */  
65 - List<CrmBusinessStatusTypeDO> selectList(CrmBusinessStatusTypeQueryVO queryVO);  
66 -  
67 - /**  
68 - * 获得商机状态类型列表  
69 - *  
70 - * @param ids 编号数组  
71 - * @return 商机状态类型列表  
72 - */  
73 - List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids);  
74 -  
75 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java deleted
1 -package cn.iocoder.yudao.module.crm.service.business;  
2 -  
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
5 -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;  
6 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
7 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO;  
8 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;  
9 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;  
10 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;  
11 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;  
12 -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper;  
13 -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper;  
14 -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;  
15 -import org.springframework.stereotype.Service;  
16 -import org.springframework.transaction.annotation.Transactional;  
17 -import org.springframework.validation.annotation.Validated;  
18 -  
19 -import jakarta.annotation.Resource;  
20 -  
21 -import java.util.Collection;  
22 -import java.util.List;  
23 -  
24 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
25 -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS;  
26 -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NAME_EXISTS;  
27 -  
28 -/**  
29 - * 商机状态类型 Service 实现类  
30 - *  
31 - * @author ljlleo  
32 - */  
33 -@Service  
34 -@Validated  
35 -public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeService {  
36 -  
37 - @Resource  
38 - private CrmBusinessStatusTypeMapper businessStatusTypeMapper;  
39 -  
40 - @Resource  
41 - private CrmBusinessStatusMapper businessStatusMapper;  
42 -  
43 - @Override  
44 - @Transactional(rollbackFor = Exception.class)  
45 - public Long createBusinessStatusType(CrmBusinessStatusTypeSaveReqVO createReqVO) {  
46 - //检验名称是否存在  
47 - validateBusinessStatusTypeExists(createReqVO.getName(), null);  
48 - // 插入类型  
49 - CrmBusinessStatusTypeDO businessStatusType = BeanUtils.toBean(createReqVO, CrmBusinessStatusTypeDO.class);  
50 - businessStatusTypeMapper.insert(businessStatusType);  
51 - // 插入状态  
52 - if (CollUtil.isNotEmpty(createReqVO.getStatusList())) {  
53 - createReqVO.getStatusList().forEach(status -> status.setTypeId(businessStatusType.getId()));  
54 - businessStatusMapper.insertBatch(BeanUtils.toBean(createReqVO.getStatusList(), CrmBusinessStatusDO.class));  
55 - }  
56 - return businessStatusType.getId();  
57 - }  
58 -  
59 - @Override  
60 - @Transactional(rollbackFor = Exception.class)  
61 - public void updateBusinessStatusType(CrmBusinessStatusTypeSaveReqVO updateReqVO) {  
62 - // 校验存在  
63 - validateBusinessStatusTypeExists(updateReqVO.getId());  
64 - // 校验名称是否存在  
65 - validateBusinessStatusTypeExists(updateReqVO.getName(), updateReqVO.getId());  
66 - // 更新类型  
67 - CrmBusinessStatusTypeDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusTypeDO.class);  
68 - businessStatusTypeMapper.updateById(updateObj);  
69 - // 更新状态(删除 + 更新)  
70 - // TODO @ljlleo 可以参考 DeliveryExpressTemplateServiceImpl 的 updateExpressTemplateFree 方法;主要没变化的,还是不删除了哈。  
71 - businessStatusMapper.delete(updateReqVO.getId());  
72 - updateReqVO.getStatusList().forEach(status -> status.setTypeId(updateReqVO.getId()));  
73 - businessStatusMapper.insertBatch(BeanUtils.toBean(updateReqVO.getStatusList(), CrmBusinessStatusDO.class));  
74 - }  
75 -  
76 - @Override  
77 - @Transactional(rollbackFor = Exception.class)  
78 - public void deleteBusinessStatusType(Long id) {  
79 - // TODO 待添加被引用校验  
80 - //...  
81 -  
82 - // 校验存在  
83 - validateBusinessStatusTypeExists(id);  
84 - // 删除类型  
85 - businessStatusTypeMapper.deleteById(id);  
86 - // 删除状态  
87 - businessStatusMapper.delete(id);  
88 - }  
89 -  
90 - private void validateBusinessStatusTypeExists(Long id) {  
91 - if (businessStatusTypeMapper.selectById(id) == null) {  
92 - throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS);  
93 - }  
94 - }  
95 -  
96 - // TODO @ljlleo 这个方法,这个参考 validateDeptNameUnique 实现。  
97 - private void validateBusinessStatusTypeExists(String name, Long id) {  
98 - CrmBusinessStatusTypeDO businessStatusTypeDO = businessStatusTypeMapper.selectByIdAndName(id, name);  
99 - if (businessStatusTypeDO != null) {  
100 - throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS);  
101 - }  
102 -// LambdaQueryWrapper<CrmBusinessStatusTypeDO> wrapper = new LambdaQueryWrapperX<>();  
103 -// if(null != id) {  
104 -// wrapper.ne(CrmBusinessStatusTypeDO::getId, id);  
105 -// }  
106 -// long cnt = businessStatusTypeMapper.selectCount(wrapper.eq(CrmBusinessStatusTypeDO::getName, name));  
107 -// if (cnt > 0) {  
108 -// throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS);  
109 -// }  
110 - }  
111 -  
112 - @Override  
113 - public CrmBusinessStatusTypeDO getBusinessStatusType(Long id) {  
114 - return businessStatusTypeMapper.selectById(id);  
115 - }  
116 -  
117 - @Override  
118 - public PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO) {  
119 - return businessStatusTypeMapper.selectPage(pageReqVO);  
120 - }  
121 -  
122 - @Override  
123 - public List<CrmBusinessStatusTypeDO> selectList(CrmBusinessStatusTypeQueryVO queryVO) {  
124 - return businessStatusTypeMapper.selectList(queryVO);  
125 - }  
126 -  
127 - @Override  
128 - public List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids) {  
129 - return businessStatusTypeMapper.selectBatchIds(ids);  
130 - }  
131 -  
132 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
@@ -89,6 +89,13 @@ public interface CrmContactService { @@ -89,6 +89,13 @@ public interface CrmContactService {
89 CrmContactDO getContact(Long id); 89 CrmContactDO getContact(Long id);
90 90
91 /** 91 /**
  92 + * 校验联系人
  93 + *
  94 + * @param id 编号
  95 + */
  96 + void validateContact(Long id);
  97 +
  98 + /**
92 * 获得联系人列表 99 * 获得联系人列表
93 * 100 *
94 * @param ids 编号 101 * @param ids 编号
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
@@ -252,6 +252,11 @@ public class CrmContactServiceImpl implements CrmContactService { @@ -252,6 +252,11 @@ public class CrmContactServiceImpl implements CrmContactService {
252 } 252 }
253 253
254 @Override 254 @Override
  255 + public void validateContact(Long id) {
  256 + validateContactExists(id);
  257 + }
  258 +
  259 + @Override
255 public List<CrmContactDO> getContactListByIds(Collection<Long> ids, Long userId) { 260 public List<CrmContactDO> getContactListByIds(Collection<Long> ids, Long userId) {
256 if (CollUtil.isEmpty(ids)) { 261 if (CollUtil.isEmpty(ids)) {
257 return ListUtil.empty(); 262 return ListUtil.empty();
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -184,7 +184,8 @@ public class CrmContractServiceImpl implements CrmContractService { @@ -184,7 +184,8 @@ public class CrmContractServiceImpl implements CrmContractService {
184 return BeanUtils.toBean(product, CrmContractProductDO.class) 184 return BeanUtils.toBean(product, CrmContractProductDO.class)
185 .setId(null).setProductId(productItem.getId()).setContractId(contractId) 185 .setId(null).setProductId(productItem.getId()).setContractId(contractId)
186 .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) 186 .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent())
187 - .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent())); 187 + // TODO 芋艿:这里临时注释掉
  188 + .setTotalPrice(MoneyUtils.calculator(null, productItem.getCount(), productItem.getDiscountPercent()));
188 }); 189 });
189 } 190 }
190 191
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java
@@ -3,10 +3,13 @@ package cn.iocoder.yudao.module.crm.service.product; @@ -3,10 +3,13 @@ package cn.iocoder.yudao.module.crm.service.product;
3 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO; 3 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
4 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO; 4 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
5 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; 5 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
6 -  
7 import jakarta.validation.Valid; 6 import jakarta.validation.Valid;
  7 +
8 import java.util.Collection; 8 import java.util.Collection;
9 import java.util.List; 9 import java.util.List;
  10 +import java.util.Map;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
10 13
11 /** 14 /**
12 * CRM 产品分类 Service 接口 15 * CRM 产品分类 Service 接口
@@ -61,4 +64,14 @@ public interface CrmProductCategoryService { @@ -61,4 +64,14 @@ public interface CrmProductCategoryService {
61 */ 64 */
62 List<CrmProductCategoryDO> getProductCategoryList(Collection<Long> ids); 65 List<CrmProductCategoryDO> getProductCategoryList(Collection<Long> ids);
63 66
  67 + /**
  68 + * 获得产品分类 Map
  69 + *
  70 + * @param ids 编号数组
  71 + * @return 产品分类 Map
  72 + */
  73 + default Map<Long, CrmProductCategoryDO> getProductCategoryMap(Collection<Long> ids) {
  74 + return convertMap(getProductCategoryList(ids), CrmProductCategoryDO::getId);
  75 + }
  76 +
64 } 77 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java
@@ -8,6 +8,9 @@ import jakarta.validation.Valid; @@ -8,6 +8,9 @@ import jakarta.validation.Valid;
8 8
9 import java.util.Collection; 9 import java.util.Collection;
10 import java.util.List; 10 import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
11 14
12 /** 15 /**
13 * CRM 产品 Service 接口 16 * CRM 产品 Service 接口
@@ -55,27 +58,45 @@ public interface CrmProductService { @@ -55,27 +58,45 @@ public interface CrmProductService {
55 List<CrmProductDO> getProductList(Collection<Long> ids); 58 List<CrmProductDO> getProductList(Collection<Long> ids);
56 59
57 /** 60 /**
  61 + * 获得产品 Map
  62 + *
  63 + * @param ids 编号
  64 + * @return 产品 Map
  65 + */
  66 + default Map<Long, CrmProductDO> getProductMap(Collection<Long> ids) {
  67 + return convertMap(getProductList(ids), CrmProductDO::getId);
  68 + }
  69 +
  70 + /**
58 * 获得产品分页 71 * 获得产品分页
59 * 72 *
60 * @param pageReqVO 分页查询 73 * @param pageReqVO 分页查询
61 * @return 产品分页 74 * @return 产品分页
62 */ 75 */
63 - PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO, Long userId); 76 + PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO);
64 77
65 /** 78 /**
66 - * 获得产品 79 + * 获得产品数量
67 * 80 *
68 * @param categoryId 分类编号 81 * @param categoryId 分类编号
69 * @return 产品 82 * @return 产品
70 */ 83 */
71 - CrmProductDO getProductByCategoryId(Long categoryId); 84 + Long getProductByCategoryId(Long categoryId);
72 85
73 /** 86 /**
74 - * 获得产品列表 87 + * 获得指定状态的产品列表
  88 + *
  89 + * @param status 状态
  90 + * @return 产品列表
  91 + */
  92 + List<CrmProductDO> getProductListByStatus(Integer status);
  93 +
  94 + /**
  95 + * 校验产品们的有效性
75 * 96 *
76 - * @param ids 产品编号 97 + * @param ids 编号数组
77 * @return 产品列表 98 * @return 产品列表
78 */ 99 */
79 - List<CrmProductDO> getProductListByIds(Collection<Long> ids); 100 + List<CrmProductDO> validProductList(Collection<Long> ids);
80 101
81 } 102 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
1 package cn.iocoder.yudao.module.crm.service.product; 1 package cn.iocoder.yudao.module.crm.service.product;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.collection.ListUtil; 4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; 7 import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
@@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm @@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
15 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 15 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
16 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; 16 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
17 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 17 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
18 -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;  
19 import com.mzt.logapi.context.LogRecordContext; 18 import com.mzt.logapi.context.LogRecordContext;
20 import com.mzt.logapi.service.impl.DiffParseFunction; 19 import com.mzt.logapi.service.impl.DiffParseFunction;
21 import com.mzt.logapi.starter.annotation.LogRecord; 20 import com.mzt.logapi.starter.annotation.LogRecord;
@@ -27,8 +26,10 @@ import org.springframework.validation.annotation.Validated; @@ -27,8 +26,10 @@ import org.springframework.validation.annotation.Validated;
27 import java.util.Collection; 26 import java.util.Collection;
28 import java.util.Collections; 27 import java.util.Collections;
29 import java.util.List; 28 import java.util.List;
  29 +import java.util.Map;
30 30
31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  32 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
32 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; 33 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
33 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; 34 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
34 35
@@ -138,25 +139,41 @@ public class CrmProductServiceImpl implements CrmProductService { @@ -138,25 +139,41 @@ public class CrmProductServiceImpl implements CrmProductService {
138 } 139 }
139 140
140 @Override 141 @Override
141 - public List<CrmProductDO> getProductList(Collection<Long> ids) {  
142 - if (CollUtil.isEmpty(ids)) {  
143 - return ListUtil.empty();  
144 - }  
145 - return productMapper.selectBatchIds(ids); 142 + public PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO) {
  143 + return productMapper.selectPage(pageReqVO);
  144 + }
  145 +
  146 + @Override
  147 + public Long getProductByCategoryId(Long categoryId) {
  148 + return productMapper.selectCountByCategoryId(categoryId);
146 } 149 }
147 150
148 @Override 151 @Override
149 - public PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO, Long userId) {  
150 - return productMapper.selectPage(pageReqVO, userId); 152 + public List<CrmProductDO> getProductListByStatus(Integer status) {
  153 + return productMapper.selectListByStatus(status);
151 } 154 }
152 155
153 @Override 156 @Override
154 - public CrmProductDO getProductByCategoryId(Long categoryId) {  
155 - return productMapper.selectOne(new LambdaQueryWrapper<CrmProductDO>().eq(CrmProductDO::getCategoryId, categoryId)); 157 + public List<CrmProductDO> validProductList(Collection<Long> ids) {
  158 + if (CollUtil.isEmpty(ids)) {
  159 + return Collections.emptyList();
  160 + }
  161 + List<CrmProductDO> list = productMapper.selectBatchIds(ids);
  162 + Map<Long, CrmProductDO> productMap = convertMap(list, CrmProductDO::getId);
  163 + for (Long id : ids) {
  164 + CrmProductDO product = productMap.get(id);
  165 + if (productMap.get(id) == null) {
  166 + throw exception(PRODUCT_NOT_EXISTS);
  167 + }
  168 + if (CommonStatusEnum.isDisable(product.getStatus())) {
  169 + throw exception(PRODUCT_NOT_ENABLE, product.getName());
  170 + }
  171 + }
  172 + return list;
156 } 173 }
157 174
158 @Override 175 @Override
159 - public List<CrmProductDO> getProductListByIds(Collection<Long> ids) { 176 + public List<CrmProductDO> getProductList(Collection<Long> ids) {
160 if (CollUtil.isEmpty(ids)) { 177 if (CollUtil.isEmpty(ids)) {
161 return Collections.emptyList(); 178 return Collections.emptyList();
162 } 179 }