Browse Source

!771 同步最新的 CRM 代码
Merge pull request !771 from 芋道源码/feature/crm

芋道源码 1 year ago
parent
commit
fa1aa51c96
100 changed files with 1289 additions and 1604 deletions
  1. 2 0
      sql/mysql/crm.sql
  2. 0 88
      sql/mysql/crm_menu.sql
  3. 34 34
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
  4. 4 4
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java
  5. 0 61
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/AuditStatusEnum.java
  6. 1 1
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java
  7. 19 7
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
  8. 0 8
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ReturnTypeEnum.java
  9. 34 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmAuditStatusEnum.java
  10. 6 7
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java
  11. 7 8
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneEnum.java
  12. 44 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java
  13. 2 2
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java
  14. 76 9
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
  15. 64 27
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java
  16. 0 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/package-info.java
  17. 0 74
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExportReqVO.java
  18. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessBaseVO.java
  19. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessCreateReqVO.java
  20. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessExcelVO.java
  21. 4 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessPageReqVO.java
  22. 10 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
  23. 2 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java
  24. 2 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateReqVO.java
  25. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusPageReqVO.java
  26. 19 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusQueryVO.java
  27. 33 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusRespVO.java
  28. 9 10
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java
  29. 1 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypePageReqVO.java
  30. 19 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeQueryVO.java
  31. 44 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeRespVO.java
  32. 29 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java
  33. 0 119
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/CrmBusinessStatusController.java
  34. 0 14
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusCreateReqVO.java
  35. 0 30
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExcelVO.java
  36. 0 23
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExportReqVO.java
  37. 0 15
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusRespVO.java
  38. 0 20
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusUpdateReqVO.java
  39. 0 27
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeBaseVO.java
  40. 0 15
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeCreateReqVO.java
  41. 0 32
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExcelVO.java
  42. 0 29
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExportReqVO.java
  43. 0 19
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeRespVO.java
  44. 0 21
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeUpdateReqVO.java
  45. 0 135
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/ContactController.java
  46. 163 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
  47. 0 73
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactBaseVO.java
  48. 0 72
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExcelVO.java
  49. 0 71
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExportReqVO.java
  50. 0 79
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactPageReqVO.java
  51. 0 27
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactRespVO.java
  52. 103 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBaseVO.java
  53. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactCreateReqVO.java
  54. 36 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java
  55. 50 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java
  56. 5 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSimpleRespVO.java
  57. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactTransferReqVO.java
  58. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactUpdateReqVO.java
  59. 58 14
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
  60. 0 37
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExportReqVO.java
  61. 16 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.java
  62. 1 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractBaseVO.java
  63. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractCreateReqVO.java
  64. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java
  65. 4 19
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java
  66. 3 9
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractTransferReqVO.java
  67. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractUpdateReqVO.java
  68. 6 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http
  69. 54 77
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
  70. 7 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java
  71. 5 6
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerPoolConfigController.java
  72. 0 17
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExportReqVO.java
  73. 8 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java
  74. 0 14
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPoolConfigUpdateReqVO.java
  75. 17 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerQueryAllRespVO.java
  76. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java
  77. 1 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigBaseVO.java
  78. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java
  79. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigPageReqVO.java
  80. 5 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigRespVO.java
  81. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigUpdateReqVO.java
  82. 1 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigBaseVO.java
  83. 1 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigRespVO.java
  84. 38 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigSaveReqVO.java
  85. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.http
  86. 20 76
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java
  87. 3 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/vo/CrmPermissionBaseVO.java
  88. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/vo/CrmPermissionRespVO.java
  89. 2 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/vo/CrmPermissionUpdateReqVO.java
  90. 2 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivableBaseVO.java
  91. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivableExcelVO.java
  92. 2 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivablePlanBaseVO.java
  93. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivablePlanExcelVO.java
  94. 21 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java
  95. 6 10
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java
  96. 26 11
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java
  97. 72 9
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java
  98. 34 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java
  99. 28 53
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java
  100. 8 12
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerLimitConfigConvert.java

+ 2 - 0
sql/mysql/crm.sql

@@ -1 +1,3 @@
 SET NAMES utf8mb4;
+-- `ruoyi-vue-pro`.crm_contact definition
+

+ 0 - 88
sql/mysql/crm_menu.sql

@@ -1,88 +0,0 @@
--- ----------------------------
--- 客户公海配置
--- ----------------------------
--- 菜单 SQL
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status, component_name
-)
-VALUES (
-   '客户公海配置', '', 2, 0, 2397,
-   'customer-pool-config', 'ep:data-analysis', 'crm/customerPoolConf/index', 0, 'CustomerPoolConf'
-);
-
--- 按钮父菜单ID
--- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
-SELECT @parentId := LAST_INSERT_ID();
-
--- 按钮 SQL
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status
-)
-VALUES (
-   '客户公海配置保存', 'crm:customer-pool-config:update', 3, 1, @parentId,
-   '', '', '', 0
-);
-
-
-
-
--- ----------------------------
--- 客户限制配置管理
--- ----------------------------
--- 菜单 SQL
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status, component_name
-)
-VALUES (
-   '客户限制配置管理', '', 2, 0, 2397,
-   'customer-limit-config', '', 'crm/customerLimitConfig/index', 0, 'CrmCustomerLimitConfig'
-);
-
--- 按钮父菜单ID
--- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
-SELECT @parentId := LAST_INSERT_ID();
-
--- 按钮 SQL
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status
-)
-VALUES (
-   '客户限制配置查询', 'crm:customer-limit-config:query', 3, 1, @parentId,
-   '', '', '', 0
-);
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status
-)
-VALUES (
-   '客户限制配置创建', 'crm:customer-limit-config:create', 3, 2, @parentId,
-   '', '', '', 0
-);
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status
-)
-VALUES (
-   '客户限制配置更新', 'crm:customer-limit-config:update', 3, 3, @parentId,
-   '', '', '', 0
-);
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status
-)
-VALUES (
-   '客户限制配置删除', 'crm:customer-limit-config:delete', 3, 4, @parentId,
-   '', '', '', 0
-);
-INSERT INTO system_menu(
-    name, permission, type, sort, parent_id,
-    path, icon, component, status
-)
-VALUES (
-   '客户限制配置导出', 'crm:customer-limit-config:export', 3, 5, @parentId,
-   '', '', '', 0
-);

+ 34 - 34
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java

@@ -73,6 +73,23 @@ public class CollectionUtils {
         return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList());
     }
 
+    public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
+                                                      Function<T, ? extends Stream<? extends U>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new ArrayList<>();
+        }
+        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
+    }
+
+    public static <T, U, R> List<R> convertListByFlatMap(Collection<T> from,
+                                                         Function<? super T, ? extends U> mapper,
+                                                         Function<U, ? extends Stream<? extends R>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new ArrayList<>();
+        }
+        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
+    }
+
     public static <K, V> List<V> mergeValuesFromMap(Map<K, List<V>> map) {
         return map.values()
                 .stream()
@@ -101,6 +118,23 @@ public class CollectionUtils {
         return from.stream().filter(filter).collect(Collectors.toMap(keyFunc, v -> v));
     }
 
+    public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
+                                                    Function<T, ? extends Stream<? extends U>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new HashSet<>();
+        }
+        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
+    }
+
+    public static <T, U, R> Set<R> convertSetByFlatMap(Collection<T> from,
+                                                       Function<? super T, ? extends U> mapper,
+                                                       Function<U, ? extends Stream<? extends R>> func) {
+        if (CollUtil.isEmpty(from)) {
+            return new HashSet<>();
+        }
+        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
+    }
+
     public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) {
         if (CollUtil.isEmpty(from)) {
             return new HashMap<>();
@@ -272,38 +306,4 @@ public class CollectionUtils {
         return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
     }
 
-    public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
-                                                      Function<T, ? extends Stream<? extends U>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <T, U, R> List<R> convertListByFlatMap(Collection<T> from,
-                                                         Function<? super T, ? extends U> mapper,
-                                                         Function<U, ? extends Stream<? extends R>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
-                                                    Function<T, ? extends Stream<? extends U>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
-    public static <T, U, R> Set<R> convertSetByFlatMap(Collection<T> from,
-                                                       Function<? super T, ? extends U> mapper,
-                                                       Function<U, ? extends Stream<? extends R>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
 }

+ 4 - 4
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.common.util.spring;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ArrayUtil;
-import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.reflect.MethodSignature;
 import org.springframework.core.DefaultParameterNameDiscoverer;
 import org.springframework.core.ParameterNameDiscoverer;
@@ -25,7 +25,7 @@ import java.util.Map;
 public class SpringExpressionUtils {
 
     /**
-     * spel表达式解析器
+     * Spring EL 表达式解析器
      */
     private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
     /**
@@ -43,7 +43,7 @@ public class SpringExpressionUtils {
      * @param expressionString EL 表达式数组
      * @return 执行界面
      */
-    public static Object parseExpression(ProceedingJoinPoint joinPoint, String expressionString) {
+    public static Object parseExpression(JoinPoint joinPoint, String expressionString) {
         Map<String, Object> result = parseExpressions(joinPoint, Collections.singletonList(expressionString));
         return result.get(expressionString);
     }
@@ -55,7 +55,7 @@ public class SpringExpressionUtils {
      * @param expressionStrings EL 表达式数组
      * @return 结果,key 为表达式,value 为对应值
      */
-    public static Map<String, Object> parseExpressions(ProceedingJoinPoint joinPoint, List<String> expressionStrings) {
+    public static Map<String, Object> parseExpressions(JoinPoint joinPoint, List<String> expressionStrings) {
         // 如果为空,则不进行解析
         if (CollUtil.isEmpty(expressionStrings)) {
             return MapUtil.newHashMap();

+ 0 - 61
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/AuditStatusEnum.java

@@ -1,61 +0,0 @@
-package cn.iocoder.yudao.module.crm.enums;
-
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-
-import java.util.Arrays;
-
-// TODO @liuhongfeng:这个状态,还是搞成专属 CrmReceivableDO 专属的 status;
-/**
- * 流程审批状态枚举类
- * 0 未审核 1 审核通过 2 审核拒绝 3 审核中 4 已撤回 TODO @liuhongfeng:这一行可以删除,因为已经有枚举属性了哈;
- * @author 赤焰
- */
-// TODO @liuhongfeng:可以使用 @Getter、@AllArgsConstructor 简化 get、构造方法
-public enum AuditStatusEnum implements IntArrayValuable {
-
-    // TODO @liuhongfeng:草稿 0;10 审核中;20 审核通过;30 审核拒绝;40 已撤回;主要是留好间隙,万一每个地方要做点拓展; 然后,枚举字段的顺序调整下,审批中,一定要放两个审批通过、拒绝前面哈;
-    /**
-     * 未审批
-     */
-    AUDIT_NEW(0, "未审批"),
-    /**
-     * 审核通过
-     */
-	AUDIT_FINISH(1, "审核通过"),
-    /**
-     * 审核拒绝
-     */
-	AUDIT_REJECT(2, "审核拒绝"),
-    /**
-     * 审核中
-     */
-    AUDIT_DOING(3, "审核中"),
-	/**
-	 * 已撤回
-	 */
-	AUDIT_RETURN(4, "已撤回");
-
-    // TODO liuhongfeng:value 改成 status;desc 改成 name;
-    private final Integer value;
-    private final String desc;
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AuditStatusEnum::getValue).toArray();
-
-    AuditStatusEnum(Integer value, String desc) {
-        this.value = value;
-        this.desc = desc;
-    }
-
-    public Integer getValue() {
-        return value;
-    }
-
-    public String getDesc() {
-        return desc;
-    }
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-}

+ 1 - 1
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java

@@ -11,6 +11,6 @@ public interface DictTypeConstants {
     String CRM_CUSTOMER_INDUSTRY = "crm_customer_industry"; // CRM 客户所属行业
     String CRM_CUSTOMER_LEVEL = "crm_customer_level"; // CRM 客户等级
     String CRM_CUSTOMER_SOURCE = "crm_customer_source"; // CRM 客户来源
-    String CRM_RECEIVABLE_CHECK_STATUS = "crm_receivable_check_status"; // CRM 审批状态
+    String CRM_AUDIT_STATUS = "crm_audit_status"; // CRM 审批状态
 
 }

+ 19 - 7
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java

@@ -20,8 +20,6 @@ public interface ErrorCodeConstants {
 
     // TODO @lilleo:商机状态、商机类型,都单独错误码段
 
-    ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_002_001, "商机状态类型不存在");
-    ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_002_002, "商机状态不存在");
 
     // ========== 联系人管理 1-020-003-000 ==========
     ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
@@ -34,18 +32,22 @@ public interface ErrorCodeConstants {
 
     // ========== 客户管理 1_020_006_000 ==========
     ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在");
-    ErrorCode CUSTOMER_OWNER_EXISTS = new ErrorCode(1_020_006_001, "客户已存在所属负责人");
-    ErrorCode CUSTOMER_LOCKED = new ErrorCode(1_020_006_002, "客户状态已锁定");
+    ErrorCode CUSTOMER_OWNER_EXISTS = new ErrorCode(1_020_006_001, "客户【{}】已存在所属负责人");
+    ErrorCode CUSTOMER_LOCKED = new ErrorCode(1_020_006_002, "客户【{}】状态已锁定");
     ErrorCode CUSTOMER_ALREADY_DEAL = new ErrorCode(1_020_006_003, "客户已交易");
-    // TODO @wanwan:这 2 个单独配置段噢
-    ErrorCode CUSTOMER_POOL_CONFIG_ERROR = new ErrorCode(1_020_006_001, "客户公海规则设置不正确");
-    ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_006_002, "客户限制配置不存在");
+    ErrorCode CUSTOMER_IN_POOL = new ErrorCode(1_020_006_004, "客户【{}】放入公海失败,原因:已经是公海客户");
+    ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定");
+    ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常");
 
     // ========== 权限管理 1_020_007_000 ==========
     ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在");
     ErrorCode CRM_PERMISSION_DENIED = new ErrorCode(1_020_007_001, "{}操作失败,原因:没有权限");
     ErrorCode CRM_PERMISSION_MODEL_NOT_EXISTS = new ErrorCode(1_020_007_002, "{}不存在");
     ErrorCode CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS = new ErrorCode(1_020_007_003, "{}操作失败,原因:转移对象已经是该负责人");
+    ErrorCode CRM_PERMISSION_DELETE_FAIL = new ErrorCode(1_020_007_004, "删除数据权限失败,原因:批量删除权限的时候,只能属于同一个 bizId 下");
+    ErrorCode CRM_PERMISSION_DELETE_FAIL_EXIST_OWNER = new ErrorCode(1_020_007_005, "删除数据权限失败,原因:存在负责人");
+    ErrorCode CRM_PERMISSION_DELETE_DENIED = new ErrorCode(1_020_007_006, "删除数据权限失败,原因:没有权限");
+    ErrorCode CRM_PERMISSION_DELETE_SELF_PERMISSION_FAIL_EXIST_OWNER = new ErrorCode(1_020_007_007, "删除数据权限失败,原因:不能删除负责人");
 
     // ========== 产品 1_020_008_000 ==========
     ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_020_008_000, "产品不存在");
@@ -54,4 +56,14 @@ public interface ErrorCodeConstants {
     // ========== 产品分类 1_020_009_000 ==========
     ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_020_009_000, "产品分类不存在");
 
+    // ========== 商机状态类型 1_020_010_000 ==========
+    ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_010_000, "商机状态类型不存在");
+    ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态类型名称已存在");
+
+    // ========== 商机状态 1_020_011_000 ==========
+    ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_011_000, "商机状态不存在");
+
+    // ========== 客户公海规则设置 1_020_011_000 ==========
+    ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_012_000, "客户限制配置不存在");
+
 }

+ 0 - 8
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ReturnTypeEnum.java

@@ -1,8 +0,0 @@
-package cn.iocoder.yudao.module.crm.enums;
-
-// TODO @liuhongfeng:这个的作用是?
-/**
- * @author 赤焰
- */
-public enum ReturnTypeEnum {
-}

+ 34 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmAuditStatusEnum.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.crm.enums.common;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * CRM 的审批状态
+ *
+ * @author 赤焰
+ */
+@RequiredArgsConstructor
+@Getter
+public enum CrmAuditStatusEnum implements IntArrayValuable {
+
+    DRAFT(0, "未提交"),
+    PROCESS(10, "审批中"),
+    APPROVE(20, "审核通过"),
+	REJECT(30, "审核不通过"),
+    CANCEL(40, "已取消");
+
+    private final Integer status;
+    private final String name;
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmAuditStatusEnum::getStatus).toArray();
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+}

+ 6 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmBizTypeEnum.java → yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.framework.enums;
+package cn.iocoder.yudao.module.crm.enums.common;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
@@ -9,7 +9,7 @@ import lombok.RequiredArgsConstructor;
 import java.util.Arrays;
 
 /**
- * Crm 类型枚举
+ * CRM 业务类型枚举
  *
  * @author HUIHUI
  */
@@ -17,15 +17,14 @@ import java.util.Arrays;
 @Getter
 public enum CrmBizTypeEnum implements IntArrayValuable {
 
-    // TODO @puhui999:如果类似 CrmBizPermission 的 bizType 需要为空,可以设置它是数组,参考 Telephone 的 payload
-    CRM_PERMISSION(0, "团队"), // CrmPermissionController 中使用
     CRM_LEADS(1, "线索"),
     CRM_CUSTOMER(2, "客户"),
-    CRM_CONTACTS(3, "联系人"),
-    CRM_BUSINESS(5, "商机"),
-    CRM_CONTRACT(6, "合同");
+    CRM_CONTACT(3, "联系人"),
+    CRM_BUSINESS(4, "商机"),
+    CRM_CONTRACT(5, "合同");
 
     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray();
+
     /**
      * 类型
      */

+ 7 - 8
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerSceneEnum.java → yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.enums.customer;
+package cn.iocoder.yudao.module.crm.enums.common;
 
 import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
@@ -7,20 +7,19 @@ import lombok.Getter;
 
 import java.util.Arrays;
 
-// TODO @puhui999:这个应该是 crm 全局的,不仅仅属于 customer 客户哈;
 /**
- * CRM 客户等级
+ * CRM 列表检索场景
  *
- * @author Wanwan
+ * @author HUIHUI
  */
 @Getter
 @AllArgsConstructor
-public enum CrmCustomerSceneEnum implements IntArrayValuable {
+public enum CrmSceneEnum implements IntArrayValuable {
 
-    OWNER(1, "我负责的客户"),
-    FOLLOW(2, "我关注的客户");
+    OWNER(1, "我负责的"),
+    FOLLOW(2, "我关注的");
 
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerSceneEnum::getType).toArray();
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmSceneEnum::getType).toArray();
 
     /**
      * 场景类型

+ 44 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java

@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.crm.enums.customer;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * CRM 客户限制配置规则类型
+ *
+ * @author Wanwan
+ */
+@Getter
+@AllArgsConstructor
+public enum CrmCustomerLimitConfigTypeEnum implements IntArrayValuable {
+
+    /**
+     * 拥有客户数限制
+     */
+    CUSTOMER_QUANTITY_LIMIT(1, "拥有客户数限制"),
+    /**
+     * 锁定客户数限制
+     */
+    CUSTOMER_LOCK_LIMIT(2, "锁定客户数限制"),
+    ;
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getCode).toArray();
+
+    /**
+     * 状态
+     */
+    private final Integer code;
+    /**
+     * 状态名
+     */
+    private final String name;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+}

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmPermissionLevelEnum.java → yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.framework.enums;
+package cn.iocoder.yudao.module.crm.enums.permission;
 
 import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
@@ -8,7 +8,7 @@ import lombok.Getter;
 import java.util.Arrays;
 
 /**
- * Crm 数据权限级别枚举
+ * CRM 数据权限级别枚举
  *
  * @author HUIHUI
  */

+ 76 - 9
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java

@@ -1,14 +1,24 @@
 package cn.iocoder.yudao.module.crm.controller.admin.business;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
 import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService;
+import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -21,6 +31,9 @@ import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
 import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@@ -35,6 +48,15 @@ public class CrmBusinessController {
     @Resource
     private CrmBusinessService businessService;
 
+    @Resource
+    private CrmCustomerService customerService;
+
+    @Resource
+    private CrmBusinessStatusTypeService businessStatusTypeService;
+
+    @Resource
+    private CrmBusinessStatusService businessStatusService;
+
     @PostMapping("/create")
     @Operation(summary = "创建商机")
     @PreAuthorize("@ss.hasPermission('crm:business:create')")
@@ -73,27 +95,72 @@ public class CrmBusinessController {
     @PreAuthorize("@ss.hasPermission('crm:business:query')")
     public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPage(@Valid CrmBusinessPageReqVO pageVO) {
         PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(pageVO, getLoginUserId());
-        return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult));
+        if (CollUtil.isEmpty(pageResult.getList())) {
+            return success(PageResult.empty(pageResult.getTotal()));
+        }
+        // 处理客户名称回显
+        // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
+        Set<Long> customerIds = pageResult.getList().stream()
+                .map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet());
+        List<CrmCustomerDO> customerList = customerService.getCustomerList(customerIds);
+        // 处理商机状态类型名称回显
+        Set<Long> statusTypeIds = pageResult.getList().stream()
+                .map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet());
+        CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO();
+        queryStatusTypeVO.setIdList(statusTypeIds);
+        List<CrmBusinessStatusTypeDO> statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO);
+        // 处理商机状态名称回显
+        Set<Long> statusIds = pageResult.getList().stream()
+                .map(CrmBusinessDO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet());
+        CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
+        queryVO.setIdList(statusIds);
+        List<CrmBusinessStatusDO> statusList = businessStatusService.selectList(queryVO);
+        return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList));
+    }
+
+    @GetMapping("/page-by-customer")
+    @Operation(summary = "获得商机分页,基于指定客户")
+    public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmContractPageReqVO pageReqVO) {
+        Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
+        PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomer(pageReqVO);
+        // 处理客户名称回显
+        // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
+        Set<Long> customerIds = pageResult.getList().stream()
+                .map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet());
+        List<CrmCustomerDO> customerList = customerService.getCustomerList(customerIds);
+        // 处理商机状态类型名称回显
+        Set<Long> statusTypeIds = pageResult.getList().stream()
+                .map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet());
+        CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO();
+        queryStatusTypeVO.setIdList(statusTypeIds);
+        List<CrmBusinessStatusTypeDO> statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO);
+        // 处理商机状态名称回显
+        Set<Long> statusIds = pageResult.getList().stream()
+                .map(CrmBusinessDO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet());
+        CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
+        queryVO.setIdList(statusIds);
+        List<CrmBusinessStatusDO> statusList = businessStatusService.selectList(queryVO);
+        return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList));
     }
 
     @GetMapping("/pool-page")
     @Operation(summary = "获得商机公海分页")
     @PreAuthorize("@ss.hasPermission('crm:business:query')")
     public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPoolPage(@Valid CrmBusinessPageReqVO pageVO) {
-        PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(pageVO, CrmPermissionDO.POOL_USER_ID);
-        return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult));
+        // TODO puhui999: 等数据权限完善后再实现
+        return null;
     }
 
     @GetMapping("/export-excel")
     @Operation(summary = "导出商机 Excel")
     @PreAuthorize("@ss.hasPermission('crm:business:export')")
     @OperateLog(type = EXPORT)
