Commit 0719efb4c209e72f581d834dc19b745ac51e2b13

Authored by 芋道源码
Committed by Gitee
2 parents ecb36eef 866eaedf

!695 feat: 客户表的 crud

Merge pull request !695 from wanwan/feature/crm
Showing 22 changed files with 1010 additions and 11 deletions
sql/mysql/crm.sql
... ... @@ -180,3 +180,35 @@ CREATE TABLE `crm_contact` (
180 180 `tenant_id` bigint DEFAULT NULL,
181 181 PRIMARY KEY (`id`)
182 182 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='crm联系人';
  183 +
  184 +-- ----------------------------
  185 +-- 客户表
  186 +-- ----------------------------
  187 +CREATE TABLE `crm_customer` (
  188 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,主键自增',
  189 + `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户名称',
  190 + `follow_up_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '跟进状态',
  191 + `lock_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '锁定状态',
  192 + `deal_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '成交状态',
  193 + `mobile` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '手机',
  194 + `telephone` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '电话',
  195 + `website` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '网址',
  196 + `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
  197 + `owner_user_id` bigint DEFAULT NULL COMMENT '负责人的用户编号',
  198 + `ro_user_ids` varchar(4096) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '只读权限的用户编号数组',
  199 + `rw_user_ids` varchar(4096) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '读写权限的用户编号数组',
  200 + `area_id` bigint DEFAULT NULL COMMENT '地区编号',
  201 + `detail_address` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '详细地址',
  202 + `longitude` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地理位置经度',
  203 + `latitude` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地理位置维度',
  204 + `contact_last_time` datetime DEFAULT NULL COMMENT '最后跟进时间',
  205 + `contact_next_time` datetime DEFAULT NULL COMMENT '下次联系时间',
  206 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
  207 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  208 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
  209 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  210 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  211 + `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
  212 + PRIMARY KEY (`id`),
  213 + KEY `owner_user_id` (`owner_user_id`)
  214 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户表';
183 215 \ No newline at end of file
... ...
sql/mysql/crm_menu.sql
... ... @@ -360,3 +360,63 @@ VALUES (
360 360 '回款计划导出', 'crm:receivable-plan:export', 3, 5, @parentId,
361 361 '', '', '', 0
362 362 );
  363 +
  364 +-- ----------------------------
  365 +-- 客户管理菜单
  366 +-- ----------------------------
  367 +
  368 +-- 菜单 SQL
  369 +INSERT INTO system_menu(
  370 + name, permission, type, sort, parent_id,
  371 + path, icon, component, status, component_name
  372 +)
  373 +VALUES (
  374 + '客户管理', '', 2, 0, 2375,
  375 + 'customer', '', 'crm/customer/index', 0, 'CrmCustomer'
  376 +);
  377 +
  378 +-- 按钮父菜单ID
  379 +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
  380 +SELECT @parentId := LAST_INSERT_ID();
  381 +
  382 +-- 按钮 SQL
  383 +INSERT INTO system_menu(
  384 + name, permission, type, sort, parent_id,
  385 + path, icon, component, status
  386 +)
  387 +VALUES (
  388 + '客户查询', 'crm:customer:query', 3, 1, @parentId,
  389 + '', '', '', 0
  390 +);
  391 +INSERT INTO system_menu(
  392 + name, permission, type, sort, parent_id,
  393 + path, icon, component, status
  394 +)
  395 +VALUES (
  396 + '客户创建', 'crm:customer:create', 3, 2, @parentId,
  397 + '', '', '', 0
  398 +);
  399 +INSERT INTO system_menu(
  400 + name, permission, type, sort, parent_id,
  401 + path, icon, component, status
  402 +)
  403 +VALUES (
  404 + '客户更新', 'crm:customer:update', 3, 3, @parentId,
  405 + '', '', '', 0
  406 +);
  407 +INSERT INTO system_menu(
  408 + name, permission, type, sort, parent_id,
  409 + path, icon, component, status
  410 +)
  411 +VALUES (
  412 + '客户删除', 'crm:customer:delete', 3, 4, @parentId,
  413 + '', '', '', 0
  414 +);
  415 +INSERT INTO system_menu(
  416 + name, permission, type, sort, parent_id,
  417 + path, icon, component, status
  418 +)
  419 +VALUES (
  420 + '客户导出', 'crm:customer:export', 3, 5, @parentId,
  421 + '', '', '', 0
  422 +);
... ...
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
... ... @@ -26,4 +26,7 @@ public interface ErrorCodeConstants {
26 26  
27 27 ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_040_000_001, "回款计划不存在");
28 28  
  29 + // ========== 客户管理 1_020_006_000 ==========
  30 + ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在");
  31 +
29 32 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.customer;
2 2  
3 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.customer.vo.*;
  8 +import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  10 +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
  11 +import io.swagger.v3.oas.annotations.Operation;
  12 +import io.swagger.v3.oas.annotations.Parameter;
4 13 import io.swagger.v3.oas.annotations.tags.Tag;
  14 +import org.springframework.security.access.prepost.PreAuthorize;
5 15 import org.springframework.validation.annotation.Validated;
6   -import org.springframework.web.bind.annotation.GetMapping;
7   -import org.springframework.web.bind.annotation.RequestMapping;
8   -import org.springframework.web.bind.annotation.RestController;
  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;
9 24  
10 25 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  26 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
11 27  
12   -@Tag(name = "管理后台 - 客户信息")
  28 +@Tag(name = "管理后台 - 客户")
13 29 @RestController
14 30 @RequestMapping("/crm/customer")
15 31 @Validated
16 32 public class CrmCustomerController {
17 33  
18   - @GetMapping("/test")
19   - public CommonResult<String> test() {
20   - return success("hello");
  34 + @Resource
  35 + private CrmCustomerService customerService;
  36 +
  37 + @PostMapping("/create")
  38 + @Operation(summary = "创建客户")
  39 + @PreAuthorize("@ss.hasPermission('crm:customer:create')")
  40 + public CommonResult<Long> createCustomer(@Valid @RequestBody CrmCustomerCreateReqVO createReqVO) {
  41 + return success(customerService.createCustomer(createReqVO));
  42 + }
  43 +
  44 + @PutMapping("/update")
  45 + @Operation(summary = "更新客户")
  46 + @PreAuthorize("@ss.hasPermission('crm:customer:update')")
  47 + public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) {
  48 + customerService.updateCustomer(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:customer:delete')")
  56 + public CommonResult<Boolean> deleteCustomer(@RequestParam("id") Long id) {
  57 + customerService.deleteCustomer(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:customer:query')")
  65 + public CommonResult<CrmCustomerRespVO> getCustomer(@RequestParam("id") Long id) {
  66 + CrmCustomerDO customer = customerService.getCustomer(id);
  67 + return success(CrmCustomerConvert.INSTANCE.convert(customer));
  68 + }
  69 +
  70 + @GetMapping("/page")
  71 + @Operation(summary = "获得客户分页")
  72 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  73 + public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
  74 + PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO);
  75 + return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult));
  76 + }
  77 +
  78 + @GetMapping("/export-excel")
  79 + @Operation(summary = "导出客户 Excel")
  80 + @PreAuthorize("@ss.hasPermission('crm:customer:export')")
  81 + @OperateLog(type = EXPORT)
  82 + public void exportCustomerExcel(@Valid CrmCustomerExportReqVO exportReqVO,
  83 + HttpServletResponse response) throws IOException {
  84 + List<CrmCustomerDO> list = customerService.getCustomerList(exportReqVO);
  85 + // 导出 Excel
  86 + List<CrmCustomerExcelVO> datas = CrmCustomerConvert.INSTANCE.convertList02(list);
  87 + ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerExcelVO.class, datas);
21 88 }
22 89  
23 90 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.Mobile;
  4 +import cn.iocoder.yudao.framework.common.validation.Telephone;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import lombok.Data;
  7 +import org.springframework.format.annotation.DateTimeFormat;
  8 +
  9 +import javax.validation.constraints.NotEmpty;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.time.LocalDateTime;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +/**
  16 + * 客户 Base VO,提供给添加、修改、详细的子 VO 使用
  17 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  18 + */
  19 +@Data
  20 +public class CrmCustomerBaseVO {
  21 +
  22 + @Schema(description = "客户名称", example = "赵六")
  23 + @NotEmpty(message = "客户名称不能为空")
  24 + private String name;
  25 +
  26 + @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  27 + @NotNull(message = "跟进状态不能为空")
  28 + private Boolean followUpStatus;
  29 +
  30 + @Schema(description = "锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  31 + @NotNull(message = "锁定状态不能为空")
  32 + private Boolean lockStatus;
  33 +
  34 + @Schema(description = "手机", example = "18000000000")
  35 + @Mobile
  36 + private String mobile;
  37 +
  38 + @Schema(description = "电话", example = "18000000000")
  39 + @Telephone
  40 + private String telephone;
  41 +
  42 + @Schema(description = "网址", example = "https://www.baidu.com")
  43 + private String website;
  44 +
  45 + @Schema(description = "备注", example = "随便")
  46 + private String remark;
  47 +
  48 + @Schema(description = "负责人的用户编号", example = "25682")
  49 + @NotNull(message = "负责人不能为空")
  50 + private Long ownerUserId;
  51 +
  52 + @Schema(description = "地区编号", example = "20158")
  53 + private Long areaId;
  54 +
  55 + @Schema(description = "详细地址", example = "北京市海淀区")
  56 + private String detailAddress;
  57 +
  58 + @Schema(description = "地理位置经度", example = "116.40341")
  59 + private String longitude;
  60 +
  61 + @Schema(description = "地理位置维度", example = "39.92409")
  62 + private String latitude;
  63 +
  64 + @Schema(description = "最后跟进时间")
  65 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  66 + private LocalDateTime contactLastTime;
  67 +
  68 + @Schema(description = "下次联系时间")
  69 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  70 + private LocalDateTime contactNextTime;
  71 +
  72 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerCreateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import 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 CrmCustomerCreateReqVO extends CrmCustomerBaseVO {
  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/customer/vo/CrmCustomerExcelVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  4 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  5 +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
  6 +import com.alibaba.excel.annotation.ExcelProperty;
  7 +import lombok.Data;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +
  12 +/**
  13 + * 客户 Excel VO
  14 + *
  15 + * @author Wanwan
  16 + */
  17 +@Data
  18 +public class CrmCustomerExcelVO {
  19 +
  20 + @ExcelProperty("编号")
  21 + private Long id;
  22 +
  23 + @ExcelProperty("客户名称")
  24 + private String name;
  25 +
  26 + @ExcelProperty(value = "跟进状态", converter = DictConvert.class)
  27 + @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  28 + private Boolean followUpStatus;
  29 +
  30 + @ExcelProperty(value = "锁定状态", converter = DictConvert.class)
  31 + @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  32 + private Boolean lockStatus;
  33 +
  34 + @ExcelProperty(value = "成交状态", converter = DictConvert.class)
  35 + @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  36 + private Boolean dealStatus;
  37 +
  38 + @ExcelProperty("手机")
  39 + private String mobile;
  40 +
  41 + @ExcelProperty("电话")
  42 + private String telephone;
  43 +
  44 + @ExcelProperty("网址")
  45 + private String website;
  46 +
  47 + @ExcelProperty("备注")
  48 + private String remark;
  49 +
  50 + @ExcelProperty("负责人的用户编号")
  51 + private Long ownerUserId;
  52 +
  53 + @ExcelProperty("地区编号")
  54 + private Long areaId;
  55 +
  56 + @ExcelProperty("详细地址")
  57 + private String detailAddress;
  58 +
  59 + @ExcelProperty("地理位置经度")
  60 + private String longitude;
  61 +
  62 + @ExcelProperty("地理位置维度")
  63 + private String latitude;
  64 +
  65 + @ExcelProperty("最后跟进时间")
  66 + private LocalDateTime contactLastTime;
  67 +
  68 + @ExcelProperty("下次联系时间")
  69 + private LocalDateTime contactNextTime;
  70 +
  71 + @ExcelProperty("创建时间")
  72 + private LocalDateTime createTime;
  73 +
  74 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExportReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "管理后台 - 客户 Excel 导出 Request VO,参数和 CrmCustomerPageReqVO 是一致的")
  7 +@Data
  8 +public class CrmCustomerExportReqVO {
  9 +
  10 + @Schema(description = "客户名称", example = "赵六")
  11 + private String name;
  12 +
  13 + @Schema(description = "手机", example = "18000000000")
  14 + private String mobile;
  15 +
  16 + @Schema(description = "电话", example = "18000000000")
  17 + private String telephone;
  18 +
  19 + @Schema(description = "网址", example = "https://www.baidu.com")
  20 + private String website;
  21 +
  22 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.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 +
  9 +@Schema(description = "管理后台 - 客户分页 Request VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class CrmCustomerPageReqVO extends PageParam {
  14 +
  15 + @Schema(description = "客户名称", example = "赵六")
  16 + private String name;
  17 +
  18 + @Schema(description = "手机", example = "18000000000")
  19 + private String mobile;
  20 +
  21 + @Schema(description = "电话", example = "18000000000")
  22 + private String telephone;
  23 +
  24 + @Schema(description = "网址", example = "https://www.baidu.com")
  25 + private String website;
  26 +
  27 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import 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 CrmCustomerRespVO extends CrmCustomerBaseVO {
  15 +
  16 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
  17 + private Long id;
  18 +
  19 + @Schema(description = "成交状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  20 + private Boolean dealStatus;
  21 +
  22 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  23 + private LocalDateTime createTime;
  24 +
  25 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerUpdateReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import 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 CrmCustomerUpdateReqVO extends CrmCustomerBaseVO {
  15 +
  16 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
  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/customer/CrmCustomerConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.convert.customer;
  2 +
  3 +import java.util.*;
  4 +
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +
  7 +import org.mapstruct.Mapper;
  8 +import org.mapstruct.factory.Mappers;
  9 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
  10 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  11 +
  12 +/**
  13 + * 客户 Convert
  14 + *
  15 + * @author Wanwan
  16 + */
  17 +@Mapper
  18 +public interface CrmCustomerConvert {
  19 +
  20 + CrmCustomerConvert INSTANCE = Mappers.getMapper(CrmCustomerConvert.class);
  21 +
  22 + CrmCustomerDO convert(CrmCustomerCreateReqVO bean);
  23 +
  24 + CrmCustomerDO convert(CrmCustomerUpdateReqVO bean);
  25 +
  26 + CrmCustomerRespVO convert(CrmCustomerDO bean);
  27 +
  28 + List<CrmCustomerRespVO> convertList(List<CrmCustomerDO> list);
  29 +
  30 + PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> page);
  31 +
  32 + List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list);
  33 +
  34 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java
1 1 package cn.iocoder.yudao.module.crm.dal.dataobject.clue;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
4 5 import com.baomidou.mybatisplus.annotation.KeySequence;
5 6 import com.baomidou.mybatisplus.annotation.TableId;
6 7 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -43,8 +44,7 @@ public class CrmClueDO extends BaseDO {
43 44 private String name;
44 45 /**
45 46 * 客户 id
46   - *
47   - * // TODO @wanwan:要写下关联的实体,以及对应的属性哈
  47 + * 对应 {@link CrmCustomerDO#getId()}
48 48 */
49 49 private Long customerId;
50 50 /**
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.dal.dataobject.customer;
  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 com.sun.xml.bind.v2.TODO;
  8 +import lombok.*;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +/**
  13 + * 客户 DO
  14 + *
  15 + * @author Wanwan
  16 + */
  17 +@TableName("crm_customer")
  18 +@KeySequence("crm_customer_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class CrmCustomerDO extends BaseDO {
  26 +
  27 + /**
  28 + * 编号
  29 + */
  30 + @TableId
  31 + private Long id;
  32 + /**
  33 + * 客户名称
  34 + */
  35 + private String name;
  36 + /**
  37 + * 跟进状态
  38 + * <p>
  39 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  40 + */
  41 + private Boolean followUpStatus;
  42 + /**
  43 + * 锁定状态
  44 + * <p>
  45 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  46 + */
  47 + private Boolean lockStatus;
  48 + /**
  49 + * 成交状态
  50 + * <p>
  51 + * 枚举 {@link TODO infra_boolean_string 对应的类}
  52 + */
  53 + private Boolean dealStatus;
  54 + /**
  55 + * 手机
  56 + */
  57 + private String mobile;
  58 + /**
  59 + * 电话
  60 + */
  61 + private String telephone;
  62 + /**
  63 + * 网址
  64 + */
  65 + private String website;
  66 + /**
  67 + * 备注
  68 + */
  69 + private String remark;
  70 + /**
  71 + * 负责人的用户编号
  72 + */
  73 + private Long ownerUserId;
  74 + /**
  75 + * 只读权限的用户编号数组
  76 + */
  77 + private String roUserIds;
  78 + /**
  79 + * 读写权限的用户编号数组
  80 + */
  81 + private String rwUserIds;
  82 + /**
  83 + * 地区编号
  84 + */
  85 + private Long areaId;
  86 + /**
  87 + * 详细地址
  88 + */
  89 + private String detailAddress;
  90 + /**
  91 + * 地理位置经度
  92 + */
  93 + private String longitude;
  94 + /**
  95 + * 地理位置维度
  96 + */
  97 + private String latitude;
  98 + /**
  99 + * 最后跟进时间
  100 + */
  101 + private LocalDateTime contactLastTime;
  102 + /**
  103 + * 下次联系时间
  104 + */
  105 + private LocalDateTime contactNextTime;
  106 +
  107 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.dal.mysql.customer;
  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.customer.vo.CrmCustomerExportReqVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 客户 Mapper
  15 + *
  16 + * @author Wanwan
  17 + */
  18 +@Mapper
  19 +public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
  20 +
  21 + default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO reqVO) {
  22 + return selectPage(reqVO, new LambdaQueryWrapperX<CrmCustomerDO>()
  23 + .likeIfPresent(CrmCustomerDO::getName, reqVO.getName())
  24 + .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile())
  25 + .eqIfPresent(CrmCustomerDO::getTelephone, reqVO.getTelephone())
  26 + .likeIfPresent(CrmCustomerDO::getWebsite, reqVO.getWebsite())
  27 + .orderByDesc(CrmCustomerDO::getId));
  28 + }
  29 +
  30 + default List<CrmCustomerDO> selectList(CrmCustomerExportReqVO reqVO) {
  31 + return selectList(new LambdaQueryWrapperX<CrmCustomerDO>()
  32 + .likeIfPresent(CrmCustomerDO::getName, reqVO.getName())
  33 + .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile())
  34 + .eqIfPresent(CrmCustomerDO::getTelephone, reqVO.getTelephone())
  35 + .likeIfPresent(CrmCustomerDO::getWebsite, reqVO.getWebsite())
  36 + .orderByDesc(CrmCustomerDO::getId));
  37 + }
  38 +
  39 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
... ... @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO;
10 10 import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert;
11 11 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
12 12 import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper;
  13 +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
13 14 import org.springframework.stereotype.Service;
14 15 import org.springframework.validation.annotation.Validated;
15 16  
... ... @@ -19,6 +20,7 @@ import java.util.List;
19 20  
20 21 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 22 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS;
  23 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
22 24  
23 25 /**
24 26 * 线索 Service 实现类
... ... @@ -31,10 +33,13 @@ public class CrmClueServiceImpl implements CrmClueService {
31 33  
32 34 @Resource
33 35 private CrmClueMapper clueMapper;
  36 + @Resource
  37 + private CrmCustomerService customerService;
34 38  
35 39 @Override
36 40 public Long createClue(CrmClueCreateReqVO createReqVO) {
37   - // TODO @wanwan:校验客户是否存在;以及类似的逻辑哈;如果目前还缺对应的模块的 service,可以先给自己写 todo;
  41 + // 校验客户是否存在
  42 + validateCustomerExists(createReqVO.getCustomerId());
38 43 // 插入
39 44 CrmClueDO clue = CrmClueConvert.INSTANCE.convert(createReqVO);
40 45 clueMapper.insert(clue);
... ... @@ -44,9 +49,10 @@ public class CrmClueServiceImpl implements CrmClueService {
44 49  
45 50 @Override
46 51 public void updateClue(CrmClueUpdateReqVO updateReqVO) {
47   - // TODO @wanwan:校验客户是否存在;以及类似的逻辑哈;如果目前还缺对应的模块的 service,可以先给自己写 todo;
48 52 // 校验存在
49 53 validateClueExists(updateReqVO.getId());
  54 + // 校验客户是否存在
  55 + validateCustomerExists(updateReqVO.getCustomerId());
50 56  
51 57 // 更新
52 58 CrmClueDO updateObj = CrmClueConvert.INSTANCE.convert(updateReqVO);
... ... @@ -90,4 +96,15 @@ public class CrmClueServiceImpl implements CrmClueService {
90 96 return clueMapper.selectList(exportReqVO);
91 97 }
92 98  
  99 + /**
  100 + * 校验客户是否存在
  101 + *
  102 + * @param customerId 客户id
  103 + */
  104 + private void validateCustomerExists(Long customerId) {
  105 + if (customerService.getCustomer(customerId) == null) {
  106 + throw exception(CUSTOMER_NOT_EXISTS);
  107 + }
  108 + }
  109 +
93 110 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.customer;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO;
  8 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  9 +
  10 +import javax.validation.Valid;
  11 +import java.util.Collection;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 客户 Service 接口
  16 + *
  17 + * @author Wanwan
  18 + */
  19 +public interface CrmCustomerService {
  20 +
  21 + /**
  22 + * 创建客户
  23 + *
  24 + * @param createReqVO 创建信息
  25 + * @return 编号
  26 + */
  27 + Long createCustomer(@Valid CrmCustomerCreateReqVO createReqVO);
  28 +
  29 + /**
  30 + * 更新客户
  31 + *
  32 + * @param updateReqVO 更新信息
  33 + */
  34 + void updateCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO);
  35 +
  36 + /**
  37 + * 删除客户
  38 + *
  39 + * @param id 编号
  40 + */
  41 + void deleteCustomer(Long id);
  42 +
  43 + /**
  44 + * 获得客户
  45 + *
  46 + * @param id 编号
  47 + * @return 客户
  48 + */
  49 + CrmCustomerDO getCustomer(Long id);
  50 +
  51 + /**
  52 + * 获得客户列表
  53 + *
  54 + * @param ids 编号
  55 + * @return 客户列表
  56 + */
  57 + List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
  58 +
  59 + /**
  60 + * 获得客户分页
  61 + *
  62 + * @param pageReqVO 分页查询
  63 + * @return 客户分页
  64 + */
  65 + PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO);
  66 +
  67 + /**
  68 + * 获得客户列表, 用于 Excel 导出
  69 + *
  70 + * @param exportReqVO 查询条件
  71 + * @return 客户列表
  72 + */
  73 + List<CrmCustomerDO> getCustomerList(CrmCustomerExportReqVO exportReqVO);
  74 +
  75 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.customer;
  2 +
  3 +import org.springframework.stereotype.Service;
  4 +import javax.annotation.Resource;
  5 +import org.springframework.validation.annotation.Validated;
  6 +
  7 +import java.util.*;
  8 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  10 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  11 +
  12 +import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
  13 +import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  16 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
  17 +
  18 +import cn.hutool.core.collection.CollUtil;
  19 +import cn.hutool.core.collection.ListUtil;
  20 +
  21 +/**
  22 + * 客户 Service 实现类
  23 + *
  24 + * @author Wanwan
  25 + */
  26 +@Service
  27 +@Validated
  28 +public class CrmCustomerServiceImpl implements CrmCustomerService {
  29 +
  30 + @Resource
  31 + private CrmCustomerMapper customerMapper;
  32 +
  33 + @Override
  34 + public Long createCustomer(CrmCustomerCreateReqVO createReqVO) {
  35 + // 插入
  36 + CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO);
  37 + customerMapper.insert(customer);
  38 + // 返回
  39 + return customer.getId();
  40 + }
  41 +
  42 + @Override
  43 + public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
  44 + // 校验存在
  45 + validateCustomerExists(updateReqVO.getId());
  46 + // 更新
  47 + CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO);
  48 + customerMapper.updateById(updateObj);
  49 + }
  50 +
  51 + @Override
  52 + public void deleteCustomer(Long id) {
  53 + // 校验存在
  54 + validateCustomerExists(id);
  55 + // 删除
  56 + customerMapper.deleteById(id);
  57 + }
  58 +
  59 + private void validateCustomerExists(Long id) {
  60 + if (customerMapper.selectById(id) == null) {
  61 + throw exception(CUSTOMER_NOT_EXISTS);
  62 + }
  63 + }
  64 +
  65 + @Override
  66 + public CrmCustomerDO getCustomer(Long id) {
  67 + return customerMapper.selectById(id);
  68 + }
  69 +
  70 + @Override
  71 + public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {
  72 + if (CollUtil.isEmpty(ids)) {
  73 + return ListUtil.empty();
  74 + }
  75 + return customerMapper.selectBatchIds(ids);
  76 + }
  77 +
  78 + @Override
  79 + public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO) {
  80 + return customerMapper.selectPage(pageReqVO);
  81 + }
  82 +
  83 + @Override
  84 + public List<CrmCustomerDO> getCustomerList(CrmCustomerExportReqVO exportReqVO) {
  85 + return customerMapper.selectList(exportReqVO);
  86 + }
  87 +
  88 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/customer/CrmCustomerMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper">
  4 +
  5 + <!--
  6 + 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
  7 + 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
  8 + 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
  9 + 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
  10 + -->
  11 +
  12 +</mapper>
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.customer;
  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.customer.vo.CrmCustomerCreateReqVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
  8 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  10 +import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
  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.object.ObjectUtils.cloneIgnoreId;
  19 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  20 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  21 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  22 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  23 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
  24 +import static org.junit.jupiter.api.Assertions.*;
  25 +
  26 +/**
  27 + * {@link CrmCustomerServiceImpl} 的单元测试类
  28 + *
  29 + * @author Wanwan
  30 + */
  31 +@Import(CrmCustomerServiceImpl.class)
  32 +public class CrmCustomerServiceImplTest extends BaseDbUnitTest {
  33 +
  34 + @Resource
  35 + private CrmCustomerServiceImpl customerService;
  36 +
  37 + @Resource
  38 + private CrmCustomerMapper customerMapper;
  39 +
  40 + @Test
  41 + public void testCreateCustomer_success() {
  42 + // 准备参数
  43 + CrmCustomerCreateReqVO reqVO = randomPojo(CrmCustomerCreateReqVO.class);
  44 +
  45 + // 调用
  46 + Long customerId = customerService.createCustomer(reqVO);
  47 + // 断言
  48 + assertNotNull(customerId);
  49 + // 校验记录的属性是否正确
  50 + CrmCustomerDO customer = customerMapper.selectById(customerId);
  51 + assertPojoEquals(reqVO, customer);
  52 + }
  53 +
  54 + @Test
  55 + public void testUpdateCustomer_success() {
  56 + // mock 数据
  57 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class);
  58 + customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据
  59 + // 准备参数
  60 + CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class, o -> {
  61 + o.setId(dbCustomer.getId()); // 设置更新的 ID
  62 + });
  63 +
  64 + // 调用
  65 + customerService.updateCustomer(reqVO);
  66 + // 校验是否更新正确
  67 + CrmCustomerDO customer = customerMapper.selectById(reqVO.getId()); // 获取最新的
  68 + assertPojoEquals(reqVO, customer);
  69 + }
  70 +
  71 + @Test
  72 + public void testUpdateCustomer_notExists() {
  73 + // 准备参数
  74 + CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class);
  75 +
  76 + // 调用, 并断言异常
  77 + assertServiceException(() -> customerService.updateCustomer(reqVO), CUSTOMER_NOT_EXISTS);
  78 + }
  79 +
  80 + @Test
  81 + public void testDeleteCustomer_success() {
  82 + // mock 数据
  83 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class);
  84 + customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据
  85 + // 准备参数
  86 + Long id = dbCustomer.getId();
  87 +
  88 + // 调用
  89 + customerService.deleteCustomer(id);
  90 + // 校验数据不存在了
  91 + assertNull(customerMapper.selectById(id));
  92 + }
  93 +
  94 + @Test
  95 + public void testDeleteCustomer_notExists() {
  96 + // 准备参数
  97 + Long id = randomLongId();
  98 +
  99 + // 调用, 并断言异常
  100 + assertServiceException(() -> customerService.deleteCustomer(id), CUSTOMER_NOT_EXISTS);
  101 + }
  102 +
  103 + @Test
  104 + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
  105 + public void testGetCustomerPage() {
  106 + // mock 数据
  107 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到
  108 + o.setName(null);
  109 + o.setMobile(null);
  110 + o.setTelephone(null);
  111 + o.setWebsite(null);
  112 + });
  113 + customerMapper.insert(dbCustomer);
  114 + // 测试 name 不匹配
  115 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null)));
  116 + // 测试 mobile 不匹配
  117 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null)));
  118 + // 测试 telephone 不匹配
  119 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null)));
  120 + // 测试 website 不匹配
  121 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null)));
  122 + // 准备参数
  123 + CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO();
  124 + reqVO.setName(null);
  125 + reqVO.setMobile(null);
  126 + reqVO.setTelephone(null);
  127 + reqVO.setWebsite(null);
  128 +
  129 + // 调用
  130 + PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(reqVO);
  131 + // 断言
  132 + assertEquals(1, pageResult.getTotal());
  133 + assertEquals(1, pageResult.getList().size());
  134 + assertPojoEquals(dbCustomer, pageResult.getList().get(0));
  135 + }
  136 +
  137 + @Test
  138 + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
  139 + public void testGetCustomerList() {
  140 + // mock 数据
  141 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到
  142 + o.setName(null);
  143 + o.setMobile(null);
  144 + o.setTelephone(null);
  145 + o.setWebsite(null);
  146 + });
  147 + customerMapper.insert(dbCustomer);
  148 + // 测试 name 不匹配
  149 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null)));
  150 + // 测试 mobile 不匹配
  151 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null)));
  152 + // 测试 telephone 不匹配
  153 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null)));
  154 + // 测试 website 不匹配
  155 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null)));
  156 + // 准备参数
  157 + CrmCustomerExportReqVO reqVO = new CrmCustomerExportReqVO();
  158 + reqVO.setName(null);
  159 + reqVO.setMobile(null);
  160 + reqVO.setTelephone(null);
  161 + reqVO.setWebsite(null);
  162 +
  163 + // 调用
  164 + List<CrmCustomerDO> list = customerService.getCustomerList(reqVO);
  165 + // 断言
  166 + assertEquals(1, list.size());
  167 + assertPojoEquals(dbCustomer, list.get(0));
  168 + }
  169 +
  170 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql
