mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-28 08:48:43 +08:00 
			
		
		
		
	| @@ -180,3 +180,35 @@ CREATE TABLE `crm_contact` ( | ||||
|                                `tenant_id` bigint DEFAULT NULL, | ||||
|                                PRIMARY KEY (`id`) | ||||
| ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='crm联系人'; | ||||
|  | ||||
| -- ---------------------------- | ||||
| -- 客户表 | ||||
| -- ---------------------------- | ||||
| CREATE TABLE `crm_customer` ( | ||||
|     `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,主键自增', | ||||
|     `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户名称', | ||||
|     `follow_up_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '跟进状态', | ||||
|     `lock_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '锁定状态', | ||||
|     `deal_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '成交状态', | ||||
|     `mobile` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '手机', | ||||
|     `telephone` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '电话', | ||||
|     `website` varchar(1024) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '网址', | ||||
|     `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', | ||||
|     `owner_user_id` bigint DEFAULT NULL COMMENT '负责人的用户编号', | ||||
|     `ro_user_ids` varchar(4096) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '只读权限的用户编号数组', | ||||
|     `rw_user_ids` varchar(4096) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '读写权限的用户编号数组', | ||||
|     `area_id` bigint DEFAULT NULL COMMENT '地区编号', | ||||
|     `detail_address` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '详细地址', | ||||
|     `longitude` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地理位置经度', | ||||
|     `latitude` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地理位置维度', | ||||
|     `contact_last_time` datetime DEFAULT NULL COMMENT '最后跟进时间', | ||||
|     `contact_next_time` datetime DEFAULT NULL COMMENT '下次联系时间', | ||||
|     `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', | ||||
|     `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | ||||
|     `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', | ||||
|     `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | ||||
|     `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | ||||
|     `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', | ||||
|     PRIMARY KEY (`id`), | ||||
|     KEY `owner_user_id` (`owner_user_id`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户表'; | ||||
| @@ -360,3 +360,63 @@ VALUES ( | ||||
|            '回款计划导出', 'crm:receivable-plan:export', 3, 5, @parentId, | ||||
|            '', '', '', 0 | ||||
|        ); | ||||
|  | ||||
| -- ---------------------------- | ||||
| -- 客户管理菜单 | ||||
| -- ---------------------------- | ||||
|  | ||||
| -- 菜单 SQL | ||||
| INSERT INTO system_menu( | ||||
|     name, permission, type, sort, parent_id, | ||||
|     path, icon, component, status, component_name | ||||
| ) | ||||
| VALUES ( | ||||
|    '客户管理', '', 2, 0, 2375, | ||||
|    'customer', '', 'crm/customer/index', 0, 'CrmCustomer' | ||||
| ); | ||||
|  | ||||
| -- 按钮父菜单ID | ||||
| -- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 | ||||
| SELECT @parentId := LAST_INSERT_ID(); | ||||
|  | ||||
| -- 按钮 SQL | ||||
| INSERT INTO system_menu( | ||||
|     name, permission, type, sort, parent_id, | ||||
|     path, icon, component, status | ||||
| ) | ||||
| VALUES ( | ||||
|    '客户查询', 'crm:customer:query', 3, 1, @parentId, | ||||
|    '', '', '', 0 | ||||
| ); | ||||
| INSERT INTO system_menu( | ||||
|     name, permission, type, sort, parent_id, | ||||
|     path, icon, component, status | ||||
| ) | ||||
| VALUES ( | ||||
|    '客户创建', 'crm:customer:create', 3, 2, @parentId, | ||||
|    '', '', '', 0 | ||||
| ); | ||||
| INSERT INTO system_menu( | ||||
|     name, permission, type, sort, parent_id, | ||||
|     path, icon, component, status | ||||
| ) | ||||
| VALUES ( | ||||
|    '客户更新', 'crm:customer:update', 3, 3, @parentId, | ||||
|    '', '', '', 0 | ||||
| ); | ||||
| INSERT INTO system_menu( | ||||
|     name, permission, type, sort, parent_id, | ||||
|     path, icon, component, status | ||||
| ) | ||||
| VALUES ( | ||||
|    '客户删除', 'crm:customer:delete', 3, 4, @parentId, | ||||
|    '', '', '', 0 | ||||
| ); | ||||
| INSERT INTO system_menu( | ||||
|     name, permission, type, sort, parent_id, | ||||
|     path, icon, component, status | ||||
| ) | ||||
| VALUES ( | ||||
|    '客户导出', 'crm:customer:export', 3, 5, @parentId, | ||||
|    '', '', '', 0 | ||||
| ); | ||||
|   | ||||
| @@ -26,4 +26,7 @@ public interface ErrorCodeConstants { | ||||
|  | ||||
|     ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_040_000_001, "回款计划不存在"); | ||||
|  | ||||
|     // ========== 客户管理 1_020_006_000 ========== | ||||
|     ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在"); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,23 +1,90 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | ||||
| import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | ||||
| import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import javax.validation.Valid; | ||||
| import java.io.IOException; | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
| import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | ||||
|  | ||||
| @Tag(name = "管理后台 - 客户信息") | ||||
| @Tag(name = "管理后台 - 客户") | ||||
| @RestController | ||||
| @RequestMapping("/crm/customer") | ||||
| @Validated | ||||
| public class CrmCustomerController { | ||||
|  | ||||
|     @GetMapping("/test") | ||||
|     public CommonResult<String> test() { | ||||
|         return success("hello"); | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|  | ||||
|     @PostMapping("/create") | ||||
|     @Operation(summary = "创建客户") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:create')") | ||||
|     public CommonResult<Long> createCustomer(@Valid @RequestBody CrmCustomerCreateReqVO createReqVO) { | ||||
|         return success(customerService.createCustomer(createReqVO)); | ||||
|     } | ||||
|  | ||||
|     @PutMapping("/update") | ||||
|     @Operation(summary = "更新客户") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:update')") | ||||
|     public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { | ||||
|         customerService.updateCustomer(updateReqVO); | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @DeleteMapping("/delete") | ||||
|     @Operation(summary = "删除客户") | ||||
|     @Parameter(name = "id", description = "编号", required = true) | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:delete')") | ||||
|     public CommonResult<Boolean> deleteCustomer(@RequestParam("id") Long id) { | ||||
|         customerService.deleteCustomer(id); | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get") | ||||
|     @Operation(summary = "获得客户") | ||||
|     @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:query')") | ||||
|     public CommonResult<CrmCustomerRespVO> getCustomer(@RequestParam("id") Long id) { | ||||
|         CrmCustomerDO customer = customerService.getCustomer(id); | ||||
|         return success(CrmCustomerConvert.INSTANCE.convert(customer)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/page") | ||||
|     @Operation(summary = "获得客户分页") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:query')") | ||||
|     public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { | ||||
|         PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO); | ||||
|         return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult)); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/export-excel") | ||||
|     @Operation(summary = "导出客户 Excel") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:export')") | ||||
|     @OperateLog(type = EXPORT) | ||||
|     public void exportCustomerExcel(@Valid CrmCustomerExportReqVO exportReqVO, | ||||
|                                     HttpServletResponse response) throws IOException { | ||||
|         List<CrmCustomerDO> list = customerService.getCustomerList(exportReqVO); | ||||
|         // 导出 Excel | ||||
|         List<CrmCustomerExcelVO> datas = CrmCustomerConvert.INSTANCE.convertList02(list); | ||||
|         ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerExcelVO.class, datas); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,72 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.validation.Mobile; | ||||
| import cn.iocoder.yudao.framework.common.validation.Telephone; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import org.springframework.format.annotation.DateTimeFormat; | ||||
|  | ||||
| import javax.validation.constraints.NotEmpty; | ||||
| import javax.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 文档生成 | ||||
|  */ | ||||
| @Data | ||||
| public class CrmCustomerBaseVO { | ||||
|  | ||||
|     @Schema(description = "客户名称", example = "赵六") | ||||
|     @NotEmpty(message = "客户名称不能为空") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||||
|     @NotNull(message = "跟进状态不能为空") | ||||
|     private Boolean followUpStatus; | ||||
|  | ||||
|     @Schema(description = "锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||||
|     @NotNull(message = "锁定状态不能为空") | ||||
|     private Boolean lockStatus; | ||||
|  | ||||
|     @Schema(description = "手机", example = "18000000000") | ||||
|     @Mobile | ||||
|     private String mobile; | ||||
|  | ||||
|     @Schema(description = "电话", example = "18000000000") | ||||
|     @Telephone | ||||
|     private String telephone; | ||||
|  | ||||
|     @Schema(description = "网址", example = "https://www.baidu.com") | ||||
|     private String website; | ||||
|  | ||||
|     @Schema(description = "备注", example = "随便") | ||||
|     private String remark; | ||||
|  | ||||
|     @Schema(description = "负责人的用户编号", example = "25682") | ||||
|     @NotNull(message = "负责人不能为空") | ||||
|     private Long ownerUserId; | ||||
|  | ||||
|     @Schema(description = "地区编号", example = "20158") | ||||
|     private Long areaId; | ||||
|  | ||||
|     @Schema(description = "详细地址", example = "北京市海淀区") | ||||
|     private String detailAddress; | ||||
|  | ||||
|     @Schema(description = "地理位置经度", example = "116.40341") | ||||
|     private String longitude; | ||||
|  | ||||
|     @Schema(description = "地理位置维度", example = "39.92409") | ||||
|     private String latitude; | ||||
|  | ||||
|     @Schema(description = "最后跟进时间") | ||||
|     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||||
|     private LocalDateTime contactLastTime; | ||||
|  | ||||
|     @Schema(description = "下次联系时间") | ||||
|     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||||
|     private LocalDateTime contactNextTime; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,20 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| @Schema(description = "管理后台 - 客户创建 Request VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class CrmCustomerCreateReqVO extends CrmCustomerBaseVO { | ||||
|  | ||||
|     @Schema(description = "只读权限的用户编号数组") | ||||
|     private String roUserIds; | ||||
|  | ||||
|     @Schema(description = "读写权限的用户编号数组") | ||||
|     private String rwUserIds; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,74 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | ||||
| import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | ||||
| import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; | ||||
| import com.alibaba.excel.annotation.ExcelProperty; | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 客户 Excel VO | ||||
|  * | ||||
|  * @author Wanwan | ||||
|  */ | ||||
| @Data | ||||
| public class CrmCustomerExcelVO { | ||||
|  | ||||
|     @ExcelProperty("编号") | ||||
|     private Long id; | ||||
|  | ||||
|     @ExcelProperty("客户名称") | ||||
|     private String name; | ||||
|  | ||||
|     @ExcelProperty(value = "跟进状态", converter = DictConvert.class) | ||||
|     @DictFormat(DictTypeConstants.BOOLEAN_STRING) | ||||
|     private Boolean followUpStatus; | ||||
|  | ||||
|     @ExcelProperty(value = "锁定状态", converter = DictConvert.class) | ||||
|     @DictFormat(DictTypeConstants.BOOLEAN_STRING) | ||||
|     private Boolean lockStatus; | ||||
|  | ||||
|     @ExcelProperty(value = "成交状态", converter = DictConvert.class) | ||||
|     @DictFormat(DictTypeConstants.BOOLEAN_STRING) | ||||
|     private Boolean dealStatus; | ||||
|  | ||||
|     @ExcelProperty("手机") | ||||
|     private String mobile; | ||||
|  | ||||
|     @ExcelProperty("电话") | ||||
|     private String telephone; | ||||
|  | ||||
|     @ExcelProperty("网址") | ||||
|     private String website; | ||||
|  | ||||
|     @ExcelProperty("备注") | ||||
|     private String remark; | ||||
|  | ||||
|     @ExcelProperty("负责人的用户编号") | ||||
|     private Long ownerUserId; | ||||
|  | ||||
|     @ExcelProperty("地区编号") | ||||
|     private Long areaId; | ||||
|  | ||||
|     @ExcelProperty("详细地址") | ||||
|     private String detailAddress; | ||||
|  | ||||
|     @ExcelProperty("地理位置经度") | ||||
|     private String longitude; | ||||
|  | ||||
|     @ExcelProperty("地理位置维度") | ||||
|     private String latitude; | ||||
|  | ||||
|     @ExcelProperty("最后跟进时间") | ||||
|     private LocalDateTime contactLastTime; | ||||
|  | ||||
|     @ExcelProperty("下次联系时间") | ||||
|     private LocalDateTime contactNextTime; | ||||
|  | ||||
|     @ExcelProperty("创建时间") | ||||
|     private LocalDateTime createTime; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,22 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| @Schema(description = "管理后台 - 客户 Excel 导出 Request VO,参数和 CrmCustomerPageReqVO 是一致的") | ||||
| @Data | ||||
| public class CrmCustomerExportReqVO { | ||||
|  | ||||
|     @Schema(description = "客户名称", example = "赵六") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "手机", example = "18000000000") | ||||
|     private String mobile; | ||||
|  | ||||
|     @Schema(description = "电话", example = "18000000000") | ||||
|     private String telephone; | ||||
|  | ||||
|     @Schema(description = "网址", example = "https://www.baidu.com") | ||||
|     private String website; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,27 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| @Schema(description = "管理后台 - 客户分页 Request VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class CrmCustomerPageReqVO extends PageParam { | ||||
|  | ||||
|     @Schema(description = "客户名称", example = "赵六") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "手机", example = "18000000000") | ||||
|     private String mobile; | ||||
|  | ||||
|     @Schema(description = "电话", example = "18000000000") | ||||
|     private String telephone; | ||||
|  | ||||
|     @Schema(description = "网址", example = "https://www.baidu.com") | ||||
|     private String website; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,25 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| @Schema(description = "管理后台 - 客户 Response VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class CrmCustomerRespVO extends CrmCustomerBaseVO { | ||||
|  | ||||
|     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | ||||
|     private Long id; | ||||
|  | ||||
|     @Schema(description = "成交状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||||
|     private Boolean dealStatus; | ||||
|  | ||||
|     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     private LocalDateTime createTime; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| import javax.validation.constraints.NotNull; | ||||
|  | ||||
| @Schema(description = "管理后台 - 客户更新 Request VO") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| public class CrmCustomerUpdateReqVO extends CrmCustomerBaseVO { | ||||
|  | ||||
|     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | ||||
|     @NotNull(message = "编号不能为空") | ||||
|     private Long id; | ||||
|  | ||||
|     @Schema(description = "只读权限的用户编号数组") | ||||
|     private String roUserIds; | ||||
|  | ||||
|     @Schema(description = "读写权限的用户编号数组") | ||||
|     private String rwUserIds; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,34 @@ | ||||
| package cn.iocoder.yudao.module.crm.convert.customer; | ||||
|  | ||||
| import java.util.*; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
|  | ||||
| import org.mapstruct.Mapper; | ||||
| import org.mapstruct.factory.Mappers; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
|  | ||||
| /** | ||||
|  * 客户 Convert | ||||
|  * | ||||
|  * @author Wanwan | ||||
|  */ | ||||
| @Mapper | ||||
| public interface CrmCustomerConvert { | ||||
|  | ||||
|     CrmCustomerConvert INSTANCE = Mappers.getMapper(CrmCustomerConvert.class); | ||||
|  | ||||
|     CrmCustomerDO convert(CrmCustomerCreateReqVO bean); | ||||
|  | ||||
|     CrmCustomerDO convert(CrmCustomerUpdateReqVO bean); | ||||
|  | ||||
|     CrmCustomerRespVO convert(CrmCustomerDO bean); | ||||
|  | ||||
|     List<CrmCustomerRespVO> convertList(List<CrmCustomerDO> list); | ||||
|  | ||||
|     PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> page); | ||||
|  | ||||
|     List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list); | ||||
|  | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package cn.iocoder.yudao.module.crm.dal.dataobject.clue; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| import com.baomidou.mybatisplus.annotation.KeySequence; | ||||
| import com.baomidou.mybatisplus.annotation.TableId; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| @@ -43,8 +44,7 @@ public class CrmClueDO extends BaseDO { | ||||
|     private String name; | ||||
|     /** | ||||
|      * 客户 id | ||||
|      * | ||||
|      * // TODO @wanwan:要写下关联的实体,以及对应的属性哈 | ||||
|      * 对应 {@link CrmCustomerDO#getId()} | ||||
|      */ | ||||
|     private Long customerId; | ||||
|     /** | ||||
|   | ||||
| @@ -0,0 +1,107 @@ | ||||
| package cn.iocoder.yudao.module.crm.dal.dataobject.customer; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||||
| import com.baomidou.mybatisplus.annotation.KeySequence; | ||||
| import com.baomidou.mybatisplus.annotation.TableId; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import com.sun.xml.bind.v2.TODO; | ||||
| import lombok.*; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| /** | ||||
|  * 客户 DO | ||||
|  * | ||||
|  * @author Wanwan | ||||
|  */ | ||||
| @TableName("crm_customer") | ||||
| @KeySequence("crm_customer_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @ToString(callSuper = true) | ||||
| @Builder | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class CrmCustomerDO extends BaseDO { | ||||
|  | ||||
|     /** | ||||
|      * 编号 | ||||
|      */ | ||||
|     @TableId | ||||
|     private Long id; | ||||
|     /** | ||||
|      * 客户名称 | ||||
|      */ | ||||
|     private String name; | ||||
|     /** | ||||
|      * 跟进状态 | ||||
|      * <p> | ||||
|      * 枚举 {@link TODO infra_boolean_string 对应的类} | ||||
|      */ | ||||
|     private Boolean followUpStatus; | ||||
|     /** | ||||
|      * 锁定状态 | ||||
|      * <p> | ||||
|      * 枚举 {@link TODO infra_boolean_string 对应的类} | ||||
|      */ | ||||
|     private Boolean lockStatus; | ||||
|     /** | ||||
|      * 成交状态 | ||||
|      * <p> | ||||
|      * 枚举 {@link TODO infra_boolean_string 对应的类} | ||||
|      */ | ||||
|     private Boolean dealStatus; | ||||
|     /** | ||||
|      * 手机 | ||||
|      */ | ||||
|     private String mobile; | ||||
|     /** | ||||
|      * 电话 | ||||
|      */ | ||||
|     private String telephone; | ||||
|     /** | ||||
|      * 网址 | ||||
|      */ | ||||
|     private String website; | ||||
|     /** | ||||
|      * 备注 | ||||
|      */ | ||||
|     private String remark; | ||||
|     /** | ||||
|      * 负责人的用户编号 | ||||
|      */ | ||||
|     private Long ownerUserId; | ||||
|     /** | ||||
|      * 只读权限的用户编号数组 | ||||
|      */ | ||||
|     private String roUserIds; | ||||
|     /** | ||||
|      * 读写权限的用户编号数组 | ||||
|      */ | ||||
|     private String rwUserIds; | ||||
|     /** | ||||
|      * 地区编号 | ||||
|      */ | ||||
|     private Long areaId; | ||||
|     /** | ||||
|      * 详细地址 | ||||
|      */ | ||||
|     private String detailAddress; | ||||
|     /** | ||||
|      * 地理位置经度 | ||||
|      */ | ||||
|     private String longitude; | ||||
|     /** | ||||
|      * 地理位置维度 | ||||
|      */ | ||||
|     private String latitude; | ||||
|     /** | ||||
|      * 最后跟进时间 | ||||
|      */ | ||||
|     private LocalDateTime contactLastTime; | ||||
|     /** | ||||
|      * 下次联系时间 | ||||
|      */ | ||||
|     private LocalDateTime contactNextTime; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,39 @@ | ||||
| package cn.iocoder.yudao.module.crm.dal.mysql.customer; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 客户 Mapper | ||||
|  * | ||||
|  * @author Wanwan | ||||
|  */ | ||||
| @Mapper | ||||
| public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||||
|  | ||||
|     default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO reqVO) { | ||||
|         return selectPage(reqVO, new LambdaQueryWrapperX<CrmCustomerDO>() | ||||
|                 .likeIfPresent(CrmCustomerDO::getName, reqVO.getName()) | ||||
|                 .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile()) | ||||
|                 .eqIfPresent(CrmCustomerDO::getTelephone, reqVO.getTelephone()) | ||||
|                 .likeIfPresent(CrmCustomerDO::getWebsite, reqVO.getWebsite()) | ||||
|                 .orderByDesc(CrmCustomerDO::getId)); | ||||
|     } | ||||
|  | ||||
|     default List<CrmCustomerDO> selectList(CrmCustomerExportReqVO reqVO) { | ||||
|         return selectList(new LambdaQueryWrapperX<CrmCustomerDO>() | ||||
|                 .likeIfPresent(CrmCustomerDO::getName, reqVO.getName()) | ||||
|                 .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile()) | ||||
|                 .eqIfPresent(CrmCustomerDO::getTelephone, reqVO.getTelephone()) | ||||
|                 .likeIfPresent(CrmCustomerDO::getWebsite, reqVO.getWebsite()) | ||||
|                 .orderByDesc(CrmCustomerDO::getId)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; | ||||
| import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; | ||||
| import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
|  | ||||
| @@ -19,6 +20,7 @@ import java.util.List; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS; | ||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; | ||||
|  | ||||
| /** | ||||
|  * 线索 Service 实现类 | ||||
| @@ -31,10 +33,13 @@ public class CrmClueServiceImpl implements CrmClueService { | ||||
|  | ||||
|     @Resource | ||||
|     private CrmClueMapper clueMapper; | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|  | ||||
|     @Override | ||||
|     public Long createClue(CrmClueCreateReqVO createReqVO) { | ||||
|         // TODO @wanwan:校验客户是否存在;以及类似的逻辑哈;如果目前还缺对应的模块的 service,可以先给自己写 todo; | ||||
|         // 校验客户是否存在 | ||||
|         validateCustomerExists(createReqVO.getCustomerId()); | ||||
|         // 插入 | ||||
|         CrmClueDO clue = CrmClueConvert.INSTANCE.convert(createReqVO); | ||||
|         clueMapper.insert(clue); | ||||
| @@ -44,9 +49,10 @@ public class CrmClueServiceImpl implements CrmClueService { | ||||
|  | ||||
|     @Override | ||||
|     public void updateClue(CrmClueUpdateReqVO updateReqVO) { | ||||
|         // TODO @wanwan:校验客户是否存在;以及类似的逻辑哈;如果目前还缺对应的模块的 service,可以先给自己写 todo; | ||||
|         // 校验存在 | ||||
|         validateClueExists(updateReqVO.getId()); | ||||
|         // 校验客户是否存在 | ||||
|         validateCustomerExists(updateReqVO.getCustomerId()); | ||||
|  | ||||
|         // 更新 | ||||
|         CrmClueDO updateObj = CrmClueConvert.INSTANCE.convert(updateReqVO); | ||||
| @@ -90,4 +96,15 @@ public class CrmClueServiceImpl implements CrmClueService { | ||||
|         return clueMapper.selectList(exportReqVO); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验客户是否存在 | ||||
|      * | ||||
|      * @param customerId 客户id | ||||
|      */ | ||||
|     private void validateCustomerExists(Long customerId) { | ||||
|         if (customerService.getCustomer(customerId) == null) { | ||||
|             throw exception(CUSTOMER_NOT_EXISTS); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,75 @@ | ||||
| package cn.iocoder.yudao.module.crm.service.customer; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
|  | ||||
| import javax.validation.Valid; | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 客户 Service 接口 | ||||
|  * | ||||
|  * @author Wanwan | ||||
|  */ | ||||
| public interface CrmCustomerService { | ||||
|  | ||||
|     /** | ||||
|      * 创建客户 | ||||
|      * | ||||
|      * @param createReqVO 创建信息 | ||||
|      * @return 编号 | ||||
|      */ | ||||
|     Long createCustomer(@Valid CrmCustomerCreateReqVO createReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 更新客户 | ||||
|      * | ||||
|      * @param updateReqVO 更新信息 | ||||
|      */ | ||||
|     void updateCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 删除客户 | ||||
|      * | ||||
|      * @param id 编号 | ||||
|      */ | ||||
|     void deleteCustomer(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 获得客户 | ||||
|      * | ||||
|      * @param id 编号 | ||||
|      * @return 客户 | ||||
|      */ | ||||
|     CrmCustomerDO getCustomer(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 获得客户列表 | ||||
|      * | ||||
|      * @param ids 编号 | ||||
|      * @return 客户列表 | ||||
|      */ | ||||
|     List<CrmCustomerDO> getCustomerList(Collection<Long> ids); | ||||
|  | ||||
|     /** | ||||
|      * 获得客户分页 | ||||
|      * | ||||
|      * @param pageReqVO 分页查询 | ||||
|      * @return 客户分页 | ||||
|      */ | ||||
|     PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 获得客户列表, 用于 Excel 导出 | ||||
|      * | ||||
|      * @param exportReqVO 查询条件 | ||||
|      * @return 客户列表 | ||||
|      */ | ||||
|     List<CrmCustomerDO> getCustomerList(CrmCustomerExportReqVO exportReqVO); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,88 @@ | ||||
| package cn.iocoder.yudao.module.crm.service.customer; | ||||
|  | ||||
| import org.springframework.stereotype.Service; | ||||
| import javax.annotation.Resource; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
|  | ||||
| import java.util.*; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
|  | ||||
| import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; | ||||
| import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | ||||
|  | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.collection.ListUtil; | ||||
|  | ||||
| /** | ||||
|  * 客户 Service 实现类 | ||||
|  * | ||||
|  * @author Wanwan | ||||
|  */ | ||||
| @Service | ||||
| @Validated | ||||
| public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|  | ||||
|     @Resource | ||||
|     private CrmCustomerMapper customerMapper; | ||||
|  | ||||
|     @Override | ||||
|     public Long createCustomer(CrmCustomerCreateReqVO createReqVO) { | ||||
|         // 插入 | ||||
|         CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); | ||||
|         customerMapper.insert(customer); | ||||
|         // 返回 | ||||
|         return customer.getId(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { | ||||
|         // 校验存在 | ||||
|         validateCustomerExists(updateReqVO.getId()); | ||||
|         // 更新 | ||||
|         CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); | ||||
|         customerMapper.updateById(updateObj); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void deleteCustomer(Long id) { | ||||
|         // 校验存在 | ||||
|         validateCustomerExists(id); | ||||
|         // 删除 | ||||
|         customerMapper.deleteById(id); | ||||
|     } | ||||
|  | ||||
|     private void validateCustomerExists(Long id) { | ||||
|         if (customerMapper.selectById(id) == null) { | ||||
|             throw exception(CUSTOMER_NOT_EXISTS); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public CrmCustomerDO getCustomer(Long id) { | ||||
|         return customerMapper.selectById(id); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) { | ||||
|         if (CollUtil.isEmpty(ids)) { | ||||
|             return ListUtil.empty(); | ||||
|         } | ||||
|         return customerMapper.selectBatchIds(ids); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO) { | ||||
|         return customerMapper.selectPage(pageReqVO); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmCustomerDO> getCustomerList(CrmCustomerExportReqVO exportReqVO) { | ||||
|         return customerMapper.selectList(exportReqVO); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||||
| <mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper"> | ||||
|  | ||||
|     <!-- | ||||
|         一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 | ||||
|         无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。 | ||||
|         代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。 | ||||
|         文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ | ||||
|      --> | ||||
|  | ||||
| </mapper> | ||||
| @@ -0,0 +1,170 @@ | ||||
| package cn.iocoder.yudao.module.crm.service.customer; | ||||
|  | ||||
| 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.customer.vo.CrmCustomerCreateReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; | ||||
| import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||||
| import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; | ||||
| import org.junit.jupiter.api.Disabled; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.springframework.context.annotation.Import; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.util.List; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||||
| import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; | ||||
| import static org.junit.jupiter.api.Assertions.*; | ||||
|  | ||||
| /** | ||||
|  * {@link CrmCustomerServiceImpl} 的单元测试类 | ||||
|  * | ||||
|  * @author Wanwan | ||||
|  */ | ||||
| @Import(CrmCustomerServiceImpl.class) | ||||
| public class CrmCustomerServiceImplTest extends BaseDbUnitTest { | ||||
|  | ||||
|     @Resource | ||||
|     private CrmCustomerServiceImpl customerService; | ||||
|  | ||||
|     @Resource | ||||
|     private CrmCustomerMapper customerMapper; | ||||
|  | ||||
|     @Test | ||||
|     public void testCreateCustomer_success() { | ||||
|         // 准备参数 | ||||
|         CrmCustomerCreateReqVO reqVO = randomPojo(CrmCustomerCreateReqVO.class); | ||||
|  | ||||
|         // 调用 | ||||
|         Long customerId = customerService.createCustomer(reqVO); | ||||
|         // 断言 | ||||
|         assertNotNull(customerId); | ||||
|         // 校验记录的属性是否正确 | ||||
|         CrmCustomerDO customer = customerMapper.selectById(customerId); | ||||
|         assertPojoEquals(reqVO, customer); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testUpdateCustomer_success() { | ||||
|         // mock 数据 | ||||
|         CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class); | ||||
|         customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 | ||||
|         // 准备参数 | ||||
|         CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class, o -> { | ||||
|             o.setId(dbCustomer.getId()); // 设置更新的 ID | ||||
|         }); | ||||
|  | ||||
|         // 调用 | ||||
|         customerService.updateCustomer(reqVO); | ||||
|         // 校验是否更新正确 | ||||
|         CrmCustomerDO customer = customerMapper.selectById(reqVO.getId()); // 获取最新的 | ||||
|         assertPojoEquals(reqVO, customer); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testUpdateCustomer_notExists() { | ||||
|         // 准备参数 | ||||
|         CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> customerService.updateCustomer(reqVO), CUSTOMER_NOT_EXISTS); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testDeleteCustomer_success() { | ||||
|         // mock 数据 | ||||
|         CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class); | ||||
|         customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 | ||||
|         // 准备参数 | ||||
|         Long id = dbCustomer.getId(); | ||||
|  | ||||
|         // 调用 | ||||
|         customerService.deleteCustomer(id); | ||||
|         // 校验数据不存在了 | ||||
|         assertNull(customerMapper.selectById(id)); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testDeleteCustomer_notExists() { | ||||
|         // 准备参数 | ||||
|         Long id = randomLongId(); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> customerService.deleteCustomer(id), CUSTOMER_NOT_EXISTS); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | ||||
|     public void testGetCustomerPage() { | ||||
|         // mock 数据 | ||||
|         CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到 | ||||
|             o.setName(null); | ||||
|             o.setMobile(null); | ||||
|             o.setTelephone(null); | ||||
|             o.setWebsite(null); | ||||
|         }); | ||||
|         customerMapper.insert(dbCustomer); | ||||
|         // 测试 name 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null))); | ||||
|         // 测试 mobile 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); | ||||
|         // 测试 telephone 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); | ||||
|         // 测试 website 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null))); | ||||
|         // 准备参数 | ||||
|         CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO(); | ||||
|         reqVO.setName(null); | ||||
|         reqVO.setMobile(null); | ||||
|         reqVO.setTelephone(null); | ||||
|         reqVO.setWebsite(null); | ||||
|  | ||||
|         // 调用 | ||||
|         PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(reqVO); | ||||
|         // 断言 | ||||
|         assertEquals(1, pageResult.getTotal()); | ||||
|         assertEquals(1, pageResult.getList().size()); | ||||
|         assertPojoEquals(dbCustomer, pageResult.getList().get(0)); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | ||||
|     public void testGetCustomerList() { | ||||
|         // mock 数据 | ||||
|         CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到 | ||||
|             o.setName(null); | ||||
|             o.setMobile(null); | ||||
|             o.setTelephone(null); | ||||
|             o.setWebsite(null); | ||||
|         }); | ||||
|         customerMapper.insert(dbCustomer); | ||||
|         // 测试 name 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null))); | ||||
|         // 测试 mobile 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); | ||||
|         // 测试 telephone 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); | ||||
|         // 测试 website 不匹配 | ||||
|         customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null))); | ||||
|         // 准备参数 | ||||
|         CrmCustomerExportReqVO reqVO = new CrmCustomerExportReqVO(); | ||||
|         reqVO.setName(null); | ||||
|         reqVO.setMobile(null); | ||||
|         reqVO.setTelephone(null); | ||||
|         reqVO.setWebsite(null); | ||||
|  | ||||
|         // 调用 | ||||
|         List<CrmCustomerDO> list = customerService.getCustomerList(reqVO); | ||||
|         // 断言 | ||||
|         assertEquals(1, list.size()); | ||||
|         assertPojoEquals(dbCustomer, list.get(0)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -5,3 +5,5 @@ DELETE FROM "crm_clue"; | ||||
| DELETE FROM "crm_receivable"; | ||||
|  | ||||
| DELETE FROM "crm_receivable_plan"; | ||||
|  | ||||
| DELETE FROM "crm_customer"; | ||||
| @@ -98,3 +98,30 @@ CREATE TABLE IF NOT EXISTS "crm_receivable_plan" ( | ||||
|      PRIMARY KEY ("id") | ||||
| ) COMMENT '回款计划'; | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS "crm_customer" ( | ||||
|   "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | ||||
|   "name" varchar, | ||||
|   "follow_up_status" bit NOT NULL, | ||||
|   "lock_status" bit NOT NULL, | ||||
|   "deal_status" bit NOT NULL, | ||||
|   "mobile" varchar, | ||||
|   "telephone" varchar, | ||||
|   "website" varchar, | ||||
|   "remark" varchar, | ||||
|   "owner_user_id" bigint, | ||||
|   "ro_user_ids" varchar, | ||||
|   "rw_user_ids" varchar, | ||||
|   "area_id" bigint, | ||||
|   "detail_address" varchar, | ||||
|   "longitude" varchar, | ||||
|   "latitude" varchar, | ||||
|   "contact_last_time" varchar, | ||||
|   "contact_next_time" varchar, | ||||
|   "creator" varchar DEFAULT '', | ||||
|   "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
|   "updater" varchar DEFAULT '', | ||||
|   "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   "deleted" bit NOT NULL DEFAULT FALSE, | ||||
|   "tenant_id" bigint NOT NULL, | ||||
|   PRIMARY KEY ("id") | ||||
| ) COMMENT '客户表'; | ||||
		Reference in New Issue
	
	Block a user
	 芋道源码
					芋道源码