-    public void exportBusinessExcel(@Valid CrmBusinessExportReqVO exportReqVO,
+    public void exportBusinessExcel(@Valid CrmBusinessPageReqVO exportReqVO,
                                     HttpServletResponse response) throws IOException {
-        List<CrmBusinessDO> list = businessService.getBusinessList(exportReqVO);
+        PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(exportReqVO, getLoginUserId());
         // 导出 Excel
-        List<CrmBusinessExcelVO> datas = CrmBusinessConvert.INSTANCE.convertList02(list);
-        ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessExcelVO.class, datas);
+        ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessExcelVO.class,
+                CrmBusinessConvert.INSTANCE.convertList02(pageResult.getList()));
     }
 
     @PutMapping("/transfer")

+ 64 - 27
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/CrmBusinessStatusTypeController.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java

@@ -1,14 +1,26 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype;
+package cn.iocoder.yudao.module.crm.controller.admin.business;
 
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.*;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;
+import cn.iocoder.yudao.module.crm.convert.businessstatus.CrmBusinessStatusConvert;
 import cn.iocoder.yudao.module.crm.convert.businessstatustype.CrmBusinessStatusTypeConvert;
-import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO;
-import cn.iocoder.yudao.module.crm.service.businessstatustype.CrmBusinessStatusTypeService;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,11 +34,13 @@ import javax.validation.Valid;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
-// TODO @lilleo:这个模块,可以挪到 business 下;这样我打开 business 包下,就知道,噢~原来里面有 business 商机、有 type 状态类型、status 具体状态;
 @Tag(name = "管理后台 - 商机状态类型")
 @RestController
 @RequestMapping("/crm/business-status-type")
@@ -36,17 +50,23 @@ public class CrmBusinessStatusTypeController {
     @Resource
     private CrmBusinessStatusTypeService businessStatusTypeService;
 
+    @Resource
+    private CrmBusinessStatusService businessStatusService;
+
+    @Resource
+    private DeptApi deptApi;
+
     @PostMapping("/create")
     @Operation(summary = "创建商机状态类型")
     @PreAuthorize("@ss.hasPermission('crm:business-status-type:create')")
-    public CommonResult<Long> createBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeCreateReqVO createReqVO) {
+    public CommonResult<Long> createBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO createReqVO) {
         return success(businessStatusTypeService.createBusinessStatusType(createReqVO));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新商机状态类型")
     @PreAuthorize("@ss.hasPermission('crm:business-status-type:update')")
-    public CommonResult<Boolean> updateBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeUpdateReqVO updateReqVO) {
+    public CommonResult<Boolean> updateBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO updateReqVO) {
         businessStatusTypeService.updateBusinessStatusType(updateReqVO);
         return success(true);
     }
@@ -66,45 +86,62 @@ public class CrmBusinessStatusTypeController {
     @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")
     public CommonResult<CrmBusinessStatusTypeRespVO> getBusinessStatusType(@RequestParam("id") Long id) {
         CrmBusinessStatusTypeDO businessStatusType = businessStatusTypeService.getBusinessStatusType(id);
-        return success(CrmBusinessStatusTypeConvert.INSTANCE.convert(businessStatusType));
-    }
-
-    // TODO @lilleo:这个接口,暂时用不到,可以考虑先删除掉
-    @GetMapping("/list")
-    @Operation(summary = "获得商机状态类型列表")
-    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
-    @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")
-    public CommonResult<List<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypeList(@RequestParam("ids") Collection<Long> ids) {
-        List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypeList(ids);
-        return success(CrmBusinessStatusTypeConvert.INSTANCE.convertList(list));
+        // 处理状态回显
+        // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
+        CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
+        queryVO.setTypeId(id);
+        List<CrmBusinessStatusDO> statusList = businessStatusService.selectList(queryVO);
+        return success(CrmBusinessStatusTypeConvert.INSTANCE.convert(businessStatusType, statusList));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得商机状态类型分页")
     @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")
-    public CommonResult<PageResult<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypePage(@Valid CrmBusinessStatusTypePageReqVO pageVO) {
-        PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageVO);
-        return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult));
+    public CommonResult<PageResult<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypePage(@Valid CrmBusinessStatusTypePageReqVO pageReqVO) {
+        PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);
+        // 处理部门回显
+        // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
+        Set<Long> deptIds = pageResult.getList().stream()
+                .map(CrmBusinessStatusTypeDO::getDeptIds)
+                .filter(Objects::nonNull)
+                .flatMap(Collection::stream)
+                .collect(Collectors.toSet());
+        List<DeptRespDTO> deptList = deptApi.getDeptList(deptIds);
+        return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult, deptList));
     }
 
     @GetMapping("/export-excel")
     @Operation(summary = "导出商机状态类型 Excel")
     @PreAuthorize("@ss.hasPermission('crm:business-status-type:export')")
     @OperateLog(type = EXPORT)
-    public void exportBusinessStatusTypeExcel(@Valid CrmBusinessStatusTypeExportReqVO exportReqVO,
+    public void exportBusinessStatusTypeExcel(@Valid CrmBusinessStatusTypePageReqVO pageReqVO,
               HttpServletResponse response) throws IOException {
-        List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypeList(exportReqVO);
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO).getList();
         // 导出 Excel
-        List<CrmBusinessStatusTypeExcelVO> datas = CrmBusinessStatusTypeConvert.INSTANCE.convertList02(list);
-        ExcelUtils.write(response, "商机状态类型.xls", "数据", CrmBusinessStatusTypeExcelVO.class, datas);
+        ExcelUtils.write(response, "商机状态类型.xls", "数据", CrmBusinessStatusTypeRespVO.class,
+                        BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class));
     }
 
     @GetMapping("/get-simple-list")
     @Operation(summary = "获得商机状态类型列表")
     @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")
     public CommonResult<List<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypeList() {
-        List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypeListByStatus(CommonStatusEnum.ENABLE.getStatus());
-        return success(CrmBusinessStatusTypeConvert.INSTANCE.convertList(list));
+        CrmBusinessStatusTypeQueryVO queryVO = new CrmBusinessStatusTypeQueryVO();
+        queryVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.selectList(queryVO);
+        return success(BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class));
+    }
+
+    // TODO @ljlleo 这个接口,是不是可以和 getBusinessStatusTypeList 合并成一个?
+    @GetMapping("/get-status-list")
+    @Operation(summary = "获得商机状态列表")
+    @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
+    public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusListByTypeId(@RequestParam("typeId") Long typeId) {
+        CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
+        queryVO.setTypeId(typeId);
+        List<CrmBusinessStatusDO> list = businessStatusService.selectList(queryVO);
+        return success(CrmBusinessStatusConvert.INSTANCE.convertList(list));
     }
 
 }