... ... @@ -5,3 +5,5 @@ DELETE FROM &quot;crm_clue&quot;;
5 5 DELETE FROM "crm_receivable";
6 6  
7 7 DELETE FROM "crm_receivable_plan";
  8 +
  9 +DELETE FROM "crm_customer";
8 10 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql
... ... @@ -98,3 +98,30 @@ CREATE TABLE IF NOT EXISTS &quot;crm_receivable_plan&quot; (
98 98 PRIMARY KEY ("id")
99 99 ) COMMENT '回款计划';
100 100  
  101 +CREATE TABLE IF NOT EXISTS "crm_customer" (
  102 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  103 + "name" varchar,
  104 + "follow_up_status" bit NOT NULL,
  105 + "lock_status" bit NOT NULL,
  106 + "deal_status" bit NOT NULL,
  107 + "mobile" varchar,
  108 + "telephone" varchar,
  109 + "website" varchar,
  110 + "remark" varchar,
  111 + "owner_user_id" bigint,
  112 + "ro_user_ids" varchar,
  113 + "rw_user_ids" varchar,
  114 + "area_id" bigint,
  115 + "detail_address" varchar,
  116 + "longitude" varchar,
  117 + "latitude" varchar,
  118 + "contact_last_time" varchar,
  119 + "contact_next_time" varchar,
  120 + "creator" varchar DEFAULT '',
  121 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  122 + "updater" varchar DEFAULT '',
  123 + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  124 + "deleted" bit NOT NULL DEFAULT FALSE,
  125 + "tenant_id" bigint NOT NULL,
  126 + PRIMARY KEY ("id")
  127 +) COMMENT '客户表';
101 128 \ No newline at end of file
... ...