Commit 07f3d09e38c906adbb8c19c712d82622fbd1813f

Authored by 芋道源码
Committed by Gitee
2 parents 7e312aae 164be573

!671 CRM/合同管理 CRUD初稿

Merge pull request !671 from dhb52/feature/crm
Showing 23 changed files with 1134 additions and 7 deletions
sql/mysql/crm.sql 0 → 100644
  1 +SET NAMES utf8mb4;
  2 +
  3 +-- ----------------------------
  4 +-- 合同表
  5 +-- ----------------------------
  6 +DROP TABLE IF EXISTS `crm_contract`;
  7 +CREATE TABLE `crm_contract`
  8 +(
  9 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,主键自增',
  10 + `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '合同名称',
  11 + `customer_id` bigint DEFAULT NULL COMMENT '客户编号',
  12 + `business_id` bigint DEFAULT NULL COMMENT '商机编号',
  13 + `process_instance_id` bigint DEFAULT NULL COMMENT '工作流编号',
  14 + `order_date` datetime DEFAULT NULL COMMENT '下单日期',
  15 + `owner_user_id` bigint DEFAULT NULL COMMENT '负责人的用户编号',
  16 + `no` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '合同编号',
  17 + `start_time` datetime DEFAULT NULL COMMENT '开始时间',
  18 + `end_time` datetime DEFAULT NULL COMMENT '结束时间',
  19 + `price` int DEFAULT NULL COMMENT '合同金额',
  20 + `discount_percent` int DEFAULT NULL COMMENT '整单折扣',
  21 + `product_price` int DEFAULT NULL COMMENT '产品总金额',
  22 + `ro_user_ids` varchar(4096) DEFAULT NULL COMMENT '只读权限的用户编号数组',
  23 + `rw_user_ids` varchar(4096) DEFAULT NULL COMMENT '读写权限的用户编号数组',
  24 + `contact_id` bigint DEFAULT NULL COMMENT '联系人编号',
  25 + `sign_user_id` bigint DEFAULT NULL COMMENT '公司签约人',
  26 + `contact_last_time` datetime DEFAULT NULL COMMENT '最后跟进时间',
  27 +
  28 + -- 通用字段
  29 + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
  30 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
  31 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  32 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
  33 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  34 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  35 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  36 + PRIMARY KEY (`id`) USING BTREE
  37 +) ENGINE = InnoDB
  38 + CHARACTER SET = utf8mb4
  39 + COLLATE = utf8mb4_unicode_ci COMMENT ='合同表';
... ...
sql/mysql/crm_menu.sql 0 → 100644
  1 +-- ----------------------------
  2 +-- 合同菜单
  3 +-- ----------------------------
  4 +
  5 +-- 菜单 SQL
  6 +INSERT INTO system_menu(
  7 + name, permission, type, sort, parent_id,
  8 + path, icon, component, status, component_name
  9 +)
  10 +VALUES (
  11 + '合同管理', '', 2, 0, 1254,
  12 + 'contract', '', 'crm/contract/index', 0, 'Contract'
  13 +);
  14 +
  15 +-- 按钮父菜单ID
  16 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  17 +SELECT @parentId := LAST_INSERT_ID();
  18 +
  19 +-- 按钮 SQL
  20 +INSERT INTO system_menu(
  21 + name, permission, type, sort, parent_id,
  22 + path, icon, component, status
  23 +)
  24 +VALUES (
  25 + '合同查询', 'crm:contract:query', 3, 1, @parentId,
  26 + '', '', '', 0
  27 +);
  28 +INSERT INTO system_menu(
  29 + name, permission, type, sort, parent_id,
  30 + path, icon, component, status
  31 +)
  32 +VALUES (
  33 + '合同创建', 'crm:contract:create', 3, 2, @parentId,
  34 + '', '', '', 0
  35 +);
  36 +INSERT INTO system_menu(
  37 + name, permission, type, sort, parent_id,
  38 + path, icon, component, status
  39 +)
  40 +VALUES (
  41 + '合同更新', 'crm:contract:update', 3, 3, @parentId,
  42 + '', '', '', 0
  43 +);
  44 +INSERT INTO system_menu(
  45 + name, permission, type, sort, parent_id,
  46 + path, icon, component, status
  47 +)
  48 +VALUES (
  49 + '合同删除', 'crm:contract:delete', 3, 4, @parentId,
  50 + '', '', '', 0
  51 +);
  52 +INSERT INTO system_menu(
  53 + name, permission, type, sort, parent_id,
  54 + path, icon, component, status
  55 +)
  56 +VALUES (
  57 + '合同导出', 'crm:contract:export', 3, 5, @parentId,
  58 + '', '', '', 0
  59 +);
  60 +
  61 +-- ----------------------------
  62 +-- ...菜单
  63 +-- ----------------------------
0 64 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
1 1 package cn.iocoder.yudao.module.crm.enums;
2 2  
  3 +import cn.iocoder.yudao.framework.common.exception.ErrorCode;
  4 +
3 5 /**
4 6 * CRM 错误码枚举类
5 7 * <p>
... ... @@ -7,6 +9,7 @@ package cn.iocoder.yudao.module.crm.enums;
7 9 */
8 10 public interface ErrorCodeConstants {
9 11  
10   -
  12 + // ========== 合同管理 1-020-000-000 ==========
  13 + ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在");
11 14  
12 15 }
... ...
yudao-module-crm/yudao-module-crm-biz/pom.xml
1 1 <?xml version="1.0" encoding="UTF-8"?>
2   -<project xmlns="http://maven.apache.org/POM/4.0.0"
3   - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2 +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xmlns="http://maven.apache.org/POM/4.0.0"
4 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 5 <parent>
6 6 <groupId>cn.iocoder.boot</groupId>
... ... @@ -22,6 +22,11 @@
22 22 <artifactId>yudao-module-system-api</artifactId>
23 23 <version>${revision}</version>
24 24 </dependency>
  25 + <dependency>
  26 + <groupId>cn.iocoder.boot</groupId>
  27 + <artifactId>yudao-module-crm-api</artifactId>
  28 + <version>${revision}</version>
  29 + </dependency>
25 30  
26 31 <!-- 业务组件 -->
27 32 <dependency>
... ... @@ -46,6 +51,12 @@
46 51 <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
47 52 </dependency>
48 53  
  54 + <!-- 工具类相关 -->
  55 + <dependency>
  56 + <groupId>cn.iocoder.boot</groupId>
  57 + <artifactId>yudao-spring-boot-starter-excel</artifactId>
  58 + </dependency>
  59 +
49 60 <!-- Test 测试相关 -->
50 61 <dependency>
51 62 <groupId>cn.iocoder.boot</groupId>
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/package-info.java deleted
1   -/**
2   - * 联系人
3   - */
4   -package cn.iocoder.yudao.module.crm.controller.admin.contact;
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/ContractController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  6 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*;
  8 +import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
  10 +import cn.iocoder.yudao.module.crm.service.contract.ContractService;
  11 +import io.swagger.v3.oas.annotations.Operation;
  12 +import io.swagger.v3.oas.annotations.Parameter;
  13 +import io.swagger.v3.oas.annotations.tags.Tag;
  14 +import org.springframework.security.access.prepost.PreAuthorize;
  15 +import org.springframework.validation.annotation.Validated;
  16 +import org.springframework.web.bind.annotation.*;
  17 +
  18 +import javax.annotation.Resource;
  19 +import javax.servlet.http.HttpServletResponse;
  20 +import javax.validation.Valid;
  21 +import java.io.IOException;
  22 +import java.util.Collection;
  23 +import java.util.List;
  24 +
  25 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  26 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
  27 +
  28 +@Tag(name = "管理后台 - 合同")
  29 +@RestController
  30 +@RequestMapping("/crm/contract")
  31 +@Validated
  32 +public class ContractController {
  33 +
  34 + @Resource
  35 + private ContractService contractService;
  36 +
  37 + @PostMapping("/create")
  38 + @Operation(summary = "创建合同")
  39 + @PreAuthorize("@ss.hasPermission('crm:contract:create')")
  40 + public CommonResult<Long> createContract(@Valid @RequestBody ContractCreateReqVO createReqVO) {
  41 + return success(contractService.createContract(createReqVO));
  42 + }
  43 +
  44 + @PutMapping("/update")
  45 + @Operation(summary = "更新合同")
  46 + @PreAuthorize("@ss.hasPermission('crm:contract:update')")
  47 + public CommonResult<Boolean> updateContract(@Valid @RequestBody ContractUpdateReqVO updateReqVO) {
  48 + contractService.updateContract(updateReqVO);
  49 + return success(true);
  50 + }
  51 +
  52 + @DeleteMapping("/delete")
  53 + @Operation(summary = "删除合同")
  54 + @Parameter(name = "id", description = "编号", required = true)
  55 + @PreAuthorize("@ss.hasPermission('crm:contract:delete')")
  56 + public CommonResult<Boolean> deleteContract(@RequestParam("id") Long id) {
  57 + contractService.deleteContract(id);
  58 + return success(true);
  59 + }
  60 +
  61 + @GetMapping("/get")
  62 + @Operation(summary = "获得合同")
  63 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  64 + @PreAuthorize("@ss.hasPermission('crm:contract:query')")
  65 + public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) {
  66 + ContractDO contract = contractService.getContract(id);
  67 + return success(ContractConvert.INSTANCE.convert(contract));
  68 + }
  69 +
  70 + @GetMapping("/list")
  71 + @Operation(summary = "获得合同列表")
  72 + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
  73 + @PreAuthorize("@ss.hasPermission('crm:contract:query')")
  74 + public CommonResult<List<ContractRespVO>> getContractList(@RequestParam("ids") Collection<Long> ids) {
  75 + List<ContractDO> list = contractService.getContractList(ids);
  76 + return success(ContractConvert.INSTANCE.convertList(list));
  77 + }
  78 +
  79 + @GetMapping("/page")
  80 + @Operation(summary = "获得合同分页")
  81 + @PreAuthorize("@ss.hasPermission('crm:contract:query')")
  82 + public CommonResult<PageResult<ContractRespVO>> getContractPage(@Valid ContractPageReqVO pageVO) {
  83 + PageResult<ContractDO> pageResult = contractService.getContractPage(pageVO);
  84 + return success(ContractConvert.INSTANCE.convertPage(pageResult));
  85 + }
  86 +
  87 + @GetMapping("/export-excel")
  88 + @Operation(summary = "导出合同 Excel")
  89 + @PreAuthorize("@ss.hasPermission('crm:contract:export')")
  90 + @OperateLog(type = EXPORT)
  91 + public void exportContractExcel(@Valid ContractExportReqVO exportReqVO,
  92 + HttpServletResponse response) throws IOException {
  93 + List<ContractDO> list = contractService.getContractList(exportReqVO);
  94 + // 导出 Excel
  95 + List<ContractExcelVO> datas = ContractConvert.INSTANCE.convertList02(list);
  96 + ExcelUtils.write(response, "合同.xls", "数据", ContractExcelVO.class, datas);
  97 + }
  98 +
  99 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +import java.time.LocalDateTime;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +/**
  13 + * 合同 Base VO,提供给添加、修改、详细的子 VO 使用
  14 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  15 + */
  16 +@Data
  17 +public class ContractBaseVO {
  18 +
  19 + @Schema(description = "合同名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
  20 + @NotNull(message = "合同名称不能为空")
  21 + private String name;
  22 +
  23 + @Schema(description = "客户编号", example = "18336")
  24 + private Long customerId;
  25 +
  26 + @Schema(description = "商机编号", example = "10864")
  27 + private Long businessId;
  28 +
  29 + @Schema(description = "工作流编号", example = "1043")
  30 + private Long processInstanceId;
  31 +
  32 + @Schema(description = "下单日期")
  33 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  34 + private LocalDateTime orderDate;
  35 +
  36 + @Schema(description = "负责人的用户编号", example = "17144")
  37 + private Long ownerUserId;
  38 +
  39 + @Schema(description = "合同编号")
  40 + private String no;
  41 +
  42 + @Schema(description = "开始时间")
  43 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  44 + private LocalDateTime startTime;
  45 +
  46 + @Schema(description = "结束时间")
  47 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  48 + private LocalDateTime endTime;
  49 +
  50 + @Schema(description = "合同金额", example = "5617")
  51 + private Integer price;
  52 +
  53 + @Schema(description = "整单折扣")
  54 + private Integer discountPercent;
  55 +
  56 + @Schema(description = "产品总金额", example = "19510")
  57 + private Integer productPrice;
  58 +
  59 + @Schema(description = "联系人编号", example = "18546")
  60 + private Long contactId;
  61 +
  62 + @Schema(description = "公司签约人", example = "14036")
  63 + private Long signUserId;
  64 +
  65 + @Schema(description = "最后跟进时间")
  66 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  67 + private LocalDateTime contactLastTime;
  68 +
  69 + @Schema(description = "备注", example = "你猜")
  70 + private String remark;
  71 +
  72 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +@Schema(description = "管理后台 - 合同创建 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class ContractCreateReqVO extends ContractBaseVO {
  13 +
  14 + @Schema(description = "只读权限的用户编号数组")
  15 + private String roUserIds;
  16 +
  17 + @Schema(description = "读写权限的用户编号数组")
  18 + private String rwUserIds;
  19 +
  20 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
  2 +
  3 +import com.alibaba.excel.annotation.ExcelProperty;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + * 合同 Excel VO
  10 + *
  11 + * @author dhb52
  12 + */
  13 +@Data
  14 +public class ContractExcelVO {
  15 +
  16 + @ExcelProperty("合同编号")
  17 + private Long id;
  18 +
  19 + @ExcelProperty("合同名称")
  20 + private String name;
  21 +
  22 + @ExcelProperty("客户编号")
  23 + private Long customerId;
  24 +
  25 + @ExcelProperty("商机编号")
  26 + private Long businessId;
  27 +
  28 + @ExcelProperty("工作流编号")
  29 + private Long processInstanceId;
  30 +
  31 + @ExcelProperty("下单日期")
  32 + private LocalDateTime orderDate;
  33 +
  34 + @ExcelProperty("负责人的用户编号")
  35 + private Long ownerUserId;
  36 +
  37 + @ExcelProperty("合同编号")
  38 + private String no;
  39 +
  40 + @ExcelProperty("开始时间")
  41 + private LocalDateTime startTime;
  42 +
  43 + @ExcelProperty("结束时间")
  44 + private LocalDateTime endTime;
  45 +
  46 + @ExcelProperty("合同金额")
  47 + private Integer price;
  48 +
  49 + @ExcelProperty("整单折扣")
  50 + private Integer discountPercent;
  51 +
  52 + @ExcelProperty("产品总金额")
  53 + private Integer productPrice;
  54 +
  55 + @ExcelProperty("联系人编号")
  56 + private Long contactId;
  57 +
  58 + @ExcelProperty("公司签约人")
  59 + private Long signUserId;
  60 +
  61 + @ExcelProperty("最后跟进时间")
  62 + private LocalDateTime contactLastTime;
  63 +
  64 + @ExcelProperty("备注")
  65 + private String remark;
  66 +
  67 + @ExcelProperty("创建时间")
  68 + private LocalDateTime createTime;
  69 +
  70 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import org.springframework.format.annotation.DateTimeFormat;
  6 +
  7 +import java.time.LocalDateTime;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +
  11 +@Schema(description = "管理后台 - 合同 Excel 导出 Request VO,参数和 ContractPageReqVO 是一致的")
  12 +@Data
  13 +public class ContractExportReqVO {
  14 +
  15 + @Schema(description = "合同名称", example = "王五")
  16 + private String name;
  17 +
  18 + @Schema(description = "客户编号", example = "18336")
  19 + private Long customerId;
  20 +
  21 + @Schema(description = "商机编号", example = "10864")
  22 + private Long businessId;
  23 +
  24 + @Schema(description = "下单日期")
  25 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  26 + private LocalDateTime[] orderDate;
  27 +
  28 + @Schema(description = "合同编号")
  29 + private String no;
  30 +
  31 + @Schema(description = "整单折扣")
  32 + private Integer discountPercent;
  33 +
  34 + @Schema(description = "产品总金额", example = "19510")
  35 + private Integer productPrice;
  36 +
  37 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  13 +
  14 +@Schema(description = "管理后台 - 合同分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class ContractPageReqVO extends PageParam {
  19 +
  20 + @Schema(description = "合同名称", example = "王五")
  21 + private String name;
  22 +
  23 + @Schema(description = "客户编号", example = "18336")
  24 + private Long customerId;
  25 +
  26 + @Schema(description = "商机编号", example = "10864")
  27 + private Long businessId;
  28 +
  29 + @Schema(description = "下单日期")
  30 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  31 + private LocalDateTime[] orderDate;
  32 +
  33 + @Schema(description = "合同编号")
  34 + private String no;
  35 +
  36 + @Schema(description = "整单折扣")
  37 + private Integer discountPercent;
  38 +
  39 + @Schema(description = "产品总金额", example = "19510")
  40 + private Integer productPrice;
  41 +
  42 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +@Schema(description = "管理后台 - 合同 Response VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class ContractRespVO extends ContractBaseVO {
  15 +
  16 + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
  17 + private Long id;
  18 +
  19 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  20 + private LocalDateTime createTime;
  21 +
  22 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +import javax.validation.constraints.NotNull;
  9 +
  10 +@Schema(description = "管理后台 - 合同更新 Request VO")
  11 +@Data
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@ToString(callSuper = true)
  14 +public class ContractUpdateReqVO extends ContractBaseVO {
  15 +
  16 + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
  17 + @NotNull(message = "合同编号不能为空")
  18 + private Long id;
  19 +
  20 + @Schema(description = "只读权限的用户编号数组")
  21 + private String roUserIds;
  22 +
  23 + @Schema(description = "读写权限的用户编号数组")
  24 + private String rwUserIds;
  25 +
  26 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.convert.contract;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExcelVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractRespVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
  9 +import org.mapstruct.Mapper;
  10 +import org.mapstruct.factory.Mappers;
  11 +
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 合同 Convert
  16 + *
  17 + * @author dhb52
  18 + */
  19 +@Mapper
  20 +public interface ContractConvert {
  21 +
  22 + ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class);
  23 +
  24 + ContractDO convert(ContractCreateReqVO bean);
  25 +
  26 + ContractDO convert(ContractUpdateReqVO bean);
  27 +
  28 + ContractRespVO convert(ContractDO bean);
  29 +
  30 + List<ContractRespVO> convertList(List<ContractDO> list);
  31 +
  32 + PageResult<ContractRespVO> convertPage(PageResult<ContractDO> page);
  33 +
  34 + List<ContractExcelVO> convertList02(List<ContractDO> list);
  35 +
  36 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/ContractDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.dal.dataobject.contract;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +/**
  12 + * 合同 DO
  13 + *
  14 + * @author dhb52
  15 + */
  16 +@TableName("crm_contract")
  17 +@KeySequence("crm_contract_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class ContractDO extends BaseDO {
  25 +
  26 + /**
  27 + * 合同编号
  28 + */
  29 + @TableId
  30 + private Long id;
  31 + /**
  32 + * 合同名称
  33 + */
  34 + private String name;
  35 + /**
  36 + * 客户编号
  37 + */
  38 + private Long customerId;
  39 + /**
  40 + * 商机编号
  41 + */
  42 + private Long businessId;
  43 + /**
  44 + * 工作流编号
  45 + */
  46 + private Long processInstanceId;
  47 + /**
  48 + * 下单日期
  49 + */
  50 + private LocalDateTime orderDate;
  51 + /**
  52 + * 负责人的用户编号
  53 + */
  54 + private Long ownerUserId;
  55 + /**
  56 + * 合同编号
  57 + */
  58 + private String no;
  59 + /**
  60 + * 开始时间
  61 + */
  62 + private LocalDateTime startTime;
  63 + /**
  64 + * 结束时间
  65 + */
  66 + private LocalDateTime endTime;
  67 + /**
  68 + * 合同金额
  69 + */
  70 + private Integer price;
  71 + /**
  72 + * 整单折扣
  73 + */
  74 + private Integer discountPercent;
  75 + /**
  76 + * 产品总金额
  77 + */
  78 + private Integer productPrice;
  79 + /**
  80 + * 只读权限的用户编号数组
  81 + */
  82 + private String roUserIds;
  83 + /**
  84 + * 读写权限的用户编号数组
  85 + */
  86 + private String rwUserIds;
  87 + /**
  88 + * 联系人编号
  89 + */
  90 + private Long contactId;
  91 + /**
  92 + * 公司签约人
  93 + */
  94 + private Long signUserId;
  95 + /**
  96 + * 最后跟进时间
  97 + */
  98 + private LocalDateTime contactLastTime;
  99 + /**
  100 + * 备注
  101 + */
  102 + private String remark;
  103 +
  104 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/ContractMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.dal.mysql.contract;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 合同 Mapper
  15 + *
  16 + * @author dhb52
  17 + */
  18 +@Mapper
  19 +public interface ContractMapper extends BaseMapperX<ContractDO> {
  20 +
  21 + default PageResult<ContractDO> selectPage(ContractPageReqVO reqVO) {
  22 + return selectPage(reqVO, new LambdaQueryWrapperX<ContractDO>()
  23 + .likeIfPresent(ContractDO::getName, reqVO.getName())
  24 + .eqIfPresent(ContractDO::getCustomerId, reqVO.getCustomerId())
  25 + .eqIfPresent(ContractDO::getBusinessId, reqVO.getBusinessId())
  26 + .betweenIfPresent(ContractDO::getOrderDate, reqVO.getOrderDate())
  27 + .eqIfPresent(ContractDO::getNo, reqVO.getNo())
  28 + .eqIfPresent(ContractDO::getDiscountPercent, reqVO.getDiscountPercent())
  29 + .eqIfPresent(ContractDO::getProductPrice, reqVO.getProductPrice())
  30 + .orderByDesc(ContractDO::getId));
  31 + }
  32 +
  33 + default List<ContractDO> selectList(ContractExportReqVO reqVO) {
  34 + return selectList(new LambdaQueryWrapperX<ContractDO>()
  35 + .likeIfPresent(ContractDO::getName, reqVO.getName())
  36 + .eqIfPresent(ContractDO::getCustomerId, reqVO.getCustomerId())
  37 + .eqIfPresent(ContractDO::getBusinessId, reqVO.getBusinessId())
  38 + .betweenIfPresent(ContractDO::getOrderDate, reqVO.getOrderDate())
  39 + .eqIfPresent(ContractDO::getNo, reqVO.getNo())
  40 + .eqIfPresent(ContractDO::getDiscountPercent, reqVO.getDiscountPercent())
  41 + .eqIfPresent(ContractDO::getProductPrice, reqVO.getProductPrice())
  42 + .orderByDesc(ContractDO::getId));
  43 + }
  44 +
  45 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.contract;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
  9 +
  10 +import javax.validation.Valid;
  11 +import java.util.Collection;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 合同 Service 接口
  16 + *
  17 + * @author dhb52
  18 + */
  19 +public interface ContractService {
  20 +
  21 + /**
  22 + * 创建合同
  23 + *
  24 + * @param createReqVO 创建信息
  25 + * @return 编号
  26 + */
  27 + Long createContract(@Valid ContractCreateReqVO createReqVO);
  28 +
  29 + /**
  30 + * 更新合同
  31 + *
  32 + * @param updateReqVO 更新信息
  33 + */
  34 + void updateContract(@Valid ContractUpdateReqVO updateReqVO);
  35 +
  36 + /**
  37 + * 删除合同
  38 + *
  39 + * @param id 编号
  40 + */
  41 + void deleteContract(Long id);
  42 +
  43 + /**
  44 + * 获得合同
  45 + *
  46 + * @param id 编号
  47 + * @return 合同
  48 + */
  49 + ContractDO getContract(Long id);
  50 +
  51 + /**
  52 + * 获得合同列表
  53 + *
  54 + * @param ids 编号
  55 + * @return 合同列表
  56 + */
  57 + List<ContractDO> getContractList(Collection<Long> ids);
  58 +
  59 + /**
  60 + * 获得合同分页
  61 + *
  62 + * @param pageReqVO 分页查询
  63 + * @return 合同分页
  64 + */
  65 + PageResult<ContractDO> getContractPage(ContractPageReqVO pageReqVO);
  66 +
  67 + /**
  68 + * 获得合同列表, 用于 Excel 导出
  69 + *
  70 + * @param exportReqVO 查询条件
  71 + * @return 合同列表
  72 + */
  73 + List<ContractDO> getContractList(ContractExportReqVO exportReqVO);
  74 +
  75 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.contract;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.collection.ListUtil;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO;
  8 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
  9 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
  10 +import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
  11 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
  12 +import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper;
  13 +import org.springframework.stereotype.Service;
  14 +import org.springframework.validation.annotation.Validated;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.Collection;
  18 +import java.util.List;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  21 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS;
  22 +
  23 +/**
  24 + * 合同 Service 实现类
  25 + *
  26 + * @author dhb52
  27 + */
  28 +@Service
  29 +@Validated
  30 +public class ContractServiceImpl implements ContractService {
  31 +
  32 + @Resource
  33 + private ContractMapper contractMapper;
  34 +
  35 + @Override
  36 + public Long createContract(ContractCreateReqVO createReqVO) {
  37 + // 插入
  38 + ContractDO contract = ContractConvert.INSTANCE.convert(createReqVO);
  39 + contractMapper.insert(contract);
  40 + // 返回
  41 + return contract.getId();
  42 + }
  43 +
  44 + @Override
  45 + public void updateContract(ContractUpdateReqVO updateReqVO) {
  46 + // 校验存在
  47 + validateContractExists(updateReqVO.getId());
  48 + // 更新
  49 + ContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO);
  50 + contractMapper.updateById(updateObj);
  51 + }
  52 +
  53 + @Override
  54 + public void deleteContract(Long id) {
  55 + // 校验存在
  56 + validateContractExists(id);
  57 + // 删除
  58 + contractMapper.deleteById(id);
  59 + }
  60 +
  61 + private void validateContractExists(Long id) {
  62 + if (contractMapper.selectById(id) == null) {
  63 + throw exception(CONTRACT_NOT_EXISTS);
  64 + }
  65 + }
  66 +
  67 + @Override
  68 + public ContractDO getContract(Long id) {
  69 + return contractMapper.selectById(id);
  70 + }
  71 +
  72 + @Override
  73 + public List<ContractDO> getContractList(Collection<Long> ids) {
  74 + if (CollUtil.isEmpty(ids)) {
  75 + return ListUtil.empty();
  76 + }
  77 + return contractMapper.selectBatchIds(ids);
  78 + }
  79 +
  80 + @Override
  81 + public PageResult<ContractDO> getContractPage(ContractPageReqVO pageReqVO) {
  82 + return contractMapper.selectPage(pageReqVO);
  83 + }
  84 +
  85 + @Override
  86 + public List<ContractDO> getContractList(ContractExportReqVO exportReqVO) {
  87 + return contractMapper.selectList(exportReqVO);
  88 + }
  89 +
  90 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.contract;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
  8 +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
  10 +import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper;
  11 +import org.junit.jupiter.api.Disabled;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.springframework.context.annotation.Import;
  14 +
  15 +import javax.annotation.Resource;
  16 +import java.util.List;
  17 +
  18 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
  19 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  20 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  21 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  22 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  23 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  24 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS;
  25 +import static org.junit.jupiter.api.Assertions.*;
  26 +
  27 +/**
  28 + * {@link ContractServiceImpl} 的单元测试类
  29 + *
  30 + * @author dhb52
  31 + */
  32 +@Import(ContractServiceImpl.class)
  33 +public class ContractServiceImplTest extends BaseDbUnitTest {
  34 +
  35 + @Resource
  36 + private ContractServiceImpl contractService;
  37 +
  38 + @Resource
  39 + private ContractMapper contractMapper;
  40 +
  41 + @Test
  42 + public void testCreateContract_success() {
  43 + // 准备参数
  44 + ContractCreateReqVO reqVO = randomPojo(ContractCreateReqVO.class);
  45 +
  46 + // 调用
  47 + Long contractId = contractService.createContract(reqVO);
  48 + // 断言
  49 + assertNotNull(contractId);
  50 + // 校验记录的属性是否正确
  51 + ContractDO contract = contractMapper.selectById(contractId);
  52 + assertPojoEquals(reqVO, contract);
  53 + }
  54 +
  55 + @Test
  56 + public void testUpdateContract_success() {
  57 + // mock 数据
  58 + ContractDO dbContract = randomPojo(ContractDO.class);
  59 + contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据
  60 + // 准备参数
  61 + ContractUpdateReqVO reqVO = randomPojo(ContractUpdateReqVO.class, o -> {
  62 + o.setId(dbContract.getId()); // 设置更新的 ID
  63 + });
  64 +
  65 + // 调用
  66 + contractService.updateContract(reqVO);
  67 + // 校验是否更新正确
  68 + ContractDO contract = contractMapper.selectById(reqVO.getId()); // 获取最新的
  69 + assertPojoEquals(reqVO, contract);
  70 + }
  71 +
  72 + @Test
  73 + public void testUpdateContract_notExists() {
  74 + // 准备参数
  75 + ContractUpdateReqVO reqVO = randomPojo(ContractUpdateReqVO.class);
  76 +
  77 + // 调用, 并断言异常
  78 + assertServiceException(() -> contractService.updateContract(reqVO), CONTRACT_NOT_EXISTS);
  79 + }
  80 +
  81 + @Test
  82 + public void testDeleteContract_success() {
  83 + // mock 数据
  84 + ContractDO dbContract = randomPojo(ContractDO.class);
  85 + contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据
  86 + // 准备参数
  87 + Long id = dbContract.getId();
  88 +
  89 + // 调用
  90 + contractService.deleteContract(id);
  91 + // 校验数据不存在了
  92 + assertNull(contractMapper.selectById(id));
  93 + }
  94 +
  95 + @Test
  96 + public void testDeleteContract_notExists() {
  97 + // 准备参数
  98 + Long id = randomLongId();
  99 +
  100 + // 调用, 并断言异常
  101 + assertServiceException(() -> contractService.deleteContract(id), CONTRACT_NOT_EXISTS);
  102 + }
  103 +
  104 + @Test
  105 + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
  106 + public void testGetContractPage() {
  107 + // mock 数据
  108 + ContractDO dbContract = randomPojo(ContractDO.class, o -> { // 等会查询到
  109 + o.setName(null);
  110 + o.setCustomerId(null);
  111 + o.setBusinessId(null);
  112 + o.setOrderDate(null);
  113 + o.setNo(null);
  114 + o.setDiscountPercent(null);
  115 + o.setProductPrice(null);
  116 + });
  117 + contractMapper.insert(dbContract);
  118 + // 测试 name 不匹配
  119 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setName(null)));
  120 + // 测试 customerId 不匹配
  121 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setCustomerId(null)));
  122 + // 测试 businessId 不匹配
  123 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setBusinessId(null)));
  124 + // 测试 orderDate 不匹配
  125 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setOrderDate(null)));
  126 + // 测试 no 不匹配
  127 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setNo(null)));
  128 + // 测试 discountPercent 不匹配
  129 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setDiscountPercent(null)));
  130 + // 测试 productPrice 不匹配
  131 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setProductPrice(null)));
  132 + // 准备参数
  133 + ContractPageReqVO reqVO = new ContractPageReqVO();
  134 + reqVO.setName(null);
  135 + reqVO.setCustomerId(null);
  136 + reqVO.setBusinessId(null);
  137 + reqVO.setOrderDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
  138 + reqVO.setNo(null);
  139 + reqVO.setDiscountPercent(null);
  140 + reqVO.setProductPrice(null);
  141 +
  142 + // 调用
  143 + PageResult<ContractDO> pageResult = contractService.getContractPage(reqVO);
  144 + // 断言
  145 + assertEquals(1, pageResult.getTotal());
  146 + assertEquals(1, pageResult.getList().size());
  147 + assertPojoEquals(dbContract, pageResult.getList().get(0));
  148 + }
  149 +
  150 + @Test
  151 + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
  152 + public void testGetContractList() {
  153 + // mock 数据
  154 + ContractDO dbContract = randomPojo(ContractDO.class, o -> { // 等会查询到
  155 + o.setName("合同名称");
  156 + o.setCustomerId(null);
  157 + o.setBusinessId(null);
  158 + o.setOrderDate(null);
  159 + o.setNo(null);
  160 + o.setDiscountPercent(null);
  161 + o.setProductPrice(null);
  162 + });
  163 + contractMapper.insert(dbContract);
  164 + // 测试 name 不匹配
  165 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setName(null)));
  166 + // 测试 customerId 不匹配
  167 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setCustomerId(null)));
  168 + // 测试 businessId 不匹配
  169 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setBusinessId(null)));
  170 + // 测试 orderDate 不匹配
  171 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setOrderDate(null)));
  172 + // 测试 no 不匹配
  173 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setNo(null)));
  174 + // 测试 discountPercent 不匹配
  175 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setDiscountPercent(null)));
  176 + // 测试 productPrice 不匹配
  177 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setProductPrice(null)));
  178 + // 准备参数
  179 + ContractExportReqVO reqVO = new ContractExportReqVO();
  180 + reqVO.setName(null);
  181 + reqVO.setCustomerId(null);
  182 + reqVO.setBusinessId(null);
  183 + reqVO.setOrderDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
  184 + reqVO.setNo(null);
  185 + reqVO.setDiscountPercent(null);
  186 + reqVO.setProductPrice(null);
  187 +
  188 + // 调用
  189 + List<ContractDO> list = contractService.getContractList(reqVO);
  190 + // 断言
  191 + assertEquals(1, list.size());
  192 + assertPojoEquals(dbContract, list.get(0));
  193 + }
  194 +
  195 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/resources/application-unit-test.yaml 0 → 100644
  1 +spring:
  2 + main:
  3 + lazy-initialization: true # 开启懒加载,加快速度
  4 + banner-mode: off # 单元测试,禁用 Banner
  5 +
  6 +--- #################### 数据库相关配置 ####################
  7 +
  8 +spring:
  9 + # 数据源配置项
  10 + datasource:
  11 + name: ruoyi-vue-pro
  12 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  13 + driver-class-name: org.h2.Driver
  14 + username: sa
  15 + password:
  16 + druid:
  17 + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
  18 + initial-size: 1 # 单元测试,配置为 1,提升启动速度
  19 + sql:
  20 + init:
  21 + schema-locations: classpath:/sql/create_tables.sql
  22 +
  23 + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  24 + redis:
  25 + host: 127.0.0.1 # 地址
  26 + port: 16379 # 端口(单元测试,使用 16379 端口)
  27 + database: 0 # 数据库索引
  28 +
  29 +mybatis-plus:
  30 + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
  31 + type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
  32 +
  33 +--- #################### 定时任务相关配置 ####################
  34 +
  35 +--- #################### 配置中心相关配置 ####################
  36 +
  37 +--- #################### 服务保障相关配置 ####################
  38 +
  39 +# Lock4j 配置项(单元测试,禁用 Lock4j)
  40 +
  41 +# Resilience4j 配置项
  42 +
  43 +--- #################### 监控相关配置 ####################
  44 +
  45 +--- #################### 芋道相关配置 ####################
  46 +
  47 +# 芋道配置项,设置当前项目所有自定义的配置
  48 +yudao:
  49 + info:
  50 + base-package: cn.iocoder.yudao
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/resources/logback.xml 0 → 100644
  1 +<configuration>
  2 + <!-- 引用 Spring Boot 的 logback 基础配置 -->
  3 + <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
  4 +</configuration>
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql 0 → 100644
  1 +DELETE FROM "crm_contract";
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql 0 → 100644
  1 +CREATE TABLE IF NOT EXISTS "crm_contract" (
  2 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  3 + "name" varchar NOT NULL,
  4 + "customer_id" bigint,
  5 + "business_id" bigint,
  6 + "process_instance_id" bigint,
  7 + "order_date" varchar,
  8 + "owner_user_id" bigint,
  9 + "no" varchar,
  10 + "start_time" varchar,
  11 + "end_time" varchar,
  12 + "price" int,
  13 + "discount_percent" int,
  14 + "product_price" int,
  15 + "ro_user_ids" varchar,
  16 + "rw_user_ids" varchar,
  17 + "contact_id" bigint,
  18 + "sign_user_id" bigint,
  19 + "contact_last_time" varchar,
  20 + "remark" varchar,
  21 + "creator" varchar DEFAULT '',
  22 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  23 + "updater" varchar DEFAULT '',
  24 + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  25 + "deleted" bit NOT NULL DEFAULT FALSE,
  26 + PRIMARY KEY ("id")
  27 + ) COMMENT '合同表';
0 28 \ No newline at end of file
... ...