+ 0 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/package-info.java

@@ -1,4 +0,0 @@
-/**
- * 商机(销售机会)
- */
-package cn.iocoder.yudao.module.crm.controller.admin.business;

+ 0 - 74
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExportReqVO.java

@@ -1,74 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - 商机 Excel 导出 Request VO,参数和 CrmBusinessPageReqVO 是一致的")
-@Data
-public class CrmBusinessExportReqVO {
-
-    @Schema(description = "商机名称", example = "李四")
-    private String name;
-
-    @Schema(description = "商机状态类型编号", example = "25714")
-    private Long statusTypeId;
-
-    @Schema(description = "商机状态编号", example = "30320")
-    private Long statusId;
-
-    @Schema(description = "下次联系时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] contactNextTime;
-
-    @Schema(description = "客户编号", example = "10299")
-    private Long customerId;
-
-    @Schema(description = "预计成交日期")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] dealTime;
-
-    @Schema(description = "商机金额", example = "12371")
-    private BigDecimal price;
-
-    @Schema(description = "整单折扣")
-    private BigDecimal discountPercent;
-
-    @Schema(description = "产品总金额", example = "12025")
-    private BigDecimal productPrice;
-
-    @Schema(description = "备注", example = "随便")
-    private String remark;
-
-    @Schema(description = "负责人的用户编号", example = "25562")
-    private Long ownerUserId;
-
-    @Schema(description = "创建时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] createTime;
-
-    @Schema(description = "只读权限的用户编号数组")
-    private String roUserIds;
-
-    @Schema(description = "读写权限的用户编号数组")
-    private String rwUserIds;
-
-    @Schema(description = "1赢单2输单3无效", example = "1")
-    private Integer endStatus;
-
-    @Schema(description = "结束时的备注", example = "你说的对")
-    private String endRemark;
-
-    @Schema(description = "最后跟进时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] contactLastTime;
-
-    @Schema(description = "跟进状态", example = "1")
-    private Integer followUpStatus;
-
-}

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessBaseVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessBaseVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessCreateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessCreateReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExcelVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessExcelVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
 import com.alibaba.excel.annotation.ExcelProperty;
 import lombok.Data;

+ 4 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessPageReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessPageReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -15,4 +15,7 @@ public class CrmBusinessPageReqVO extends PageParam {
     @Schema(description = "商机名称", example = "李四")
     private String name;
 
+    @Schema(description = "客户编号", example = "10795")
+    private Long customerId;
+
 }

+ 10 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessRespVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
@@ -16,4 +16,13 @@ public class CrmBusinessRespVO extends CrmBusinessBaseVO {
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
+    @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+    private String customerName;
+
+    @Schema(description = "状态类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中")
+    private String statusTypeName;
+
+    @Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "跟进中")
+    private String statusName;
+
 }

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessTransferReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java

@@ -1,6 +1,6 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 

+ 2 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessUpdateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateReqVO.java

@@ -1,5 +1,6 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessBaseVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusPageReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusPageReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -12,7 +12,4 @@ import lombok.ToString;
 @ToString(callSuper = true)
 public class CrmBusinessStatusPageReqVO extends PageParam {
 
-    @Schema(description = "状态类型编号", example = "22882")
-    private Long typeId;
-
 }

+ 19 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusQueryVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Collection;
+
+@Schema(description = "管理后台 - 商机状态 Query VO")
+@Data
+@ToString(callSuper = true)
+public class CrmBusinessStatusQueryVO {
+
+    @Schema(description = "主键集合")
+    private Collection<Long> idList;
+
+    @Schema(description = "状态类型编号")
+    private Long typeId;
+}

+ 33 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusRespVO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 商机状态 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class CrmBusinessStatusRespVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899")
+    @ExcelProperty("主键")
+    private Long id;
+
+    @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139")
+    @ExcelProperty("状态类型编号")
+    private Long typeId;
+
+    @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+    @ExcelProperty("状态名")
+    private String name;
+
+    @Schema(description = "赢单率")
+    @ExcelProperty("赢单率")
+    private String percent;
+
+    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("排序")
+    private Integer sort;
+
+}

+ 9 - 10
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusBaseVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java

@@ -1,25 +1,24 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 
-/**
- * 商机状态 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
+@Schema(description = "管理后台 - 商机状态新增/修改 Request VO")
 @Data
-public class CrmBusinessStatusBaseVO {
+public class CrmBusinessStatusSaveReqVO {
 
-    // TODO @lilleo:example 要写下
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899")
+    private Long id;
 
-    @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22882")
+    @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139")
     @NotNull(message = "状态类型编号不能为空")
     private Long typeId;
 
-    @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
-    @NotNull(message = "状态名不能为空")
+    @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+    @NotEmpty(message = "状态名不能为空")
     private String name;
 
     // TODO @lilleo:percent 应该是 Integer;

+ 1 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypePageReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypePageReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -12,10 +12,4 @@ import lombok.ToString;
 @ToString(callSuper = true)
 public class CrmBusinessStatusTypePageReqVO extends PageParam {
 
-    @Schema(description = "状态类型名", example = "芋艿")
-    private String name;
-
-    @Schema(description = "开启状态", example = "1")
-    private Boolean status;
-
 }

+ 19 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeQueryVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Collection;
+
+@Schema(description = "管理后台 - 商机状态类型 Query VO")
+@Data
+@ToString(callSuper = true)
+public class CrmBusinessStatusTypeQueryVO {
+
+    @Schema(description = "主键集合")
+    private Collection<Long> idList;
+
+    @Schema(description = "状态")
+    private Integer status;
+}

+ 44 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeRespVO.java

@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
+
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - 商机状态类型 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class CrmBusinessStatusTypeRespVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
+    @ExcelProperty("主键")
+    private Long id;
+
+    @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+    @ExcelProperty("状态类型名")
+    private String name;
+
+    @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("使用的部门编号")
+    private List<Long> deptIds;
+    @Schema(description = "使用的部门名称", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("使用的部门名称")
+    private List<String> deptNames;
+
+    @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建人")
+    private String creator;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    // TODO @ljlleo 字段后缀改成 statuses,保持和 deptIds 风格一致;CrmBusinessStatusDO 改成 VO 哈;一般不使用 do 直接返回
+    @Schema(description = "状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<CrmBusinessStatusDO> statusList;
+
+}

+ 29 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
+
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
+import com.google.common.collect.Lists;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+@Schema(description = "管理后台 - 商机状态类型新增/修改 Request VO")
+@Data
+public class CrmBusinessStatusTypeSaveReqVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
+    private Long id;
+
+    @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+    @NotEmpty(message = "状态类型名不能为空")
+    private String name;
+
+    @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<Long> deptIds = Lists.newArrayList();
+
+    // TODO @ljlleo VO 里面,我们不使用默认值哈。这里 Lists.newArrayList() 看看怎么去掉。上面 deptIds 也是类似噢
+    @Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<CrmBusinessStatusSaveReqVO> statusList = Lists.newArrayList();
+
+}

+ 0 - 119
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/CrmBusinessStatusController.java

@@ -1,119 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.*;
-import cn.iocoder.yudao.module.crm.convert.businessstatus.CrmBusinessStatusConvert;
-import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO;
-import cn.iocoder.yudao.module.crm.service.businessstatus.CrmBusinessStatusService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
-
-// TODO @lilleo:这个模块,可以挪到 business 下;这样我打开 business 包下,就知道,噢~原来里面有 business 商机、有 type 状态类型、status 具体状态;
-@Tag(name = "管理后台 - 商机状态")
-@RestController
-@RequestMapping("/crm/business-status")
-@Validated
-public class CrmBusinessStatusController {
-
-    @Resource
-    private CrmBusinessStatusService businessStatusService;
-
-    @PostMapping("/create")
-    @Operation(summary = "创建商机状态")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:create')")
-    public CommonResult<Long> createBusinessStatus(@Valid @RequestBody CrmBusinessStatusCreateReqVO createReqVO) {
-        return success(businessStatusService.createBusinessStatus(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "更新商机状态")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:update')")
-    public CommonResult<Boolean> updateBusinessStatus(@Valid @RequestBody CrmBusinessStatusUpdateReqVO updateReqVO) {
-        businessStatusService.updateBusinessStatus(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "删除商机状态")
-    @Parameter(name = "id", description = "编号", required = true)
-    @PreAuthorize("@ss.hasPermission('crm:business-status:delete')")
-    public CommonResult<Boolean> deleteBusinessStatus(@RequestParam("id") Long id) {
-        businessStatusService.deleteBusinessStatus(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "获得商机状态")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
-    public CommonResult<CrmBusinessStatusRespVO> getBusinessStatus(@RequestParam("id") Long id) {
-        CrmBusinessStatusDO businessStatus = businessStatusService.getBusinessStatus(id);
-        return success(CrmBusinessStatusConvert.INSTANCE.convert(businessStatus));
-    }
-
-    // TODO @lilleo:这个接口,暂时用不到,可以考虑先删除掉
-    @GetMapping("/list")
-    @Operation(summary = "获得商机状态列表")
-    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
-    public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusList(@RequestParam("ids") Collection<Long> ids) {
-        List<CrmBusinessStatusDO> list = businessStatusService.getBusinessStatusList(ids);
-        return success(CrmBusinessStatusConvert.INSTANCE.convertList(list));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "获得商机状态分页")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
-    public CommonResult<PageResult<CrmBusinessStatusRespVO>> getBusinessStatusPage(@Valid CrmBusinessStatusPageReqVO pageVO) {
-        PageResult<CrmBusinessStatusDO> pageResult = businessStatusService.getBusinessStatusPage(pageVO);
-        return success(CrmBusinessStatusConvert.INSTANCE.convertPage(pageResult));
-    }
-
-    @GetMapping("/export-excel")
-    @Operation(summary = "导出商机状态 Excel")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:export')")
-    @OperateLog(type = EXPORT)
-    public void exportBusinessStatusExcel(@Valid CrmBusinessStatusExportReqVO exportReqVO,
-              HttpServletResponse response) throws IOException {
-        List<CrmBusinessStatusDO> list = businessStatusService.getBusinessStatusList(exportReqVO);
-        // 导出 Excel
-        List<CrmBusinessStatusExcelVO> datas = CrmBusinessStatusConvert.INSTANCE.convertList02(list);
-        ExcelUtils.write(response, "商机状态.xls", "数据", CrmBusinessStatusExcelVO.class, datas);
-    }
-
-    // TODO 芋艿:后续再看看
-    @GetMapping("/get-simple-list")
-    @Operation(summary = "获得商机状态列表")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
-    public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusListByTypeId(@RequestParam("typeId") Integer typeId) {
-        List<CrmBusinessStatusDO> list = businessStatusService.getBusinessStatusListByTypeId(typeId);
-        return success(CrmBusinessStatusConvert.INSTANCE.convertList(list));
-    }
-
-    // TODO 芋艿:后续再看看
-    @GetMapping("/get-all-list")
-    @Operation(summary = "获得商机状态列表")
-    @PreAuthorize("@ss.hasPermission('crm:business-status:query')")
-    public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusList() {
-        List<CrmBusinessStatusDO> list = businessStatusService.getBusinessStatusList();
-        return success(CrmBusinessStatusConvert.INSTANCE.convertList(list));
-    }
-
-}

+ 0 - 14
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusCreateReqVO.java

@@ -1,14 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo;
-
-import lombok.*;
-import java.util.*;
-import io.swagger.v3.oas.annotations.media.Schema;
-import javax.validation.constraints.*;
-
-@Schema(description = "管理后台 - 商机状态创建 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessStatusCreateReqVO extends CrmBusinessStatusBaseVO {
-
-}

+ 0 - 30
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExcelVO.java

@@ -1,30 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import lombok.Data;
-
-// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈
-/**
- * 商机状态 Excel VO
- *
- * @author ljlleo
- */
-@Data
-public class CrmBusinessStatusExcelVO {
-
-    @ExcelProperty("主键")
-    private Long id;
-
-    @ExcelProperty("状态类型编号")
-    private Long typeId;
-
-    @ExcelProperty("状态名")
-    private String name;
-
-    @ExcelProperty("赢单率")
-    private String percent;
-
-    @ExcelProperty("排序")
-    private Integer sort;
-
-}

+ 0 - 23
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExportReqVO.java

@@ -1,23 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈
-@Schema(description = "管理后台 - 商机状态 Excel 导出 Request VO,参数和 CrmBusinessStatusPageReqVO 是一致的")
-@Data
-public class CrmBusinessStatusExportReqVO {
-
-    @Schema(description = "状态类型编号", example = "22882")
-    private Long typeId;
-
-    @Schema(description = "状态名", example = "李四")
-    private String name;
-
-    @Schema(description = "赢单率")
-    private String percent;
-
-    @Schema(description = "排序")
-    private Integer sort;
-
-}

+ 0 - 15
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusRespVO.java

@@ -1,15 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-
-@Schema(description = "管理后台 - 商机状态 Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessStatusRespVO extends CrmBusinessStatusBaseVO {
-
-    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6802")
-    private Long id;
-
-}

+ 0 - 20
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusUpdateReqVO.java

@@ -1,20 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "管理后台 - 商机状态更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessStatusUpdateReqVO extends CrmBusinessStatusBaseVO {
-
-    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6802")
-    @NotNull(message = "编号不能为空")
-    private Long id;
-
-}

+ 0 - 27
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeBaseVO.java

@@ -1,27 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-
-/**
- * 商机状态类型 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
-@Data
-public class CrmBusinessStatusTypeBaseVO {
-
-    @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
-    @NotNull(message = "状态类型名不能为空")
-    private String name;
-
-    @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotNull(message = "使用的部门编号不能为空")
-    private String deptIds;
-
-    @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "开启状态不能为空")
-    private Boolean status;
-
-}

+ 0 - 15
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeCreateReqVO.java

@@ -1,15 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-// TODO 状态类型和状态添加,是在一个请求里,所以需要把 CrmBusinessStatusCreateReqVO 融合进来;
-@Schema(description = "管理后台 - 商机状态类型创建 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessStatusTypeCreateReqVO extends CrmBusinessStatusTypeBaseVO {
-
-}

+ 0 - 32
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExcelVO.java

@@ -1,32 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈
-/**
- * 商机状态类型 Excel VO
- *
- * @author ljlleo
- */
-@Data
-public class CrmBusinessStatusTypeExcelVO {
-
-    @ExcelProperty("主键")
-    private Long id;
-
-    @ExcelProperty("状态类型名")
-    private String name;
-
-    @ExcelProperty("使用的部门编号")
-    private String deptIds;
-
-    @ExcelProperty("开启状态")
-    private Boolean status;
-
-    @ExcelProperty("创建时间")
-    private LocalDateTime createTime;
-
-}

+ 0 - 29
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExportReqVO.java

