فهرست منبع

crm: 完善一些 TODO

puhui999 1 سال پیش
والد
کامیت
5efa0f327f
28فایلهای تغییر یافته به همراه306 افزوده شده و 227 حذف شده
  1. 19 5
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
  2. 0 16
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessCreateReqVO.java
  3. 45 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
  4. 21 6
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
  5. 0 23
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateReqVO.java
  6. 4 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
  7. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java
  8. 9 8
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
  9. 0 37
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.java
  10. 0 14
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractCreateReqVO.java
  11. 82 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java
  12. 35 15
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java
  13. 0 20
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractUpdateReqVO.java
  14. 0 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java
  15. 2 10
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java
  16. 0 5
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java
  17. 0 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java
  18. 2 5
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java
  19. 5 16
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java
  20. 0 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java
  21. 44 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBusinessParseFunction.java
  22. 3 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
  23. 11 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
  24. 4 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
  25. 3 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
  26. 7 7
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
  27. 5 7
      yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java
  28. 4 5
      yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java

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

@@ -6,7 +6,10 @@ 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.business.vo.business.*;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
 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.business.CrmBusinessStatusDO;
@@ -32,6 +35,7 @@ import java.util.List;
 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.pojo.PageParam.PAGE_SIZE_NONE;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 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;