@@ -1,29 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈
-@Schema(description = "管理后台 - 商机状态类型 Excel 导出 Request VO,参数和 CrmBusinessStatusTypePageReqVO 是一致的")
-@Data
-public class CrmBusinessStatusTypeExportReqVO {
-
-    @Schema(description = "状态类型名", example = "芋艿")
-    private String name;
-
-    @Schema(description = "使用的部门编号")
-    private String deptIds;
-
-    @Schema(description = "开启状态", example = "1")
-    private Boolean status;
-
-    @Schema(description = "创建时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] createTime;
-
-}

+ 0 - 19
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeRespVO.java

@@ -1,19 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - 商机状态类型 Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessStatusTypeRespVO extends CrmBusinessStatusTypeBaseVO {
-
-    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "24019")
-    private Long id;
-
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime createTime;
-
-}

+ 0 - 21
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeUpdateReqVO.java

@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import javax.validation.constraints.NotNull;
-
-// TODO 状态类型和状态添加,是在一个请求里,所以需要把 CrmBusinessStatusUpdateReqVO 融合进来;
-@Schema(description = "管理后台 - 商机状态类型更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessStatusTypeUpdateReqVO extends CrmBusinessStatusTypeBaseVO {
-
-    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "24019")
-    @NotNull(message = "主键不能为空")
-    private Long id;
-
-}

+ 0 - 135
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/ContactController.java

@@ -1,135 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contact;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.NumberUtil;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO;
-import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.service.contact.ContactService;
-import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import com.google.common.collect.Lists;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
-import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
-
-// TODO @zya:crm 所有的类,dou带 Crm 前缀,因为它的名字太通用了,可能和后续的 erp 之类的冲突
-@Tag(name = "管理后台 - CRM 联系人")
-@RestController
-@RequestMapping("/crm/contact")
-@Validated
-public class ContactController {
-
-    @Resource
-    private ContactService contactService;
-    // TODO @zyna:模块内,注入的变量,不用带 crm 前缀哈
-    @Resource
-    private CrmCustomerService crmCustomerService;
-
-    @Resource
-    private AdminUserApi adminUserApi;
-
-    @PostMapping("/create")
-    @Operation(summary = "创建联系人")
-    @PreAuthorize("@ss.hasPermission('crm:contact:create')")
-    public CommonResult<Long> createContact(@Valid @RequestBody ContactCreateReqVO createReqVO) {
-        return success(contactService.createContact(createReqVO, getLoginUserId()));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "更新联系人")
-    @PreAuthorize("@ss.hasPermission('crm:contact:update')")
-    public CommonResult<Boolean> updateContact(@Valid @RequestBody ContactUpdateReqVO updateReqVO) {
-        contactService.updateContact(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "删除联系人")
-    @Parameter(name = "id", description = "编号", required = true)
-    @PreAuthorize("@ss.hasPermission('crm:contact:delete')")
-    public CommonResult<Boolean> deleteContact(@RequestParam("id") Long id) {
-        contactService.deleteContact(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "获得联系人")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('crm:contact:query')")
-    public CommonResult<ContactRespVO> getContact(@RequestParam("id") Long id) {
-        ContactDO contact = contactService.getContact(id);
-        // TODO @zyna:需要考虑 null 的情况;
-        ContactRespVO contactRespVO  = ContactConvert.INSTANCE.convert(contact);
-        // TODO @zyna:可以把数据读完后,convert 统一交给 ContactConvert,让 controller 更简洁;而 convert 专门去做一些转换逻辑
-        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList(
-                NumberUtil.parseLong(contact.getCreator()))));
-        contactRespVO.setCreatorName(Optional.ofNullable(userMap.get(NumberUtil.parseLong(contact.getCreator()))).map(AdminUserRespDTO::getNickname).orElse(null));
-        contactRespVO.setCustomerName(Optional.ofNullable(crmCustomerService.getCustomer(contact.getCustomerId())).map(CrmCustomerDO::getName).orElse(null));
-        return success(contactRespVO);
-    }
-
-    // TODO @zyna:url 使用中划线噢;然后,单词的拼写也要注意呀,AllList 是不是更好呀;
-    @GetMapping("/simpleAlllist")
-    @Operation(summary = "获得联系人列表")
-    @PreAuthorize("@ss.hasPermission('crm:contact:query')")
-    public CommonResult<List<ContactSimpleRespVO>> simpleAlllist() {
-        // TODO @zyna:方法名改成,getContactList;方法命名,要动名词,get 动词;all 可以去掉,因为没条件,自然是全部
-        List<ContactDO> list = contactService.allContactList();
-        return success(ContactConvert.INSTANCE.convertAllList(list));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "获得联系人分页")
-    @PreAuthorize("@ss.hasPermission('crm:contact:query')")
-    public CommonResult<PageResult<ContactRespVO>> getContactPage(@Valid ContactPageReqVO pageVO) {
-        PageResult<ContactDO> pageData = contactService.getContactPage(pageVO);
-        PageResult<ContactRespVO> pageResult =ContactConvert.INSTANCE.convertPage(pageData);
-        // TODO @zyna:需要考虑 null 的情况;
-        // TODO @zyna:可以把数据读完后,convert 统一交给 ContactConvert,让 controller 更简洁;而 convert 专门去做一些转换逻辑
-        //待接口实现后修改
-        List<CrmCustomerDO> crmCustomerDOList = crmCustomerService.getCustomerList(new CrmCustomerExportReqVO());
-        Map<Long,CrmCustomerDO> crmCustomerDOMap = crmCustomerDOList.stream().collect(Collectors.toMap(CrmCustomerDO::getId,v->v));
-        pageResult.getList().forEach(item -> {
-            item.setCustomerName(Optional.ofNullable(crmCustomerDOMap.get(item.getCustomerId())).map(CrmCustomerDO::getName).orElse(null));
-        });
-        return success(pageResult);
-    }
-
-    // TODO @zyna:可以看下新的导出写法,这里调整下
-    @GetMapping("/export-excel")
-    @Operation(summary = "导出联系人 Excel")
-    @PreAuthorize("@ss.hasPermission('crm:contact:export')")
-    @OperateLog(type = EXPORT)
-    public void exportContactExcel(@Valid ContactExportReqVO exportReqVO,
-              HttpServletResponse response) throws IOException {
-        List<ContactDO> list = contactService.getContactList(exportReqVO);
-        // 导出 Excel
-        List<ContactExcelVO> datas = ContactConvert.INSTANCE.convertList02(list);
-        ExcelUtils.write(response, "crm联系人.xls", "数据", ContactExcelVO.class, datas);
-    }
-
-}

+ 163 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java

@@ -0,0 +1,163 @@
+package cn.iocoder.yudao.module.crm.controller.admin.contact;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.NumberUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
+import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants;
+import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
+import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import com.google.common.collect.Lists;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Tag(name = "管理后台 - CRM 联系人")
+@RestController
+@RequestMapping("/crm/contact")
+@Validated
+@Slf4j
+public class CrmContactController {
+
+    @Resource
+    private CrmContactService contactService;
+    @Resource
+    private CrmCustomerService customerService;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建联系人")
+    @PreAuthorize("@ss.hasPermission('crm:contact:create')")
+    public CommonResult<Long> createContact(@Valid @RequestBody CrmContactCreateReqVO createReqVO) {
+        return success(contactService.createContact(createReqVO, getLoginUserId()));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新联系人")
+    @PreAuthorize("@ss.hasPermission('crm:contact:update')")
+    public CommonResult<Boolean> updateContact(@Valid @RequestBody CrmContactUpdateReqVO updateReqVO) {
+        contactService.updateContact(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除联系人")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('crm:contact:delete')")
+    public CommonResult<Boolean> deleteContact(@RequestParam("id") Long id) {
+        contactService.deleteContact(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得联系人")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('crm:contact:query')")
+    public CommonResult<CrmContactRespVO> getContact(@RequestParam("id") Long id) {
+        CrmContactDO contact = contactService.getContact(id);
+        if (contact == null) {
+            throw exception(ErrorCodeConstants.CONTACT_NOT_EXISTS);
+        }
+        // 1. 获取用户名
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList(
+                NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId())));
+        // 2. 获取客户信息
+        List<CrmCustomerDO> customerList = customerService.getCustomerList(Collections.singletonList(contact.getCustomerId()));
+        // 3. 直属上级
+        List<CrmContactDO> parentContactList = contactService.getContactList(Collections.singletonList(contact.getParentId()));
+        return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList));
+    }
+
+    @GetMapping("/simple-all-list")
+    @Operation(summary = "获得联系人列表")
+    @PreAuthorize("@ss.hasPermission('crm:contact:query')")
+    public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() {
+        List<CrmContactDO> list = contactService.getContactList();
+        return success(ContactConvert.INSTANCE.convertAllList(list));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得联系人分页")
+    @PreAuthorize("@ss.hasPermission('crm:contact:query')")
+    public CommonResult<PageResult<CrmContactRespVO>> getContactPage(@Valid CrmContactPageReqVO pageVO) {
+        PageResult<CrmContactDO> pageResult = contactService.getContactPage(pageVO);
+        return success(convertDetailContactPage(pageResult));
+    }
+
+    @GetMapping("/page-by-customer")
+    @Operation(summary = "获得联系人分页,基于指定客户")
+    public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) {
+        Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
+        PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomer(pageVO);
+        return success(convertDetailContactPage(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出联系人 Excel")
+    @PreAuthorize("@ss.hasPermission('crm:contact:export')")
+    @OperateLog(type = EXPORT)
+    public void exportContactExcel(@Valid CrmContactPageReqVO exportReqVO,
+                                   HttpServletResponse response) throws IOException {
+        exportReqVO.setPageNo(PageParam.PAGE_SIZE_NONE);
+        PageResult<CrmContactDO> pageResult = contactService.getContactPage(exportReqVO);
+        ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
+                convertDetailContactPage(pageResult).getList());
+    }
+
+    /**
+     * 转换成详细的联系人分页,即读取关联信息
+     *
+     * @param pageResult 联系人分页
+     * @return 详细的联系人分页
+     */
+    private PageResult<CrmContactRespVO> convertDetailContactPage(PageResult<CrmContactDO> pageResult) {
+        List<CrmContactDO> contactList = pageResult.getList();
+        if (CollUtil.isEmpty(contactList)) {
+            return PageResult.empty(pageResult.getTotal());
+        }
+        // 1. 获取客户列表
+        List<CrmCustomerDO> crmCustomerDOList = customerService.getCustomerList(
+                convertSet(contactList, CrmContactDO::getCustomerId));
+        // 2. 获取创建人、负责人列表
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList,
+                contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
+        // 3. 直属上级
+        List<CrmContactDO> parentContactList = contactService.getContactList(
+                convertSet(contactList, CrmContactDO::getParentId));
+        return ContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList);
+    }
+
+}

+ 0 - 73
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactBaseVO.java

@@ -1,73 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-// TODO zyna:参考新的 vo,重新拆分下 VO
-/**
- * CRM 联系人 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
-@Data
-public class ContactBaseVO {
-
-    // TODO @zyna:example 最好都写下
-    // TODO @zyna:必要的字段校验,例如说 @Mobile,@Emal 等等
-
-    @Schema(description = "下次联系时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
-    private LocalDateTime nextTime;
-
-    @Schema(description = "手机号")
-    private String mobile;
-
-    @Schema(description = "电话")
-    private String telephone;
-
-    @Schema(description = "电子邮箱")
-    private String email;
-
-    @Schema(description = "客户编号", example = "10795")
-    private Long customerId;
-
-    @Schema(description = "地址")
-    private String address;
-
-    @Schema(description = "备注", example = "你说的对")
-    private String remark;
-
-    @Schema(description = "最后跟进时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime lastTime;
-
-    @Schema(description = "直属上级", example = "23457")
-    private Long parentId;
-
-    @Schema(description = "姓名", example = "芋艿")
-    private String name;
-
-    @Schema(description = "职位")
-    private String post;
-
-    @Schema(description = "QQ")
-    private Long qq;
-
-    @Schema(description = "微信")
-    private String webchat;
-
-    @Schema(description = "性别")
-    private Integer sex;
-
-    @Schema(description = "是否关键决策人")
-    private Boolean policyMakers;
-
-    @Schema(description = "负责人用户编号", example = "14334")
-    private String ownerUserId;
-
-}

+ 0 - 72
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExcelVO.java

@@ -1,72 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-// TODO @zyna:参考新的 VO 结构,把 ContactExcelVO 融合到 ContactRespVO 中
-/**
- * crm联系人 Excel VO
- *
- * @author 芋道源码
- */
-@Data
-@Deprecated
-public class ContactExcelVO {
-
-    @ExcelProperty("下次联系时间")
-    private LocalDateTime nextTime;
-
-    @ExcelProperty("手机号")
-    private String mobile;
-
-    @ExcelProperty("电话")
-    private String telephone;
-
-    @ExcelProperty("电子邮箱")
-    private String email;
-
-    @ExcelProperty("客户编号")
-    private Long customerId;
-
-    @ExcelProperty("地址")
-    private String address;
-
-    @ExcelProperty("备注")
-    private String remark;
-
-    @ExcelProperty("创建时间")
-    private LocalDateTime createTime;
-
-    @ExcelProperty("最后跟进时间")
-    private LocalDateTime lastTime;
-
-    @ExcelProperty("主键")
-    private Long id;
-
-    @ExcelProperty("直属上级")
-    private Long parentId;
-
-    @ExcelProperty("姓名")
-    private String name;
-
-    @ExcelProperty("职位")
-    private String post;
-
-    @ExcelProperty("QQ")
-    private Long qq;
-
-    @ExcelProperty("微信")
-    private String webchat;
-
-    @ExcelProperty("性别")
-    private Integer sex;
-
-    @ExcelProperty("是否关键决策人")
-    private Boolean policyMakers;
-
-    @ExcelProperty("负责人用户编号")
-    private String ownerUserId;
-
-}

+ 0 - 71
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExportReqVO.java

@@ -1,71 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-// TODO @zyna:参考新的 VO 结构,使用 ContactPageReqVO 查询导出的数据
-@Schema(description = "管理后台 - crm联系人 Excel 导出 Request VO,参数和 ContactPageReqVO 是一致的")
-@Data
-@Deprecated
-public class ContactExportReqVO {
-
-    @Schema(description = "下次联系时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] nextTime;
-
-    @Schema(description = "手机号")
-    private String mobile;
-
-    @Schema(description = "电话")
-    private String telephone;
-
-    @Schema(description = "电子邮箱")
-    private String email;
-
-    @Schema(description = "客户编号", example = "10795")
-    private Long customerId;
-
-    @Schema(description = "地址")
-    private String address;
-
-    @Schema(description = "备注", example = "你说的对")
-    private String remark;
-
-    @Schema(description = "创建时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] createTime;
-
-    @Schema(description = "最后跟进时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] lastTime;
-
-    @Schema(description = "直属上级", example = "23457")
-    private Long parentId;
-
-    @Schema(description = "姓名", example = "芋艿")
-    private String name;
-
-    @Schema(description = "职位")
-    private String post;
-
-    @Schema(description = "QQ")
-    private Long qq;
-
-    @Schema(description = "微信")
-    private String webchat;
-
-    @Schema(description = "性别")
-    private Integer sex;
-
-    @Schema(description = "是否关键决策人")
-    private Boolean policyMakers;
-
-    @Schema(description = "负责人用户编号", example = "14334")
-    private String ownerUserId;
-
-}

+ 0 - 79
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactPageReqVO.java

@@ -1,79 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - crm联系人分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ContactPageReqVO extends PageParam {
-
-    // TODO @zyna:筛选条件
-    // ●客户:
-    // ●姓名:
-    // ●手机、电话、座机、QQ、微信、邮箱
-
-    @Schema(description = "下次联系时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] nextTime;
-
-    @Schema(description = "手机号")
-    private String mobile;
-
-    @Schema(description = "电话")
-    private String telephone;
-
-    @Schema(description = "电子邮箱")
-    private String email;
-
-    @Schema(description = "客户编号", example = "10795")
-    private Long customerId;
-
-    @Schema(description = "地址")
-    private String address;
-
-    @Schema(description = "备注", example = "你说的对")
-    private String remark;
-
-    @Schema(description = "创建时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] createTime;
-
-    @Schema(description = "最后跟进时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] lastTime;
-
-    @Schema(description = "直属上级", example = "23457")
-    private Long parentId;
-
-    @Schema(description = "姓名", example = "芋艿")
-    private String name;
-
-    @Schema(description = "职位")
-    private String post;
-
-    @Schema(description = "QQ")
-    private Long qq;
-
-    @Schema(description = "微信")
-    private String webchat;
-
-    @Schema(description = "性别")
-    private Integer sex;
-
-    @Schema(description = "是否关键决策人")
-    private Boolean policyMakers;
-
-    @Schema(description = "负责人用户编号", example = "14334")
-    private String ownerUserId;
-
-}

+ 0 - 27
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactRespVO.java

@@ -1,27 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - CRM 联系人 Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ContactRespVO extends ContactBaseVO {
-
-    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
-    private Long id;
-
-    @Schema(description = "创建时间")
-    private LocalDateTime createTime;
-
-    // TODO  @zyna:example 最好写下;
-
-    @Schema(description = "创建人")
-    private String creatorName;
-
-    @Schema(description = "客户名字")
-    private String customerName;
-
-}

+ 103 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBaseVO.java

@@ -0,0 +1,103 @@
+package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
+
+import cn.iocoder.yudao.framework.common.validation.Mobile;
+import cn.iocoder.yudao.framework.common.validation.Telephone;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+// TODO zyna:要不按照新的,干掉这个 basevo,都放子类里
+/**
+ * CRM 联系人 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class CrmContactBaseVO {
+
+    @ExcelProperty(value = "姓名",order = 1)
+    @Schema(description = "姓名", example = "芋艿")
+    @NotNull(message = "姓名不能为空")
+    private String name;
+
+    @Schema(description = "客户编号", example = "10795")
+    private Long customerId;
+
+    @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
+    @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
+    @Schema(description = "性别")
+    private Integer sex;
+
+    @Schema(description = "职位")
+    @ExcelProperty(value = "职位", order = 3)
+    private String post;
+
+    @Schema(description = "是否关键决策人")
+    @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3)
+    @DictFormat(DictTypeConstants.BOOLEAN_STRING)
+    private Boolean master;
+
+    @Schema(description = "直属上级", example = "23457")
+    private Long parentId;
+
+    @Schema(description = "手机号",example = "1387171766")
+    @Mobile
+    @ExcelProperty(value = "手机号",order = 4)
+    private String mobile;
+
+    @Schema(description = "座机",example = "021-0029922")
+    @Telephone
+    @ExcelProperty(value = "座机",order = 4)
+    private String telephone;
+
+    @ExcelProperty(value = "QQ",order = 4)
+    @Schema(description = "QQ",example = "197272662")
+    private Long qq;
+
+    @ExcelProperty(value = "微信",order = 4)
+    @Schema(description = "微信",example = "zzz3883")
+    private String wechat;
+
+    @Schema(description = "电子邮箱",example = "1111@22.com")
+    @Email
+    @ExcelProperty(value = "邮箱",order = 4)
+    private String email;
+
+    @ExcelProperty(value = "地址",order = 5)
+    @Schema(description = "地址")
+    private String address;
+
+    @Schema(description = "下次联系时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    @ExcelProperty(value = "下次联系时间",order = 6)
+    private LocalDateTime nextTime;
+
+    @Schema(description = "备注", example = "你说的对")
+    @ExcelProperty(value = "备注",order = 6)
+    private String remark;
+
+    @Schema(description = "最后跟进时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ExcelProperty(value = "最后跟进时间",order = 6)
+    private LocalDateTime lastTime;
+
+    @Schema(description = "负责人用户编号", example = "14334")
+    @NotNull(message = "负责人不能为空")
+    private Long ownerUserId;
+
+    @Schema(description = "地区编号", example = "20158")
+    private Integer areaId;
+
+}

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactCreateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactCreateReqVO.java

@@ -9,6 +9,6 @@ import lombok.ToString;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class ContactCreateReqVO extends ContactBaseVO {
+public class CrmContactCreateReqVO extends CrmContactBaseVO {
 
 }

+ 36 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - CRM 联系人分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CrmContactPageReqVO extends PageParam {
+
+    @Schema(description = "姓名", example = "芋艿")
+    private String name;
+
+    @Schema(description = "客户编号", example = "10795")
+    private Long customerId;
+
+    @Schema(description = "手机号", example = "13898273941")
+    private String mobile;
+
+    @Schema(description = "电话", example = "021-383773")
+    private String telephone;
+
+    @Schema(description = "电子邮箱", example = "111@22.com")
+    private String email;
+
+    @Schema(description = "QQ", example = "3882872")
+    private Long qq;
+
+    @Schema(description = "微信", example = "zzZ98373")
+    private String wechat;
+
+}

+ 50 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - CRM 联系人 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@ExcelIgnoreUnannotated
+public class CrmContactRespVO extends CrmContactBaseVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
+    private Long id;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty(value = "创建时间", order = 8)
+    private LocalDateTime createTime;
+
+    @Schema(description = "更新时间")
+    @ExcelProperty(value = "更新时间", order = 8)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "创建人", example = "25682")
+    private String creator;
+
+    @Schema(description = "创建人名字", example = "test")
+    @ExcelProperty(value = "创建人", order = 8)
+    private String creatorName;
+
+    @ExcelProperty(value = "客户名称",order = 2)
+    @Schema(description = "客户名字", example = "test")
+    private String customerName;
+
+    @Schema(description = "负责人", example = "test")
+    @ExcelProperty(value = "负责人", order = 7)
+    private String ownerUserName;
+
+    @Schema(description = "直属上级名", example = "芋头")
+    @ExcelProperty(value = "直属上级", order = 4)
+    private String parentName;
+
+    @Schema(description = "地区名", example = "上海上海市浦东新区")
+    @ExcelProperty(value = "地区", order = 5)
+    private String areaName;
+
+}

+ 5 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactSimpleRespVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSimpleRespVO.java

@@ -4,14 +4,15 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.ToString;
 
-@Schema(description = "管理后台 - CRM 联系人 Response VO")
+@Schema(description = "管理后台 - CRM 联系人的精简 Response VO")
 @Data
 @ToString(callSuper = true)
-public class ContactSimpleRespVO {
-    @Schema(description = "姓名", example = "芋艿") // TODO @zyna:requiredMode = Schema.RequiredMode.REQUIRED;需要空一行;字段的顺序改下,id 在 name 前面,会更干净
-    private String name;
+public class CrmContactSimpleRespVO {
 
     @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
     private Long id;
 
+    @Schema(description = "姓名", example = "芋艿")
+    private String name;
+
 }

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactTransferReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
 
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactUpdateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactUpdateReqVO.java

@@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class ContactUpdateReqVO extends ContactBaseVO {
+public class CrmContactUpdateReqVO extends CrmContactBaseVO {
 
     @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
     @NotNull(message = "主键不能为空")

+ 58 - 14
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/ContractController.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java

@@ -1,13 +1,20 @@
 package cn.iocoder.yudao.module.crm.controller.admin.contract;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
 import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
-import cn.iocoder.yudao.module.crm.service.contract.ContractService;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
+import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -20,8 +27,12 @@ import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
@@ -29,22 +40,27 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
 @RestController
 @RequestMapping("/crm/contract")
 @Validated
-public class ContractController {
+public class CrmContractController {
 
     @Resource
-    private ContractService contractService;
+    private CrmContractService contractService;
+    @Resource
+    private CrmCustomerService customerService;
+
+    @Resource
+    private AdminUserApi adminUserApi;
 
     @PostMapping("/create")
     @Operation(summary = "创建合同")
     @PreAuthorize("@ss.hasPermission('crm:contract:create')")
-    public CommonResult<Long> createContract(@Valid @RequestBody ContractCreateReqVO createReqVO) {
+    public CommonResult<Long> createContract(@Valid @RequestBody CrmContractCreateReqVO createReqVO) {
         return success(contractService.createContract(createReqVO, getLoginUserId()));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新合同")
     @PreAuthorize("@ss.hasPermission('crm:contract:update')")
-    public CommonResult<Boolean> updateContract(@Valid @RequestBody ContractUpdateReqVO updateReqVO) {
+    public CommonResult<Boolean> updateContract(@Valid @RequestBody CrmContractUpdateReqVO updateReqVO) {
         contractService.updateContract(updateReqVO);
         return success(true);
     }
@@ -63,28 +79,56 @@ public class ContractController {
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('crm:contract:query')")
     public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) {
-        ContractDO contract = contractService.getContract(id);
+        CrmContractDO contract = contractService.getContract(id);
         return success(ContractConvert.INSTANCE.convert(contract));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得合同分页")
     @PreAuthorize("@ss.hasPermission('crm:contract:query')")
-    public CommonResult<PageResult<ContractRespVO>> getContractPage(@Valid ContractPageReqVO pageVO) {
-        PageResult<ContractDO> pageResult = contractService.getContractPage(pageVO);
-        return success(ContractConvert.INSTANCE.convertPage(pageResult));
+    public CommonResult<PageResult<ContractRespVO>> getContractPage(@Valid CrmContractPageReqVO pageVO) {
+        PageResult<CrmContractDO> pageResult = contractService.getContractPage(pageVO);
+        return success(convertDetailContractPage(pageResult));
+    }
+
+    @GetMapping("/page-by-customer")
+    @Operation(summary = "获得联系人分页,基于指定客户")
+    public CommonResult<PageResult<ContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) {
+        Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
+        PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomer(pageVO);
+        return success(convertDetailContractPage(pageResult));
     }
 
     @GetMapping("/export-excel")
     @Operation(summary = "导出合同 Excel")
     @PreAuthorize("@ss.hasPermission('crm:contract:export')")
     @OperateLog(type = EXPORT)
-    public void exportContractExcel(@Valid ContractExportReqVO exportReqVO,
+    public void exportContractExcel(@Valid CrmContractPageReqVO exportReqVO,
                                     HttpServletResponse response) throws IOException {
-        List<ContractDO> list = contractService.getContractList(exportReqVO);
+        PageResult<CrmContractDO> pageResult = contractService.getContractPage(exportReqVO);
         // 导出 Excel
-        List<ContractExcelVO> datas = ContractConvert.INSTANCE.convertList02(list);
-        ExcelUtils.write(response, "合同.xls", "数据", ContractExcelVO.class, datas);
+        ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class,
+                ContractConvert.INSTANCE.convertList02(pageResult.getList()));
+    }
+
+    /**
+     * 转换成详细的联系人分页,即读取关联信息
+     *
+     * @param pageResult 联系人分页
+     * @return 详细的联系人分页
+     */
+    private PageResult<ContractRespVO> convertDetailContractPage(PageResult<CrmContractDO> pageResult) {
+        List<CrmContractDO> contactList = pageResult.getList();
+        if (CollUtil.isEmpty(contactList)) {
+            return PageResult.empty(pageResult.getTotal());
+        }
+        // 1. 获取客户列表
+        List<CrmCustomerDO> customerList = customerService.getCustomerList(
+                convertSet(contactList, CrmContractDO::getCustomerId));
+        // 2. 获取创建人、负责人列表
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList,
+                contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
+        return ContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList);
     }
 
     @PutMapping("/transfer")

+ 0 - 37
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExportReqVO.java

@@ -1,37 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - CRM 合同 Excel 导出 Request VO,参数和 ContractPageReqVO 是一致的")
-@Data
-public class ContractExportReqVO {
-
-    @Schema(description = "合同名称", example = "王五")
-    private String name;
-
-    @Schema(description = "客户编号", example = "18336")
-    private Long customerId;
-
-    @Schema(description = "商机编号", example = "10864")
-    private Long businessId;
-
-    @Schema(description = "下单日期")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] orderDate;
-
-    @Schema(description = "合同编号")
-    private String no;
-
-    @Schema(description = "整单折扣")
-    private Integer discountPercent;
-
-    @Schema(description = "产品总金额", example = "19510")
-    private Integer productPrice;
-
-}

+ 16 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.java

@@ -11,7 +11,7 @@ import java.time.LocalDateTime;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class ContractRespVO extends ContractBaseVO {
+public class ContractRespVO extends CrmContractBaseVO {
 
     @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
     private Long id;
@@ -19,4 +19,19 @@ public class ContractRespVO extends ContractBaseVO {
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
+    @Schema(description = "创建人", example = "25682")
+    private String creator;
+
+    @Schema(description = "创建人名字", example = "test")
+    private String creatorName;
+
+    @Schema(description = "客户名字", example = "test")
+    private String customerName;
+
+    @Schema(description = "负责人", example = "test")
+    private String ownerUserName;
+
+    @Schema(description = "审批状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+    private Integer auditStatus;
+
 }

+ 1 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractBaseVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractBaseVO.java

@@ -9,13 +9,12 @@ import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-// TODO @dhb52:所有类,带下 Crm 前缀,避免和别的模块重复
 /**
  * 合同 Base VO,提供给添加、修改、详细的子 VO 使用
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  */
 @Data
-public class ContractBaseVO {
+public class CrmContractBaseVO {
 
     // TODO @dhb52:类似 no 字段的 example 要写xia 哈;
 

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractCreateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractCreateReqVO.java

@@ -9,6 +9,6 @@ import lombok.ToString;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class ContractCreateReqVO extends ContractBaseVO {
+public class CrmContractCreateReqVO extends CrmContractBaseVO {
 
 }

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExcelVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java

@@ -11,7 +11,7 @@ import java.time.LocalDateTime;
  * @author dhb52
  */
 @Data
-public class ContractExcelVO {
+public class CrmContractExcelVO {
 
     @ExcelProperty("合同编号")
     private Long id;

+ 4 - 19
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractPageReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java

@@ -5,17 +5,15 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
 @Schema(description = "管理后台 - CRM 合同分页 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class ContractPageReqVO extends PageParam {
+public class CrmContractPageReqVO extends PageParam {
+
+    @Schema(description = "合同编号", example = "XYZ008")
+    private String no;
 
     @Schema(description = "合同名称", example = "王五")
     private String name;
@@ -26,17 +24,4 @@ public class ContractPageReqVO extends PageParam {
     @Schema(description = "商机编号", example = "10864")
     private Long businessId;
 
-    @Schema(description = "下单日期")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] orderDate;
-
-    @Schema(description = "合同编号")
-    private String no;
-
-    @Schema(description = "整单折扣")
-    private Integer discountPercent;
-
-    @Schema(description = "产品总金额", example = "19510")
-    private Integer productPrice;
-
 }

+ 3 - 9
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractTransferReqVO.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -14,19 +15,12 @@ public class CrmContractTransferReqVO {
     @NotNull(message = "联系人编号不能为空")
     private Long id;
 
-    /**
-     * 新负责人的用户编号
-     */
     @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
     @NotNull(message = "新负责人的用户编号不能为空")
     private Long newOwnerUserId;
 
-    /**
-     * 老负责人加入团队后的权限级别。如果 null 说明移除
-     *
-     * 关联 {@link CrmPermissionLevelEnum}
-     */
     @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @InEnum(value = CrmPermissionLevelEnum.class)
     private Integer oldOwnerPermissionLevel;
 
 }

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractUpdateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractUpdateReqVO.java

@@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class ContractUpdateReqVO extends ContractBaseVO {
+public class CrmContractUpdateReqVO extends CrmContractBaseVO {
 
     @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
     @NotNull(message = "合同编号不能为空")

+ 6 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http

@@ -0,0 +1,6 @@
+### 请求 /update
+GET {{baseUrl}}/crm/customer/page?pageNo=1&pageSize=10&name="张三"
+Authorization: Bearer {{token}}
+tenant-id: {{adminTenentId}}
+
+

+ 54 - 77
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.crm.controller.admin.customer;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@@ -9,20 +8,17 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
-import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import org.mapstruct.ap.internal.util.Collections;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.util.CollectionUtils;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -30,17 +26,17 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
+import java.util.stream.Stream;
 
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+import static java.util.Collections.singletonList;
 
 @Tag(name = "管理后台 - CRM 客户")
 @RestController
@@ -55,8 +51,6 @@ public class CrmCustomerController {
     private DeptApi deptApi;
     @Resource
     private AdminUserApi adminUserApi;
-    @Resource
-    private CrmPermissionService permissionService;
 
     @PostMapping("/create")
     @Operation(summary = "创建客户")
@@ -92,73 +86,38 @@ public class CrmCustomerController {
         if (customer == null) {
             return success(null);
         }
-
         // 2. 拼接数据
-        // 2.1 获取负责人
-        List<CrmPermissionDO> ownerList = permissionService.getPermissionByBizTypeAndBizIdsAndLevel(
-                CrmBizTypeEnum.CRM_CUSTOMER.getType(), Collections.singletonList(customer.getId()),
-                CrmPermissionLevelEnum.OWNER.getLevel());
-        Map<Long, CrmPermissionDO> ownerMap = convertMap(ownerList, CrmPermissionDO::getBizId);
-        // 2.2 获取负责人详情
-        Set<Long> userIds = convertSet(ownerList, CrmPermissionDO::getUserId);
-        userIds.add(Long.parseLong(customer.getCreator())); // 加入创建者
-        List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
-        Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
-        // 2.3 获取部门详情
-        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
-        return success(CrmCustomerConvert.INSTANCE.convert(customer, ownerMap, userMap, deptMap));
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
+                Collections.asSet(Long.valueOf(customer.getCreator()), customer.getOwnerUserId()));
+        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
+        return success(CrmCustomerConvert.INSTANCE.convert(customer, userMap, deptMap));
     }
 
-    // TODO @puhui999:可以在 CrmCustomerPageReqVO 里面加个 pool 参数,为 true 时,代表来自公海客户的分页
     @GetMapping("/page")
     @Operation(summary = "获得客户分页")
     @PreAuthorize("@ss.hasPermission('crm:customer:query')")
     public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
+        // 1. 查询客户分页
         PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO, getLoginUserId());
         if (CollUtil.isEmpty(pageResult.getList())) {
             return success(PageResult.empty(pageResult.getTotal()));
         }
-        // 拼接数据
-        // TODO @puhui999:这块的拼接逻辑,可以和 convertPage 合并下;
-//        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-//                convertSetByFlatMap(pageResult.getList(), user -> Stream.of(NumberUtil.parseLong(user.getCreator()), user.getOwnerUserId())));
-//        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
-//                convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
-        return convertPage(customerService.getCustomerPage(pageVO, getLoginUserId()));
-    }
-
-    // TODO @puhui999:
-    @GetMapping("/pool-page")
-    @Operation(summary = "获得公海客户分页")
-    @PreAuthorize("@ss.hasPermission('crm:customer:query')")
-    public CommonResult<PageResult<CrmCustomerRespVO>> getPoolCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
-        return convertPage(customerService.getCustomerPage(pageVO, CrmPermissionDO.POOL_USER_ID));
-    }
 
-    private CommonResult<PageResult<CrmCustomerRespVO>> convertPage(PageResult<CrmCustomerDO> pageResult) {
         // 2. 拼接数据
-        Set<Long> ids = convertSet(pageResult.getList(), CrmCustomerDO::getId);
-        // 2.1 获取负责人
-        List<CrmPermissionDO> ownerList = permissionService.getPermissionByBizTypeAndBizIdsAndLevel(
-                CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, CrmPermissionLevelEnum.OWNER.getLevel());
-        Map<Long, CrmPermissionDO> ownerMap = convertMap(ownerList, CrmPermissionDO::getBizId);
-        // 2.2 获取负责人详情
-        Set<Long> userIds = convertSet(ownerList, CrmPermissionDO::getUserId);
-        userIds.addAll(convertSet(pageResult.getList(), item -> Long.parseLong(item.getCreator()))); // 加入创建者
-        List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIds);
-        Map<Long, AdminUserRespDTO> userMap = convertMap(userList, AdminUserRespDTO::getId);
-        // 2.3 获取部门详情
-        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
-        return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, ownerMap, userMap, deptMap));
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
+                convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId())));
+        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
+        return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap));
     }
 
     @GetMapping("/export-excel")
     @Operation(summary = "导出客户 Excel")
     @PreAuthorize("@ss.hasPermission('crm:customer:export')")
     @OperateLog(type = EXPORT)
-    public void exportCustomerExcel(@Valid CrmCustomerExportReqVO exportReqVO,
+    public void exportCustomerExcel(@Valid CrmCustomerPageReqVO pageVO,
                                     HttpServletResponse response) throws IOException {
-        List<CrmCustomerDO> list = customerService.getCustomerList(exportReqVO);
+        pageVO.setPageSize(PAGE_SIZE_NONE); // 不分页
+        List<CrmCustomerDO> list = customerService.getCustomerPage(pageVO, getLoginUserId()).getList();
         // 导出 Excel
         List<CrmCustomerExcelVO> datas = CrmCustomerConvert.INSTANCE.convertList02(list);
         ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerExcelVO.class, datas);
@@ -181,30 +140,48 @@ public class CrmCustomerController {
         return success(true);
     }
 
+    // ==================== 公海相关操作 ====================
+
+    @PutMapping("/put-pool")
+    @Operation(summary = "数据放入公海")
+    @Parameter(name = "id", description = "客户编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('crm:customer:update')")
+    public CommonResult<Boolean> putCustomerPool(@RequestParam("id") Long id) {
+        customerService.putCustomerPool(id);
+        return success(true);
+    }
+
     @PutMapping("/receive")
     @Operation(summary = "领取公海客户")
-    // TODO @xiaqing:1)receiveCustomer 方法名字;2)cIds 改成 ids,要加下 @RequestParam,还有 swagger 注解;3)参数非空,使用 validator 校验;4)返回 true 即可;
+    @Parameter(name = "ids", description = "编号数组", required = true, example = "1,2,3")
     @PreAuthorize("@ss.hasPermission('crm:customer:receive')")
-    public CommonResult<String> receiveByIds(List<Long> cIds){
-        // 判断是否为空
-        if(CollectionUtils.isEmpty(cIds))
-            return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),GlobalErrorCodeConstants.BAD_REQUEST.getMsg());
-        // 领取公海任务
-        // TODO @xiaqing:userid,通过 controller 传递给 service,不要在 service 里面获取,无状态
-        customerService.receive(cIds);
-        return success("领取成功");
+    public CommonResult<Boolean> receiveCustomer(@RequestParam(value = "ids") List<Long> ids) {
+        customerService.receiveCustomer(ids, getLoginUserId());
+        return success(true);
     }
 
-    // TODO @xiaqing:1)distributeCustomer 方法名;2)cIds 同上;3)参数校验,同上;4)ownerId 改成 ownerUserId,和别的模块统一;5)返回 true 即可;
-    @PutMapping("/distributeByIds")
+    @PutMapping("/distribute")
     @Operation(summary = "分配公海给对应负责人")
-    @PreAuthorize("@ss.hasPermission('crm:customer:distributeByIds')")
-    public CommonResult<String> distributeByIds(Long ownerId,List<Long>cIds){
-        //判断参数不能为空
-        if(ownerId==null || CollectionUtils.isEmpty(cIds))
-            return error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),GlobalErrorCodeConstants.BAD_REQUEST.getMsg());
-        customerService.distributeByIds(cIds,ownerId);
-        return success("分配成功");
+    @Parameters({
+            @Parameter(name = "ids", description = "客户编号数组", required = true, example = "1,2,3"),
+            @Parameter(name = "ownerUserId", description = "分配的负责人编号", required = true, example = "12345")
+    })
+    @PreAuthorize("@ss.hasPermission('crm:customer:distribute')")
+    public CommonResult<Boolean> distributeCustomer(@RequestParam(value = "ids") List<Long> ids,
+                                                    @RequestParam(value = "ownerUserId") Long ownerUserId) {
+        // 领取公海数据
+        customerService.receiveCustomer(ids, ownerUserId);
+        return success(true);
+    }
+
+    // TODO 芋艿:这个接口要调整下
+    @GetMapping("/query-all-list")
+    @Operation(summary = "查询客户列表")
+    @PreAuthorize("@ss.hasPermission('crm:customer:all')")
+    public CommonResult<List<CrmCustomerQueryAllRespVO>> queryAll(){
+        List<CrmCustomerDO> crmCustomerDOList = customerService.getCustomerList();
+        List<CrmCustomerQueryAllRespVO> data = CrmCustomerConvert.INSTANCE.convertQueryAll(crmCustomerDOList);
+        return success(data);
     }
 
 }

+ 7 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java

@@ -3,13 +3,13 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer;
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLimitConfigCreateReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLimitConfigPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLimitConfigRespVO;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLimitConfigUpdateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO;
 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerLimitConfigConvert;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customerlimitconfig.CrmCustomerLimitConfigDO;
-import cn.iocoder.yudao.module.crm.service.customerlimitconfig.CrmCustomerLimitConfigService;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
+import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerLimitConfigService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
@@ -29,7 +29,7 @@ import java.util.Map;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
 
-@Tag(name = "管理后台 - 客户限制配置")
+@Tag(name = "管理后台 - CRM 客户限制配置")
 @RestController
 @RequestMapping("/crm/customer-limit-config")
 @Validated

+ 5 - 6
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerPoolConfigController.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.module.crm.controller.admin.customer;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPoolConfigRespVO;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPoolConfigUpdateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigSaveReqVO;
 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService;
@@ -34,12 +34,11 @@ public class CrmCustomerPoolConfigController {
         return success(CrmCustomerConvert.INSTANCE.convert(customerPoolConfig));
     }
 
-    // TODO @wanwan:这个请求,搞成 save 哈;
-    @PutMapping("/update")
+    @PutMapping("/save")
     @Operation(summary = "更新客户公海规则设置")
     @PreAuthorize("@ss.hasPermission('crm:customer-pool-config:update')")
-    public CommonResult<Boolean> updateCustomerPoolConfig(@Valid @RequestBody CrmCustomerPoolConfigUpdateReqVO updateReqVO) {
-        customerPoolConfigService.updateCustomerPoolConfig(updateReqVO);
+    public CommonResult<Boolean> saveCustomerPoolConfig(@Valid @RequestBody CrmCustomerPoolConfigSaveReqVO updateReqVO) {
+        customerPoolConfigService.saveCustomerPoolConfig(updateReqVO);
         return success(true);
     }
 

+ 0 - 17
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExportReqVO.java

@@ -1,17 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-// TODO 芋艿:导出最后做,等基本确认的差不多之后;
-@Schema(description = "管理后台 - CRM 客户 Excel 导出 Request VO,参数和 CrmCustomerPageReqVO 是一致的")
-@Data
-public class CrmCustomerExportReqVO {
-
-    @Schema(description = "客户名称", example = "赵六")
-    private String name;
-
-    @Schema(description = "手机", example = "18000000000")
-    private String mobile;
-
-}

+ 8 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java

@@ -1,12 +1,14 @@
 package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerSceneEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmSceneEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
+import javax.validation.constraints.NotNull;
+
 @Schema(description = "管理后台 - CRM 客户分页 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
@@ -31,9 +33,13 @@ public class CrmCustomerPageReqVO extends PageParam {
     /**
      * 场景类型
      *
-     * 关联 {@link CrmCustomerSceneEnum}
+     * 关联 {@link CrmSceneEnum}
      */
     @Schema(description = "场景类型", example = "1")
     private Integer sceneType;
 
+    @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
+    @NotNull(message = "是否为公海数据不能为空")
+    private Boolean pool;
+
 }

+ 0 - 14
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPoolConfigUpdateReqVO.java

@@ -1,14 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@Schema(description = "管理后台 - CRM 客户更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmCustomerPoolConfigUpdateReqVO extends CrmCustomerPoolConfigBaseVO {
-
-}

+ 17 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerQueryAllRespVO.java

@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+// TODO 芋艿:这块要统一下;
+@Schema(description = "管理后台 - CRM 全部客户 Response VO")
+@Data
+public class CrmCustomerQueryAllRespVO{
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
+    private Long id;
+
+    @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+    private String name;
+
+}

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
 
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 

+ 1 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLimitConfigBaseVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigBaseVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
@@ -6,7 +6,6 @@ import lombok.Data;
 import javax.validation.constraints.NotNull;
 import java.util.List;
 
-// TODO @wanwan:vo 下,可以新建一个 limitconfig,放它的 vo;
 /**
  * 客户限制配置 Base VO,提供给添加、修改、详细的子 VO 使用
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLimitConfigCreateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLimitConfigPageReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigPageReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;

+ 5 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLimitConfigRespVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigRespVO.java

@@ -1,5 +1,7 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig;
 
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -18,10 +20,10 @@ public class CrmCustomerLimitConfigRespVO extends CrmCustomerLimitConfigBaseVO {
     private Long id;
 
     @Schema(description = "规则适用人群名称")
-    private String userNames;
+    private List<AdminUserRespDTO> users;
 
     @Schema(description = "规则适用部门名称")
-    private String deptNames;
+    private List<DeptRespDTO> depts;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLimitConfigUpdateReqVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigUpdateReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;

+ 1 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPoolConfigBaseVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigBaseVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
@@ -12,7 +12,6 @@ import javax.validation.constraints.NotNull;
 @Data
 public class CrmCustomerPoolConfigBaseVO {
 
-    // TODO @wanwan:参数校验
     @Schema(description = "是否启用客户公海", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
     @NotNull(message = "是否启用客户公海不能为空")
     private Boolean enabled;

+ 1 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPoolConfigRespVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigRespVO.java

@@ -1,11 +1,10 @@
-package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
-// TODO @wanwan:vo 下,可以新建一个 poolconfig,放它的 vo;
 @Schema(description = "管理后台 - CRM 客户公海规则 Response VO")
 @Data
 @EqualsAndHashCode(callSuper = true)

+ 38 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigSaveReqVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig;
+
+import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.AssertTrue;
+import java.util.Objects;
+
+@Schema(description = "管理后台 - CRM 客户公海配置的保存 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CrmCustomerPoolConfigSaveReqVO extends CrmCustomerPoolConfigBaseVO {
+
+    // TODO @wanwan:AssertTrue 必须 is 开头哈;注意需要 json 忽略下,避免被序列化;
+    @AssertTrue(message = "客户公海规则设置不正确")
+    // TODO @wanwan:这个方法,是不是拆成 2 个,一个校验 contactExpireDays、一个校验 dealExpireDays;
+    public boolean poolEnableValid() {
+        if (!BooleanUtil.isTrue(getEnabled())) {
+            return true;
+        }
+        return ObjectUtil.isAllNotEmpty(getContactExpireDays(), getDealExpireDays());
+    }
+
+    @AssertTrue(message = "客户公海规则设置不正确")
+    // TODO @wanwan:这个方法,是不是改成 isNotifyDaysValid() 更好点?本质校验的是 notifyDays 是否为空
+    public boolean notifyEnableValid() {
+        if (!BooleanUtil.isTrue(getNotifyEnabled())) {
+            return true;
+        }
+        return Objects.nonNull(getNotifyDays());
+    }
+
+}

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.http

@@ -1,5 +1,5 @@
 ### 请求 /add
-PUT {{baseUrl}}/crm/permission/add
+POST {{baseUrl}}/crm/permission/create
 Content-Type: application/json
 Authorization: Bearer {{token}}
 tenant-id: {{adminTenentId}}

+ 20 - 76
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java

@@ -1,16 +1,15 @@
 package cn.iocoder.yudao.module.crm.controller.admin.permission;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO;
 import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO;
 import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
 import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.PostApi;
@@ -29,17 +28,12 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.*;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
 
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
-import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_NOT_EXISTS;
 
-@Tag(name = "管理后台 - CRM 数据权限(数据团队成员操作)")
+@Tag(name = "管理后台 - CRM 数据权限")
 @RestController
 @RequestMapping("/crm/permission")
 @Validated
@@ -55,87 +49,45 @@ public class CrmPermissionController {
     @Resource
     private PostApi postApi;
 
-    // TODO @puhui999:保持统一,create 噢;然后是 PostMapping
-    @PutMapping("/add")
-    @Operation(summary = "添加团队成员")
+    @PostMapping("/create")
+    @Operation(summary = "创建数据权限")
     @PreAuthorize("@ss.hasPermission('crm:permission:create')")
-    @CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId",
-            level = CrmPermissionLevelEnum.OWNER)
+    @CrmPermission(bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId", level = CrmPermissionLevelEnum.OWNER)
     public CommonResult<Boolean> addPermission(@Valid @RequestBody CrmPermissionCreateReqVO reqVO) {
         permissionService.createPermission(CrmPermissionConvert.INSTANCE.convert(reqVO));
         return success(true);
     }
 
-    // TODO @puhui999:领取公海客户,是不是放到客户那更合适哈?
-    @PutMapping("/receive")
-    @Operation(summary = "领取公海数据")
-    @PreAuthorize("@ss.hasPermission('crm:permission:update')")
-    public CommonResult<Boolean> receive(@RequestParam("bizType") Integer bizType, @RequestParam("bizId") Long bizId) {
-        permissionService.receiveBiz(bizType, bizId, getLoginUserId());
-        return success(true);
-    }
-
-    // TODO @puhui999:是不是放到客户那更合适哈?
-    @PutMapping("/put-pool")
-    @Operation(summary = "数据放入公海")
-    @PreAuthorize("@ss.hasPermission('crm:permission:update')")
-    @CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#bizType", bizId = "#bizId"
-            , level = CrmPermissionLevelEnum.OWNER)
-    public CommonResult<Boolean> putPool(@RequestParam(value = "bizType") Integer bizType, @RequestParam("bizId") Long bizId) {
-        permissionService.putPool(bizType, bizId, getLoginUserId());
-        return success(true);
-    }
-
     @PutMapping("/update")
-    @Operation(summary = "编辑团队成员权限")
+    @Operation(summary = "编辑数据权限")
     @PreAuthorize("@ss.hasPermission('crm:permission:update')")
-    @CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#updateReqVO.bizType", bizId = "#updateReqVO.bizId"
+    @CrmPermission(bizTypeValue = "#updateReqVO.bizType", bizId = "#updateReqVO.bizId"
             , level = CrmPermissionLevelEnum.OWNER)
     public CommonResult<Boolean> updatePermission(@Valid @RequestBody CrmPermissionUpdateReqVO updateReqVO) {
         permissionService.updatePermission(updateReqVO);
         return success(true);
     }
 
-    // TODO @puhui999:bizType 和 bizId 是不是不用啦;因为参数校验需要 bizType 和 bizId,可以先查询下,在直接调用方法;不一定都要注解哈;
     @DeleteMapping("/delete")
-    @Operation(summary = "移除团队成员")
-    @Parameters({
-            @Parameter(name = "bizType", description = "CRM 类型", required = true, example = "2"),
-            @Parameter(name = "bizId", description = "CRM 类型数据编号", required = true, example = "1024"),
-            @Parameter(name = "ids", description = "团队成员编号", required = true, example = "1024")
-    })
+    @Operation(summary = "删除数据权限")
+    @Parameter(name = "ids", description = "数据权限编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('crm:permission:delete')")
-    @CrmPermission(bizType = CrmBizTypeEnum.CRM_PERMISSION, bizTypeValue = "#bizType", bizId = "#bizId"
-            , level = CrmPermissionLevelEnum.OWNER) // 为了校验权限请求必须带上 bizType 和  bizId
-    public CommonResult<Boolean> deletePermission(@RequestParam("bizType") Integer bizType,
-                                                  @RequestParam("bizId") Long bizId,
-                                                  @RequestParam("ids") Collection<Long> ids) {
-        permissionService.deletePermission(ids);
+    public CommonResult<Boolean> deletePermission(@RequestParam("ids") Collection<Long> ids) {
+        permissionService.deletePermissionBatch(ids, getLoginUserId());
         return success(true);
     }
 
-    // TODO @puhui999:deleteSelfPermission;尽量归成 crud 这样的操作哈;
-    @DeleteMapping("/quit-team")
-    @Operation(summary = "退出团队")
-    @Parameters({
-            // TODO @puhui999:这个可以拿出来,不用包在 @Parameters 里,在只有一个参数时哈;
-            @Parameter(name = "id", description = "团队成员编号", required = true, example = "1024")
-    })
+    @DeleteMapping("/delete-self")
+    @Operation(summary = "删除自己的数据权限")
+    @Parameter(name = "id", description = "数据权限编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('crm:permission:delete')")
-    public CommonResult<Boolean> deletePermission(@RequestParam("id") Long id) {
-        // 校验数据存在且是自己
-        CrmPermissionDO permission = permissionService.getPermissionByIdAndUserId(id, getLoginUserId());
-        if (permission == null) {
-            throw exception(CRM_PERMISSION_NOT_EXISTS);
-        }
-
-        // 删除
-        permissionService.deletePermission(Collections.singletonList(id));
+    public CommonResult<Boolean> deleteSelfPermission(@RequestParam("id") Long id) {
+        permissionService.deleteSelfPermission(id, getLoginUserId());
         return success(true);
     }
 
     @GetMapping("/list")
-    @Operation(summary = "获取团队成员")
+    @Operation(summary = "获得数据权限列表")
     @Parameters({
             @Parameter(name = "bizType", description = "CRM 类型", required = true, example = "2"),
             @Parameter(name = "bizId", description = "CRM 类型数据编号", required = true, example = "1024")
@@ -143,23 +95,15 @@ public class CrmPermissionController {
     @PreAuthorize("@ss.hasPermission('crm:permission:query')")
     public CommonResult<List<CrmPermissionRespVO>> getPermissionList(@RequestParam("bizType") Integer bizType,
                                                                      @RequestParam("bizId") Long bizId) {
-        List<CrmPermissionDO> permission = permissionService.getPermissionByBizTypeAndBizId(bizType, bizId);
+        List<CrmPermissionDO> permission = permissionService.getPermissionListByBiz(bizType, bizId);
         if (CollUtil.isEmpty(permission)) {
             return success(Collections.emptyList());
         }
-        // TODO @puhui999:池子的逻辑;
-        // 判断是否是公海数据
-        // TODO @puhui999:这段逻辑,可以删除么?
-        Predicate<CrmPermissionDO> filter = item -> ObjUtil.equal(item.getUserId(), CrmPermissionDO.POOL_USER_ID);
-        if (anyMatch(permission, filter)) {
-            permission.removeIf(filter); // 排除
-        }
 
         // 拼接数据
         List<AdminUserRespDTO> userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId));
         Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
-        // TODO @puhui999:CollectionUtils.convertSetByFlatMap() 看看可以不
-        Set<Long> postIds = userList.stream().flatMap(item -> item.getPostIds().stream()).collect(Collectors.toSet());
+        Set<Long> postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, Collection::stream);
         Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
         return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap));
     }

+ 3 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/vo/CrmPermissionBaseVO.java

@@ -1,15 +1,15 @@
 package cn.iocoder.yudao.module.crm.controller.admin.permission.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
 
 /**
- * 数据权限(团队成员) Base VO,提供给添加、修改、详细的子 VO 使用
+ * 数据权限 Base VO,提供给添加、修改、详细的子 VO 使用
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  *
  * @author HUIHUI

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/vo/CrmPermissionRespVO.java

@@ -6,7 +6,7 @@ import lombok.Data;
 import java.time.LocalDateTime;
 import java.util.Set;
 
-@Schema(description = "管理后台 - CRM 数据权限(团队成员) Response VO")
+@Schema(description = "管理后台 - CRM 数据权限 Response VO")
 @Data
 public class CrmPermissionRespVO extends CrmPermissionBaseVO {
 

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/vo/CrmPermissionUpdateReqVO.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.module.crm.controller.admin.permission.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
-import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivableBaseVO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.crm.enums.AuditStatusEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -34,7 +34,7 @@ public class CrmReceivableBaseVO {
 
     // TODO @liuhongfeng:这个字段,应该不是前端传递的噢,而是后端自己生成的
     @Schema(description = "审批状态", example = "1")
-    @InEnum(AuditStatusEnum.class)
+    @InEnum(CrmAuditStatusEnum.class)
     private Integer checkStatus;
 
     @Schema(description = "回款日期")

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivableExcelVO.java

@@ -28,7 +28,7 @@ public class CrmReceivableExcelVO {
     private Long contractId;
 
     @ExcelProperty(value = "审批状态", converter = DictConvert.class)
-    @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_RECEIVABLE_CHECK_STATUS)
+    @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_AUDIT_STATUS)
     private Integer checkStatus;
 
     @ExcelProperty("工作流编号")

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivablePlanBaseVO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo;
 
 import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.crm.enums.AuditStatusEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -28,7 +28,7 @@ public class CrmReceivablePlanBaseVO {
     private Integer status;
 
     @Schema(description = "审批状态", example = "1")
-    @InEnum(AuditStatusEnum.class)
+    @InEnum(CrmAuditStatusEnum.class)
     private Integer checkStatus;
 
     @Schema(description = "计划回款金额", example = "29675")

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/CrmReceivablePlanExcelVO.java

@@ -31,7 +31,7 @@ public class CrmReceivablePlanExcelVO {
     private Integer status;
 
     @ExcelProperty(value = "审批状态", converter = DictConvert.class)
-    @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_RECEIVABLE_CHECK_STATUS)
+    @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_AUDIT_STATUS)
     private Integer checkStatus;
 
     //@ExcelProperty("工作流编号")

+ 21 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java

@@ -1,8 +1,11 @@
 package cn.iocoder.yudao.module.crm.convert.business;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
@@ -10,6 +13,9 @@ import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
 
 /**
  * 商机 Convert
@@ -37,4 +43,18 @@ public interface CrmBusinessConvert {
     })
     CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
 
+    default PageResult<CrmBusinessRespVO> convertPage(PageResult<CrmBusinessDO> page, List<CrmCustomerDO> customerList,
+                                                      List<CrmBusinessStatusTypeDO> statusTypeList, List<CrmBusinessStatusDO> statusList) {
+        PageResult<CrmBusinessRespVO> result = convertPage(page);
+        // 拼接关联字段
+        Map<Long, String> customerMap = convertMap(customerList, CrmCustomerDO::getId, CrmCustomerDO::getName);
+        Map<Long, String> statusTypeMap = convertMap(statusTypeList, CrmBusinessStatusTypeDO::getId, CrmBusinessStatusTypeDO::getName);
+        Map<Long, String> statusMap = convertMap(statusList, CrmBusinessStatusDO::getId, CrmBusinessStatusDO::getName);
+        result.getList().forEach(type -> type
+                .setCustomerName(customerMap.get(type.getCustomerId()))
+                .setStatusTypeName(statusTypeMap.get(type.getStatusTypeId()))
+                .setStatusName(statusMap.get(type.getStatusId())));
+        return result;
+    }
+
 }

+ 6 - 10
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java

@@ -1,13 +1,13 @@
 package cn.iocoder.yudao.module.crm.convert.businessstatus;
 
-import java.util.*;
-
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
-import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.*;
-import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO;
+
+import java.util.List;
 
 /**
  * 商机状态 Convert
@@ -19,9 +19,7 @@ public interface CrmBusinessStatusConvert {
 
     CrmBusinessStatusConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusConvert.class);
 
-    CrmBusinessStatusDO convert(CrmBusinessStatusCreateReqVO bean);
-
-    CrmBusinessStatusDO convert(CrmBusinessStatusUpdateReqVO bean);
+    CrmBusinessStatusDO convert(CrmBusinessStatusSaveReqVO bean);
 
     CrmBusinessStatusRespVO convert(CrmBusinessStatusDO bean);
 
@@ -29,6 +27,4 @@ public interface CrmBusinessStatusConvert {
 
     PageResult<CrmBusinessStatusRespVO> convertPage(PageResult<CrmBusinessStatusDO> page);
 
-    List<CrmBusinessStatusExcelVO> convertList02(List<CrmBusinessStatusDO> list);
-
 }

+ 26 - 11
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java

@@ -1,13 +1,19 @@
 package cn.iocoder.yudao.module.crm.convert.businessstatustype;
 
-import java.util.*;
-
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
-import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.*;
-import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO;
+
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
 
 /**
  * 商机状态类型 Convert
@@ -19,16 +25,25 @@ public interface CrmBusinessStatusTypeConvert {
 
     CrmBusinessStatusTypeConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusTypeConvert.class);
 
-    CrmBusinessStatusTypeDO convert(CrmBusinessStatusTypeCreateReqVO bean);
-
-    CrmBusinessStatusTypeDO convert(CrmBusinessStatusTypeUpdateReqVO bean);
+    CrmBusinessStatusTypeDO convert(CrmBusinessStatusTypeSaveReqVO bean);
 
     CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean);
 
-    List<CrmBusinessStatusTypeRespVO> convertList(List<CrmBusinessStatusTypeDO> list);
-
     PageResult<CrmBusinessStatusTypeRespVO> convertPage(PageResult<CrmBusinessStatusTypeDO> page);
 
-    List<CrmBusinessStatusTypeExcelVO> convertList02(List<CrmBusinessStatusTypeDO> list);
+    default PageResult<CrmBusinessStatusTypeRespVO> convertPage(PageResult<CrmBusinessStatusTypeDO> page, List<DeptRespDTO> deptList) {
+        PageResult<CrmBusinessStatusTypeRespVO> pageResult = convertPage(page);
+        // 拼接关联字段
+        Map<Long, String> deptMap = convertMap(deptList, DeptRespDTO::getId, DeptRespDTO::getName);
+        pageResult.getList().forEach(type -> type.setDeptNames(convertList(type.getDeptIds(), deptMap::get)));
+        return pageResult;
+    }
+
+    default CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean, List<CrmBusinessStatusDO> statusList) {
+        // TODO @ljlleo 可以链式赋值,简化成一行;
+        CrmBusinessStatusTypeRespVO result = convert(bean);
+        result.setStatusList(statusList);
+        return result;
+    }
 
 }

+ 72 - 9
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java

@@ -1,18 +1,27 @@
 package cn.iocoder.yudao.module.crm.convert.contact;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
+
+// TODO 芋艿:convert 后面在梳理下,略微有点乱
 /**
- * crm联系人 Convert
+ * CRM 联系人 Convert
  *
  * @author 芋道源码
  */
@@ -21,19 +30,23 @@ public interface ContactConvert {
 
     ContactConvert INSTANCE = Mappers.getMapper(ContactConvert.class);
 
-    ContactDO convert(ContactCreateReqVO bean);
+    CrmContactDO convert(CrmContactCreateReqVO bean);
 
-    ContactDO convert(ContactUpdateReqVO bean);
+    CrmContactDO convert(CrmContactUpdateReqVO bean);
 
-    ContactRespVO convert(ContactDO bean);
+    CrmContactRespVO convert(CrmContactDO bean);
 
-    List<ContactRespVO> convertList(List<ContactDO> list);
+    List<CrmContactRespVO> convertList(List<CrmContactDO> list);
 
-    PageResult<ContactRespVO> convertPage(PageResult<ContactDO> page);
+    PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> page);
 
-    List<ContactExcelVO> convertList02(List<ContactDO> list);
+    default PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
+                                                     List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
+        List<CrmContactRespVO> list = converList(pageResult.getList(), userMap, customerList, parentContactList);
+        return convertPage(pageResult).setList(list);
+    }
 
-    List<ContactSimpleRespVO> convertAllList(List<ContactDO> list);
+    List<CrmContactSimpleRespVO> convertAllList(List<CrmContactDO> list);
 
     @Mappings({
             @Mapping(target = "bizId", source = "reqVO.id"),
@@ -41,4 +54,54 @@ public interface ContactConvert {
     })
     CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
 
+    /**
+     * 转换详情信息
+     *
+     * @param contactDO         联系人
+     * @param userMap           用户列表
+     * @param crmCustomerDOList 客户
+     * @return ContactRespVO
+     */
+    default CrmContactRespVO convert(CrmContactDO contactDO, Map<Long, AdminUserRespDTO> userMap, List<CrmCustomerDO> crmCustomerDOList,
+                                     List<CrmContactDO> contactList) {
+        CrmContactRespVO contactVO = convert(contactDO);
+        setUserInfo(contactVO, userMap);
+        Map<Long, CrmCustomerDO> ustomerMap = crmCustomerDOList.stream().collect(Collectors.toMap(CrmCustomerDO::getId, v -> v));
+        Map<Long, CrmContactDO> contactMap = contactList.stream().collect(Collectors.toMap(CrmContactDO::getId, v -> v));
+        findAndThen(ustomerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName()));
+        findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName()));
+        return contactVO;
+    }
+
+    default List<CrmContactRespVO> converList(List<CrmContactDO> contactList, Map<Long, AdminUserRespDTO> userMap,
+                                              List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
+        List<CrmContactRespVO> result = convertList(contactList);
+        Map<Long, CrmContactDO> parentContactMap = convertMap(parentContactList, CrmContactDO::getId);
+        Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
+        result.forEach(item -> {
+            setUserInfo(item, userMap);
+            findAndThen(customerMap, item.getCustomerId(), customer -> { // TODO @zyna:这里的 { 可以去掉
+                item.setCustomerName(customer.getName());
+            });
+            findAndThen(parentContactMap, item.getParentId(), contactDO -> {  // TODO @zyna:这里的 { 可以去掉
+                item.setParentName(contactDO.getName());
+            });
+        });
+        return result;
+    }
+
+    /**
+     * 设置用户信息
+     *
+     * @param contactRespVO 联系人Response VO
+     * @param userMap       用户信息 map
+     */
+    static void setUserInfo(CrmContactRespVO contactRespVO, Map<Long, AdminUserRespDTO> userMap) {
+        contactRespVO.setAreaName(AreaUtils.format(contactRespVO.getAreaId()));
+        findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> {
+            contactRespVO.setOwnerUserName(user == null ? "" : user.getNickname());
+        });
+        findAndThen(userMap, Long.parseLong(contactRespVO.getCreator()), user -> contactRespVO.setCreatorName(user.getNickname()));
+    }
+
 }