@@ -52,18 +56,17 @@ public class CrmBusinessController {
     @Resource
     private CrmBusinessStatusService businessStatusService;
 
-    // TODO @商机待定:CrmBusinessCreateReqVO、CrmBusinessUpdateReqVO、CrmBusinessRespVO 按照新的 VO 规范
     @PostMapping("/create")
     @Operation(summary = "创建商机")
     @PreAuthorize("@ss.hasPermission('crm:business:create')")
-    public CommonResult<Long> createBusiness(@Valid @RequestBody CrmBusinessCreateReqVO createReqVO) {
+    public CommonResult<Long> createBusiness(@Valid @RequestBody CrmBusinessSaveReqVO createReqVO) {
         return success(businessService.createBusiness(createReqVO, getLoginUserId()));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新商机")
     @PreAuthorize("@ss.hasPermission('crm:business:update')")
-    public CommonResult<Boolean> updateBusiness(@Valid @RequestBody CrmBusinessUpdateReqVO updateReqVO) {
+    public CommonResult<Boolean> updateBusiness(@Valid @RequestBody CrmBusinessSaveReqVO updateReqVO) {
         businessService.updateBusiness(updateReqVO);
         return success(true);
     }
@@ -83,7 +86,7 @@ public class CrmBusinessController {
     @PreAuthorize("@ss.hasPermission('crm:business:query')")
     public CommonResult<CrmBusinessRespVO> getBusiness(@RequestParam("id") Long id) {
         CrmBusinessDO business = businessService.getBusiness(id);
-        return success(CrmBusinessConvert.INSTANCE.convert(business));
+        return success(BeanUtils.toBean(business, CrmBusinessRespVO.class));
     }
 
     @GetMapping("/list-by-ids")
@@ -94,6 +97,17 @@ public class CrmBusinessController {
         return success(BeanUtils.toBean(businessService.getBusinessList(ids, getLoginUserId()), CrmBusinessRespVO.class));
     }
 
+    @GetMapping("/simple-all-list")
+    @Operation(summary = "获得联系人的精简列表")
+    @PreAuthorize("@ss.hasPermission('crm:contact:query')")
+    public CommonResult<List<CrmBusinessRespVO>> getSimpleContactList() {
+        CrmBusinessPageReqVO reqVO = new CrmBusinessPageReqVO();
+        reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页
+        PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(reqVO, getLoginUserId());
+        return success(convertList(pageResult.getList(), business -> // 只返回 id、name 字段
+                new CrmBusinessRespVO().setId(business.getId()).setName(business.getName())));
+    }
+
     @GetMapping("/page")
     @Operation(summary = "获得商机分页")
     @PreAuthorize("@ss.hasPermission('crm:business:query')")

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

@@ -1,16 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@Schema(description = "管理后台 - 商机创建 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessCreateReqVO extends CrmBusinessBaseVO {
-
-    // TODO @ljileo:新建的时候,应该可以传递添加的产品;
-
-}

+ 45 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java

@@ -1,18 +1,59 @@
 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import jakarta.validation.constraints.NotNull;
+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 = "管理后台 - 商机 Response VO")
 @Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessRespVO extends CrmBusinessBaseVO {
+public class CrmBusinessRespVO {
 
     @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
     private Long id;
 
+    @Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+    @NotNull(message = "商机名称不能为空")
+    private String name;
+
+    @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
+    @NotNull(message = "商机状态类型不能为空")
+    private Long statusTypeId;
+
+    @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
+    @NotNull(message = "商机状态不能为空")
+    private Long statusId;
+
+    @Schema(description = "下次联系时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime contactNextTime;
+
+    @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")
+    @NotNull(message = "客户不能为空")
+    private Long customerId;
+
+    @Schema(description = "预计成交日期")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime dealTime;
+
+    @Schema(description = "商机金额", example = "12371")
+    private Integer price;
+
+    // TODO @ljileo:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题
+    @Schema(description = "整单折扣")
+    private Integer discountPercent;
+
+    @Schema(description = "产品总金额", example = "12025")
+    private BigDecimal productPrice;
+
+    @Schema(description = "备注", example = "随便")
+    private String remark;
+
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 

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

@@ -1,57 +1,72 @@
 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
 
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction;
+import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import jakarta.validation.constraints.NotNull;
 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;
 
-/**
- * 商机 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
+// TODO @ljileo:DiffLogField function 完善一下
+@Schema(description = "管理后台 - CRM 商机创建/更新 Request VO")
 @Data
-public class CrmBusinessBaseVO {
+public class CrmBusinessSaveReqVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
+    private Long id;
 
     @Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
+    @DiffLogField(name = "商机名称")
     @NotNull(message = "商机名称不能为空")
     private String name;
 
     @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
+    @DiffLogField(name = "商机状态")
     @NotNull(message = "商机状态类型不能为空")
     private Long statusTypeId;
 
     @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
+    @DiffLogField(name = "商机状态")
     @NotNull(message = "商机状态不能为空")
     private Long statusId;
 
     @Schema(description = "下次联系时间")
+    @DiffLogField(name = "下次联系时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime contactNextTime;
 
     @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")
+    @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
     @NotNull(message = "客户不能为空")
     private Long customerId;
 
     @Schema(description = "预计成交日期")
+    @DiffLogField(name = "预计成交日期")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime dealTime;
 
     @Schema(description = "商机金额", example = "12371")
+    @DiffLogField(name = "商机金额")
     private Integer price;
 
     // TODO @ljileo:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题
     @Schema(description = "整单折扣")
+    @DiffLogField(name = "整单折扣")
     private Integer discountPercent;
 
     @Schema(description = "产品总金额", example = "12025")
+    @DiffLogField(name = "产品总金额")
     private BigDecimal productPrice;
 
     @Schema(description = "备注", example = "随便")
+    @DiffLogField(name = "备注")
     private String remark;
 
+    // TODO @ljileo:修改的时候,应该可以传递添加的产品;
+
 }

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

@@ -1,23 +0,0 @@
-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;
-import lombok.ToString;
-
-import jakarta.validation.constraints.NotNull;
-
-@Schema(description = "管理后台 - 商机更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmBusinessUpdateReqVO extends CrmBusinessBaseVO {
-
-    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
-    @NotNull(message = "主键不能为空")
-    private Long id;
-
-    // TODO @ljileo:修改的时候,应该可以传递添加的产品;
-
-}

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

@@ -125,8 +125,10 @@ public class CrmContactController {
     @Operation(summary = "获得联系人的精简列表")
     @PreAuthorize("@ss.hasPermission('crm:contact:query')")
     public CommonResult<List<CrmContactRespVO>> getSimpleContactList() {
-        List<CrmContactDO> list = contactService.getContactList();
-        return success(convertList(list, contact -> // 只返回 id、name 字段
+        CrmContactPageReqVO reqVO = new CrmContactPageReqVO();
+        reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页
+        PageResult<CrmContactDO> pageResult = contactService.getContactPage(reqVO, getLoginUserId());
+        return success(convertList(pageResult.getList(), contact -> // 只返回 id、name 字段
                 new CrmContactRespVO().setId(contact.getId()).setName(contact.getName())));
     }
 

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

@@ -28,7 +28,7 @@ public class CrmContactSaveReqVO {
     private String name;
 
     @Schema(description = "客户编号", example = "10795")
-    @DiffLogField(name = "姓名", function = CrmCustomerParseFunction.NAME)
+    @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
     private Long customerId;
 
     @Schema(description = "性别")

+ 9 - 8
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java

@@ -5,6 +5,7 @@ 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.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.contract.vo.*;
@@ -53,14 +54,14 @@ public class CrmContractController {
     @PostMapping("/create")
     @Operation(summary = "创建合同")
     @PreAuthorize("@ss.hasPermission('crm:contract:create')")
-    public CommonResult<Long> createContract(@Valid @RequestBody CrmContractCreateReqVO createReqVO) {
+    public CommonResult<Long> createContract(@Valid @RequestBody CrmContractSaveReqVO createReqVO) {
         return success(contractService.createContract(createReqVO, getLoginUserId()));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新合同")
     @PreAuthorize("@ss.hasPermission('crm:contract:update')")
-    public CommonResult<Boolean> updateContract(@Valid @RequestBody CrmContractUpdateReqVO updateReqVO) {
+    public CommonResult<Boolean> updateContract(@Valid @RequestBody CrmContractSaveReqVO updateReqVO) {
         contractService.updateContract(updateReqVO);
         return success(true);
     }
@@ -78,22 +79,22 @@ public class CrmContractController {
     @Operation(summary = "获得合同")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
     @PreAuthorize("@ss.hasPermission('crm:contract:query')")
-    public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) {
+    public CommonResult<CrmContractRespVO> getContract(@RequestParam("id") Long id) {
         CrmContractDO contract = contractService.getContract(id);
-        return success(CrmContractConvert.INSTANCE.convert(contract));
+        return success(BeanUtils.toBean(contract, CrmContractRespVO.class));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得合同分页")
     @PreAuthorize("@ss.hasPermission('crm:contract:query')")
-    public CommonResult<PageResult<ContractRespVO>> getContractPage(@Valid CrmContractPageReqVO pageVO) {
+    public CommonResult<PageResult<CrmContractRespVO>> getContractPage(@Valid CrmContractPageReqVO pageVO) {
         PageResult<CrmContractDO> pageResult = contractService.getContractPage(pageVO, getLoginUserId());
         return success(buildContractDetailPage(pageResult));
     }
 
     @GetMapping("/page-by-customer")
     @Operation(summary = "获得联系人分页,基于指定客户")
-    public CommonResult<PageResult<ContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) {
+    public CommonResult<PageResult<CrmContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) {
         Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
         PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomerId(pageVO);
         return success(buildContractDetailPage(pageResult));
@@ -108,7 +109,7 @@ public class CrmContractController {
         PageResult<CrmContractDO> pageResult = contractService.getContractPage(exportReqVO, getLoginUserId());
         // 导出 Excel
         ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class,
-                CrmContractConvert.INSTANCE.convertList02(pageResult.getList()));
+                BeanUtils.toBean(pageResult.getList(), CrmContractExcelVO.class));
     }
 
     /**
@@ -117,7 +118,7 @@ public class CrmContractController {
      * @param pageResult 简单的合同分页结果
      * @return 详细的合同分页结果
      */
-    private PageResult<ContractRespVO> buildContractDetailPage(PageResult<CrmContractDO> pageResult) {
+    private PageResult<CrmContractRespVO> buildContractDetailPage(PageResult<CrmContractDO> pageResult) {
         List<CrmContractDO> contactList = pageResult.getList();
         if (CollUtil.isEmpty(contactList)) {
             return PageResult.empty(pageResult.getTotal());

+ 0 - 37
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.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 lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - CRM 合同 Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ContractRespVO extends CrmContractBaseVO {
-
-    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
-    private Long id;
-
-    @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;
-
-}

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

@@ -1,14 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contract.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 CrmContractCreateReqVO extends CrmContractBaseVO {
-
-}

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

@@ -0,0 +1,82 @@
+package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - CRM 合同 Response VO")
+@Data
+public class CrmContractRespVO {
+
+    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
+    private Long id;
+
+    @Schema(description = "合同名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+    private String name;
+
+    @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18336")
+    private Long customerId;
+
+    @Schema(description = "商机编号", example = "10864")
+    private Long businessId;
+
+    @Schema(description = "工作流编号", example = "1043")
+    private Long processInstanceId;
+
+    @Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime orderDate;
+
+    @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17144")
+    private Long ownerUserId;
+
+    // TODO @芋艿:未来应该支持自动生成;
+    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20230101")
+    private String no;
+
+    @Schema(description = "开始时间")
+    private LocalDateTime startTime;
+
+    @Schema(description = "结束时间")
+    private LocalDateTime endTime;
+
+    @Schema(description = "合同金额", example = "5617")
+    private Integer price;
+
+    @Schema(description = "整单折扣")
+    private Integer discountPercent;
+
+    @Schema(description = "产品总金额", example = "19510")
+    private Integer productPrice;
+
+    @Schema(description = "联系人编号", example = "18546")
+    private Long contactId;
+
+    @Schema(description = "公司签约人", example = "14036")
+    private Long signUserId;
+
+    @Schema(description = "最后跟进时间")
+    private LocalDateTime contactLastTime;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+    @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;
+
+}

+ 35 - 15
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractBaseVO.java → yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java

@@ -1,81 +1,101 @@
 package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmBusinessParseFunction;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmContactParseFunction;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFunction;
+import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import jakarta.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
-/**
- * 合同 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
+@Schema(description = "管理后台 - CRM 合同创建/更新 Request VO")
 @Data
-public class CrmContractBaseVO {
+public class CrmContractSaveReqVO {
 
-    // TODO @dhb52:类似 no 字段的 example 要写xia 哈;
+    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
+    private Long id;
 
     @Schema(description = "合同名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+    @DiffLogField(name = "合同名称")
     @NotNull(message = "合同名称不能为空")
     private String name;
 
-    // TODO @dhb52:这个必须传递
-    @Schema(description = "客户编号", example = "18336")
+    @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18336")
+    @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
+    @NotNull(message = "客户编号不能为空")
     private Long customerId;
 
     @Schema(description = "商机编号", example = "10864")
+    @DiffLogField(name = "商机", function = CrmBusinessParseFunction.NAME)
     private Long businessId;
 
     @Schema(description = "工作流编号", example = "1043")
+    @DiffLogField(name = "工作流编号")
     private Long processInstanceId;
 
-    // TODO @dhb52:这个必须传递
-    @Schema(description = "下单日期")
+    @Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED)
+    @DiffLogField(name = "下单日期")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @NotNull(message = "下单日期不能为空")
     private LocalDateTime orderDate;
 
-    // TODO @dhb52:这个必须传递
-    @Schema(description = "负责人的用户编号", example = "17144")
+    @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17144")
+    @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME)
+    @NotNull(message = "负责人不能为空")
     private Long ownerUserId;
 
     // TODO @芋艿:未来应该支持自动生成;
-    // TODO @dhb52:这个必须传递;
-    @Schema(description = "合同编号")
+    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20230101")
+    @DiffLogField(name = "合同编号")
+    @NotNull(message = "合同编号不能为空")
     private String no;
 
     @Schema(description = "开始时间")
+    @DiffLogField(name = "开始时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime startTime;
 
     @Schema(description = "结束时间")
+    @DiffLogField(name = "结束时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime endTime;
 
     @Schema(description = "合同金额", example = "5617")
+    @DiffLogField(name = "合同金额")
     private Integer price;
 
     @Schema(description = "整单折扣")
+    @DiffLogField(name = "整单折扣")
     private Integer discountPercent;
 
     @Schema(description = "产品总金额", example = "19510")
+    @DiffLogField(name = "产品总金额")
     private Integer productPrice;
 
     @Schema(description = "联系人编号", example = "18546")
+    @DiffLogField(name = "联系人", function = CrmContactParseFunction.NAME)
     private Long contactId;
 
     @Schema(description = "公司签约人", example = "14036")
+    @DiffLogField(name = "公司签约人", function = SysAdminUserParseFunction.NAME)
     private Long signUserId;
 
     @Schema(description = "最后跟进时间")
+    @DiffLogField(name = "最后跟进时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime contactLastTime;
 
     @Schema(description = "备注", example = "你猜")
+    @DiffLogField(name = "备注")
     private String remark;
 
     // TODO @dhb52:增加一个 status 字段:具体有哪些值,你来枚举下;主要页面上有个【草稿】【提交审核】的流程,可以看看。然后要对接工作流,这块也可以看看,不确定的地方问我。
 
+
 }

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

@@ -1,20 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import jakarta.validation.constraints.NotNull;
-
-@Schema(description = "管理后台 - CRM 合同更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CrmContractUpdateReqVO extends CrmContractBaseVO {
-
-    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
-    @NotNull(message = "合同编号不能为空")
-    private Long id;
-
-}

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

@@ -28,6 +28,4 @@ public class CrmCustomerTransferReqVO {
     @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     private Integer oldOwnerPermissionLevel;
 
-    // TODO @puhui999:联系人、商机、合同的转移
-
 }

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

@@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.crm.convert.business;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
 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;
@@ -27,15 +28,6 @@ public interface CrmBusinessConvert {
 
     CrmBusinessConvert INSTANCE = Mappers.getMapper(CrmBusinessConvert.class);
 
-    CrmBusinessDO convert(CrmBusinessCreateReqVO bean);
-
-    CrmBusinessDO convert(CrmBusinessUpdateReqVO bean);
-
-    CrmBusinessRespVO convert(CrmBusinessDO bean);
-    List<CrmBusinessRespVO> convert(List<CrmBusinessDO> bean);
-
-    List<CrmBusinessExcelVO> convertList02(List<CrmBusinessDO> list);
-
     @Mapping(target = "bizId", source = "reqVO.id")
     CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
 

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

@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.convert.businessstatus;
 
 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;
@@ -19,10 +18,6 @@ public interface CrmBusinessStatusConvert {
 
     CrmBusinessStatusConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusConvert.class);
 
-    CrmBusinessStatusDO convert(CrmBusinessStatusSaveReqVO bean);
-
-    CrmBusinessStatusRespVO convert(CrmBusinessStatusDO bean);
-
     List<CrmBusinessStatusRespVO> convertList(List<CrmBusinessStatusDO> list);
 
     PageResult<CrmBusinessStatusRespVO> convertPage(PageResult<CrmBusinessStatusDO> page);

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

@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.convert.businessstatustype;
 
 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;
@@ -25,7 +24,6 @@ public interface CrmBusinessStatusTypeConvert {
 
     CrmBusinessStatusTypeConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusTypeConvert.class);
 
-    CrmBusinessStatusTypeDO convert(CrmBusinessStatusTypeSaveReqVO bean);
 
     CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean);
 

+ 2 - 5
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java

@@ -4,7 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 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.controller.admin.contact.vo.CrmContactRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
 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;
@@ -31,10 +32,6 @@ public interface CrmContactConvert {
 
     CrmContactRespVO convert(CrmContactDO bean);
 
-    List<CrmContactRespVO> convertList(List<CrmContactDO> list);
-
-    PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> page);
-
     @Mapping(target = "bizId", source = "reqVO.id")
     CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
 

+ 5 - 16
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java

@@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.crm.convert.contract;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
+import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
 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;
@@ -27,24 +28,12 @@ public interface CrmContractConvert {
 
     CrmContractConvert INSTANCE = Mappers.getMapper(CrmContractConvert.class);
 
-    CrmContractDO convert(CrmContractCreateReqVO bean);
-
-    CrmContractDO convert(CrmContractUpdateReqVO bean);
-
-    ContractRespVO convert(CrmContractDO bean);
-
-    List<ContractRespVO> convertList(List<CrmContractDO> list);
-
-    PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> page);
-
-    List<CrmContractExcelVO> convertList02(List<CrmContractDO> list);
-
     @Mapping(target = "bizId", source = "reqVO.id")
     CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId);
 
-    default PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
-                                                     List<CrmCustomerDO> customerList) {
-        PageResult<ContractRespVO> voPageResult = BeanUtils.toBean(pageResult, ContractRespVO.class);
+    default PageResult<CrmContractRespVO> convertPage(PageResult<CrmContractDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
+                                                      List<CrmCustomerDO> customerList) {
+        PageResult<CrmContractRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmContractRespVO.class);
         // 拼接关联字段
         Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
         voPageResult.getList().forEach(contract -> {

+ 0 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java

@@ -15,8 +15,6 @@ import lombok.*;
 import java.time.LocalDateTime;
 import java.util.List;
 
-// TODO @puhui999:界面:做成一个 list 列表,字段是 id、跟进人、跟进方式、跟进时间、跟进内容、下次联系时间、关联联系人、关联商机
-// TODO @puhui999:界面:记录时,弹窗,表单字段是跟进方式、跟进内容、下次联系时间、关联联系人、关联商机;其中关联联系人、关联商机,要做成对应的组件列。
 /**
  * 跟进记录 DO
  *

+ 44 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBusinessParseFunction.java

@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.crm.framework.operatelog.core;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
+import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
+import com.mzt.logapi.service.IParseFunction;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * CRM 商机的 {@link IParseFunction} 实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+@Slf4j
+public class CrmBusinessParseFunction implements IParseFunction {
+
+    public static final String NAME = "getBusinessById";
+
+    @Resource
+    private CrmBusinessService businessService;
+
+    @Override
+    public boolean executeBefore() {
+        return true; // 先转换值后对比
+    }
+
+    @Override
+    public String functionName() {
+        return NAME;
+    }
+
+    @Override
+    public String apply(Object value) {
+        if (StrUtil.isEmptyIfStr(value)) {
+            return "";
+        }
+        CrmBusinessDO businessDO = businessService.getBusiness(Long.parseLong(value.toString()));
+        return businessDO == null ? "" : businessDO.getName();
+    }
+
+}

+ 3 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java

@@ -1,10 +1,9 @@
 package cn.iocoder.yudao.module.crm.service.business;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
@@ -27,14 +26,14 @@ public interface CrmBusinessService {
      * @param userId      用户编号
      * @return 编号
      */
-    Long createBusiness(@Valid CrmBusinessCreateReqVO createReqVO, Long userId);
+    Long createBusiness(@Valid CrmBusinessSaveReqVO createReqVO, Long userId);
 
     /**
      * 更新商机
      *
      * @param updateReqVO 更新信息
      */
-    void updateBusiness(@Valid CrmBusinessUpdateReqVO updateReqVO);
+    void updateBusiness(@Valid CrmBusinessSaveReqVO updateReqVO);
 
     /**
      * 删除商机

+ 11 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java

@@ -4,10 +4,9 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO;
 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.contact.CrmContactBusinessDO;
@@ -55,9 +54,11 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}",
             success = CRM_BUSINESS_CREATE_SUCCESS)
-    public Long createBusiness(CrmBusinessCreateReqVO createReqVO, Long userId) {
+    public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) {
+        createReqVO.setId(null);
         // 1. 插入商机
-        CrmBusinessDO business = CrmBusinessConvert.INSTANCE.convert(createReqVO);
+        CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class)
+                .setOwnerUserId(userId);
         businessMapper.insert(business);
         // TODO 商机待定:插入商机与产品的关联表;校验商品存在
 
@@ -77,18 +78,18 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
     @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
             success = CRM_BUSINESS_UPDATE_SUCCESS)
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
-    public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) {
+    public void updateBusiness(CrmBusinessSaveReqVO updateReqVO) {
         // 1. 校验存在
         CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId());
 
         // 2. 更新商机
-        CrmBusinessDO updateObj = CrmBusinessConvert.INSTANCE.convert(updateReqVO);
+        CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class);
         businessMapper.updateById(updateObj);
         // TODO 商机待定:插入商机与产品的关联表;校验商品存在
 
         // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
         // 3. 记录操作日志上下文
-        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessUpdateReqVO.class));
+        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessSaveReqVO.class));
         LogRecordContext.putVariable("businessName", oldBusiness.getName());
     }
 
@@ -157,6 +158,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
 
     @Override
     public List<CrmBusinessDO> getBusinessList(Collection<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return ListUtil.empty();
+        }
         return businessMapper.selectBatchIds(ids);
     }
 

+ 4 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java

@@ -68,6 +68,7 @@ public class CrmContactServiceImpl implements CrmContactService {
     @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_CREATE_SUB_TYPE, bizNo = "{{#contact.id}}",
             success = CRM_CONTACT_CREATE_SUCCESS)
     public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
+        createReqVO.setId(null);
         // 1. 校验
         validateRelationDataExists(createReqVO);
 
@@ -209,6 +210,9 @@ public class CrmContactServiceImpl implements CrmContactService {
 
     @Override
     public List<CrmContactDO> getContactList(Collection<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return ListUtil.empty();
+        }
         return contactMapper.selectBatchIds(ids);
     }
 

+ 3 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java

@@ -1,10 +1,9 @@
 package cn.iocoder.yudao.module.crm.service.contract;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import jakarta.validation.Valid;
@@ -26,14 +25,14 @@ public interface CrmContractService {
      * @param userId      用户编号
      * @return 编号
      */
-    Long createContract(@Valid CrmContractCreateReqVO createReqVO, Long userId);
+    Long createContract(@Valid CrmContractSaveReqVO createReqVO, Long userId);
 
     /**
      * 更新合同
      *
      * @param updateReqVO 更新信息
      */
-    void updateContract(@Valid CrmContractUpdateReqVO updateReqVO);
+    void updateContract(@Valid CrmContractSaveReqVO updateReqVO);
 
     /**
      * 删除合同

+ 7 - 7
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java

@@ -4,10 +4,9 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO;
 import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
@@ -50,10 +49,11 @@ public class CrmContractServiceImpl implements CrmContractService {
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}",
             success = CRM_CONTRACT_CREATE_SUCCESS)
-    public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) {
+    public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) {
+        createReqVO.setId(null);
         // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
         // 插入合同
-        CrmContractDO contract = CrmContractConvert.INSTANCE.convert(createReqVO);
+        CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class);
         contractMapper.insert(contract);
 
         // 创建数据权限
@@ -71,17 +71,17 @@ public class CrmContractServiceImpl implements CrmContractService {
     @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
             success = CRM_CONTRACT_UPDATE_SUCCESS)
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
-    public void updateContract(CrmContractUpdateReqVO updateReqVO) {
+    public void updateContract(CrmContractSaveReqVO updateReqVO) {
         // TODO @合同待定:只有草稿、审批中,可以编辑;
         // 校验存在
         CrmContractDO oldContract = validateContractExists(updateReqVO.getId());
         // 更新合同
-        CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO);
+        CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class);
         contractMapper.updateById(updateObj);
         // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
 
         // 3. 记录操作日志上下文
-        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractUpdateReqVO.class));
+        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class));
         LogRecordContext.putVariable("contractName", oldContract.getName());
     }
 

+ 5 - 7
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java

@@ -1,16 +1,14 @@
 package cn.iocoder.yudao.module.crm.service.business;
 
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
+import jakarta.annotation.Resource;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.annotation.Import;
 
-import jakarta.annotation.Resource;
-
 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
@@ -39,7 +37,7 @@ public class CrmBusinessServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testCreateBusiness_success() {
         // 准备参数
-        CrmBusinessCreateReqVO reqVO = randomPojo(CrmBusinessCreateReqVO.class);
+        CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class);
 
         // 调用
         Long businessId = businessService.createBusiness(reqVO, getLoginUserId());
@@ -56,7 +54,7 @@ public class CrmBusinessServiceImplTest extends BaseDbUnitTest {
         CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class);
         businessMapper.insert(dbBusiness);// @Sql: 先插入出一条存在的数据
         // 准备参数
-        CrmBusinessUpdateReqVO reqVO = randomPojo(CrmBusinessUpdateReqVO.class, o -> {
+        CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class, o -> {
             o.setId(dbBusiness.getId()); // 设置更新的 ID
         });
 
@@ -70,7 +68,7 @@ public class CrmBusinessServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testUpdateBusiness_notExists() {
         // 准备参数
-        CrmBusinessUpdateReqVO reqVO = randomPojo(CrmBusinessUpdateReqVO.class);
+        CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class);
 
         // 调用, 并断言异常
         assertServiceException(() -> businessService.updateBusiness(reqVO), BUSINESS_NOT_EXISTS);

+ 4 - 5
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java

@@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.crm.service.contract;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
 import jakarta.annotation.Resource;
@@ -38,7 +37,7 @@ public class ContractServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testCreateContract_success() {
         // 准备参数
-        CrmContractCreateReqVO reqVO = randomPojo(CrmContractCreateReqVO.class);
+        CrmContractSaveReqVO reqVO = randomPojo(CrmContractSaveReqVO.class);
 
         // 调用
         Long contractId = contractService.createContract(reqVO, getLoginUserId());
@@ -55,7 +54,7 @@ public class ContractServiceImplTest extends BaseDbUnitTest {
         CrmContractDO dbContract = randomPojo(CrmContractDO.class);
         contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据
         // 准备参数
-        CrmContractUpdateReqVO reqVO = randomPojo(CrmContractUpdateReqVO.class, o -> {
+        CrmContractSaveReqVO reqVO = randomPojo(CrmContractSaveReqVO.class, o -> {
             o.setId(dbContract.getId()); // 设置更新的 ID
         });
 
@@ -69,7 +68,7 @@ public class ContractServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testUpdateContract_notExists() {
         // 准备参数
-        CrmContractUpdateReqVO reqVO = randomPojo(CrmContractUpdateReqVO.class);
+        CrmContractSaveReqVO reqVO = randomPojo(CrmContractSaveReqVO.class);
 
         // 调用, 并断言异常
         assertServiceException(() -> contractService.updateContract(reqVO), CONTRACT_NOT_EXISTS);