+ 34 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java

@@ -2,14 +2,20 @@ package cn.iocoder.yudao.module.crm.convert.contract;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
 
 /**
  * 合同 Convert
@@ -21,17 +27,17 @@ public interface ContractConvert {
 
     ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class);
 
-    ContractDO convert(ContractCreateReqVO bean);
+    CrmContractDO convert(CrmContractCreateReqVO bean);
 
-    ContractDO convert(ContractUpdateReqVO bean);
+    CrmContractDO convert(CrmContractUpdateReqVO bean);
 
-    ContractRespVO convert(ContractDO bean);
+    ContractRespVO convert(CrmContractDO bean);
 
-    List<ContractRespVO> convertList(List<ContractDO> list);
+    List<ContractRespVO> convertList(List<CrmContractDO> list);
 
-    PageResult<ContractRespVO> convertPage(PageResult<ContractDO> page);
+    PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> page);
 
-    List<ContractExcelVO> convertList02(List<ContractDO> list);
+    List<CrmContractExcelVO> convertList02(List<CrmContractDO> list);
 
     @Mappings({
             @Mapping(target = "bizId", source = "reqVO.id"),
@@ -39,4 +45,25 @@ public interface ContractConvert {
     })
     CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId);
 
+    default PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
+                                                     List<CrmCustomerDO> customerList) {
+        return new PageResult<>(converList(pageResult.getList(), userMap, customerList), pageResult.getTotal());
+    }
+
+    default List<ContractRespVO> converList(List<CrmContractDO> contractList, Map<Long, AdminUserRespDTO> userMap,
+                                            List<CrmCustomerDO> customerList) {
+        List<ContractRespVO> result = convertList(contractList);
+        Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
+        result.forEach(item -> {
+            setUserInfo(item, userMap);
+            findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName()));
+        });
+        return result;
+    }
+
+    static void setUserInfo(ContractRespVO contract, Map<Long, AdminUserRespDTO> userMap) {
+        findAndThen(userMap, contract.getOwnerUserId(), user -> contract.setOwnerUserName(user.getNickname()));
+        findAndThen(userMap, Long.parseLong(contract.getCreator()), user -> contract.setCreatorName(user.getNickname()));
+    }
+
 }

+ 28 - 53
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java

@@ -1,13 +1,12 @@
 package cn.iocoder.yudao.module.crm.convert.customer;
 
-import cn.hutool.core.util.NumberUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigSaveReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -37,38 +36,20 @@ public interface CrmCustomerConvert {
 
     CrmCustomerRespVO convert(CrmCustomerDO bean);
 
-    default CrmCustomerRespVO convert(CrmCustomerDO customer, Map<Long, CrmPermissionDO> ownerMap,
-                                      Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
-        CrmCustomerRespVO customerResp = convert(customer);
-        findAndThen(ownerMap, customerResp.getId(), owner -> {
-            customerResp.setOwnerUserId(owner.getUserId());
-            customerResp.setAreaName(AreaUtils.format(customerResp.getAreaId()));
-            findAndThen(userMap, owner.getUserId(), user -> {
-                customerResp.setOwnerUserName(user.getNickname());
-            });
-            findAndThen(userMap, Long.parseLong(customerResp.getCreator()), user -> {
-                customerResp.setCreatorName(user.getNickname());
-            });
-            findAndThen(deptMap, customerResp.getOwnerUserId(), dept -> {
-                customerResp.setOwnerUserDeptName(dept.getName());
-            });
-        });
-        return customerResp;
-    }
-
-    default PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> page, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
-        PageResult<CrmCustomerRespVO> result = convertPage(page);
-        result.getList().forEach(customerRespVO -> {
-            customerRespVO.setAreaName(AreaUtils.format(customerRespVO.getAreaId()));
-            MapUtils.findAndThen(userMap, NumberUtil.parseLong(customerRespVO.getCreator()), creator ->
-                    customerRespVO.setCreatorName(creator.getNickname()));
-            MapUtils.findAndThen(userMap, customerRespVO.getOwnerUserId(), ownerUser -> {
-                customerRespVO.setOwnerUserName(ownerUser.getNickname());
-                MapUtils.findAndThen(deptMap, ownerUser.getDeptId(), dept ->
-                        customerRespVO.setOwnerUserDeptName(dept.getName()));
-            });
+    /**
+     * 设置用户信息
+     *
+     * @param customer  CRM 客户 Response VO
+     * @param userMap 用户信息 map
+     * @param deptMap 用户部门信息 map
+     */
+    static void setUserInfo(CrmCustomerRespVO customer, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
+        customer.setAreaName(AreaUtils.format(customer.getAreaId()));
+        findAndThen(userMap, customer.getOwnerUserId(), user -> {
+            customer.setOwnerUserName(user.getNickname());
+            findAndThen(deptMap, user.getDeptId(), dept -> customer.setOwnerUserDeptName(dept.getName()));
         });
-        return result;
+        findAndThen(userMap, Long.parseLong(customer.getCreator()), user -> customer.setCreatorName(user.getNickname()));
     }
 
     List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list);
@@ -81,30 +62,24 @@ public interface CrmCustomerConvert {
 
     PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> page);
 
-    // TODO @puhui999:两个 convertPage 的逻辑,合并下;
-    default PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> pageResult, Map<Long, CrmPermissionDO> ownerMap,
-                                                      Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
+    default CrmCustomerRespVO convert(CrmCustomerDO customer, Map<Long, AdminUserRespDTO> userMap,
+                                      Map<Long, DeptRespDTO> deptMap) {
+        CrmCustomerRespVO customerResp = convert(customer);
+        setUserInfo(customerResp, userMap, deptMap);
+        return customerResp;
+    }
+
+    default PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
+                                                      Map<Long, DeptRespDTO> deptMap) {
         PageResult<CrmCustomerRespVO> result = convertPage(pageResult);
-        result.getList().forEach(item -> {
-            findAndThen(ownerMap, item.getId(), owner -> {
-                item.setOwnerUserId(owner.getUserId());
-                item.setAreaName(AreaUtils.format(item.getAreaId()));
-                findAndThen(userMap, owner.getUserId(), user -> {
-                    item.setOwnerUserName(user.getNickname());
-                });
-                findAndThen(userMap, Long.parseLong(item.getCreator()), user -> {
-                    item.setCreatorName(user.getNickname());
-                });
-                findAndThen(deptMap, item.getOwnerUserId(), dept -> {
-                    item.setOwnerUserDeptName(dept.getName());
-                });
-            });
-        });
+        result.getList().forEach(item -> setUserInfo(item, userMap, deptMap));
         return result;
     }
 
     CrmCustomerPoolConfigRespVO convert(CrmCustomerPoolConfigDO customerPoolConfig);
 
-    CrmCustomerPoolConfigDO convert(CrmCustomerPoolConfigUpdateReqVO updateReqVO);
+    CrmCustomerPoolConfigDO convert(CrmCustomerPoolConfigSaveReqVO updateReqVO);
+
+    List<CrmCustomerQueryAllRespVO> convertQueryAll(List<CrmCustomerDO> crmCustomerDO);
 
 }

+ 8 - 12
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerLimitConfigConvert.java

@@ -1,10 +1,11 @@
 package cn.iocoder.yudao.module.crm.convert.customer;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLimitConfigCreateReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLimitConfigRespVO;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLimitConfigUpdateReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customerlimitconfig.CrmCustomerLimitConfigDO;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import org.mapstruct.Mapper;
@@ -12,8 +13,6 @@ import org.mapstruct.factory.Mappers;
 
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
 
 /**
  * 客户限制配置 Convert
@@ -54,14 +53,11 @@ public interface CrmCustomerLimitConfigConvert {
      *
      * @param userMap 用户映射
      * @param deptMap 部门映射
-     * @param respVo 响应实体
+     * @param respVo  响应实体
      */
     static void fillNameField(Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap, CrmCustomerLimitConfigRespVO respVo) {
-        // TODO wanwan:返回 list,具体怎么拼接叫给前端;
-        respVo.setUserNames(respVo.getUserIds().stream().map(userMap::get)
-                .filter(Objects::nonNull).map(AdminUserRespDTO::getNickname).collect(Collectors.joining(",")));
-        respVo.setDeptNames(respVo.getDeptIds().stream().map(deptMap::get)
-                .filter(Objects::nonNull).map(DeptRespDTO::getName).collect(Collectors.joining(",")));
+        respVo.setUsers(CollectionUtils.convertList(respVo.getUserIds(), userMap::get));
+        respVo.setDepts(CollectionUtils.convertList(respVo.getDeptIds(), deptMap::get));
     }
 
 }

Some files were not shown because too many files changed in this diff