diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/enums/ExcelColumn.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/enums/ExcelColumn.java index 4330b820b9..dd8a8374c1 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/enums/ExcelColumn.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/enums/ExcelColumn.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.excel.core.enums; import lombok.AllArgsConstructor; import lombok.Getter; +// TODO @puhui999:列表有办法通过 field name 么?主要考虑一个点,可能导入模版的顺序可能会变 /** * Excel 列名枚举 * 默认枚举 26 列列名如果有需求更多的列名请自行补充 @@ -12,6 +13,7 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum ExcelColumn { + A(0), B(1), C(2), D(3), E(4), F(5), G(6), H(7), I(8), J(9), K(10), L(11), M(12), N(13), O(14), P(15), Q(16), R(17), S(18), T(19), U(20), V(21), W(22), X(23), Y(24), diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java index 6b6e703204..38d01bd879 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java @@ -23,9 +23,20 @@ import java.util.stream.Collectors; */ public class SelectSheetWriteHandler implements SheetWriteHandler { + /** + * 数据起始行从 0 开始 + * + * 约定:本项目第一行有标题所以从 1 开始如果您的 Excel 有多行标题请自行更改 + */ + public static final int FIRST_ROW = 1; + /** + * 下拉列需要创建下拉框的行数,默认两千行如需更多请自行调整 + */ + public static final int LAST_ROW = 2000; + private static final String DICT_SHEET_NAME = "字典sheet"; - public static final int FIRST_ROW = 1; // 数据起始行从 0 开始,本项目第一行有标题所以从 1 开始如果您的 Excel 有多行标题请自行更改 - public static final int LAST_ROW = 2000; // 下拉列需要创建下拉框的行数,默认两千行如需更多请自行调整 + + // TODO @puhui999:Map> 可以么?之前用 keyvalue 的原因,返回给前端,无法用 linkedhashmap,默认 key 会乱序 private final List>> selectMap; public SelectSheetWriteHandler(List>> selectMap) { @@ -48,32 +59,32 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { return; } - // 1.1 获取相应操作对象 + // 1. 获取相应操作对象 DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper(); // 需要设置下拉框的 sheet 页的数据验证助手 Workbook workbook = writeWorkbookHolder.getWorkbook(); // 获得工作簿 - // 1.2 创建数据字典的 sheet 页 + // 2. 创建数据字典的 sheet 页 Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME); for (KeyValue> keyValue : selectMap) { - int rowLen = keyValue.getValue().size(); - // 设置字典 sheet 页的值 每一列一个字典项 - for (int i = 0; i < rowLen; i++) { + int rowLength = keyValue.getValue().size(); + // 2.1 设置字典 sheet 页的值 每一列一个字典项 + for (int i = 0; i < rowLength; i++) { Row row = dictSheet.getRow(i); if (row == null) { row = dictSheet.createRow(i); } row.createCell(keyValue.getKey().getColNum()).setCellValue(keyValue.getValue().get(i)); } - // 1.3 设置单元格下拉选择 - setColSelect(writeSheetHolder, workbook, helper, keyValue); + // 2.2 设置单元格下拉选择 + setColumnSelect(writeSheetHolder, workbook, helper, keyValue); } } /** * 设置单元格下拉选择 */ - private static void setColSelect(WriteSheetHolder writeSheetHolder, Workbook workbook, DataValidationHelper helper, - KeyValue> keyValue) { + private static void setColumnSelect(WriteSheetHolder writeSheetHolder, Workbook workbook, DataValidationHelper helper, + KeyValue> keyValue) { // 1.1 创建可被其他单元格引用的名称 Name name = workbook.createName(); String excelColumn = keyValue.getKey().name(); @@ -81,6 +92,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { String refers = DICT_SHEET_NAME + "!$" + excelColumn + "$1:$" + excelColumn + "$" + keyValue.getValue().size(); name.setNameName("dict" + keyValue.getKey()); // 设置名称的名字 name.setRefersToFormula(refers); // 设置公式 + // 2.1 设置约束 DataValidationConstraint constraint = helper.createFormulaListConstraint("dict" + keyValue.getKey()); // 设置引用约束 // 设置下拉单元格的首行、末行、首列、末列 diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index 65bdc1b892..c2c835b7f1 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -96,6 +96,12 @@ public interface LogRecordConstants { String CRM_BUSINESS_UPDATE_STATUS_SUB_TYPE = "更新商机状态"; String CRM_BUSINESS_UPDATE_STATUS_SUCCESS = "更新了商机【{{#businessName}}】的状态从【{{#oldStatusName}}】变更为了【{{#newStatusName}}】"; + // ======================= CRM_CONTRACT_CONFIG 合同配置 ======================= + + String CRM_CONTRACT_CONFIG_TYPE = "CRM 合同配置"; + String CRM_CONTRACT_CONFIG_SUB_TYPE = "{{#isPoolConfigUpdate ? '更新合同配置' : '创建合同配置'}}"; + String CRM_CONTRACT_CONFIG_SUCCESS = "{{#isPoolConfigUpdate ? '更新了合同配置' : '创建了合同配置'}}"; + // ======================= CRM_CONTRACT 合同 ======================= String CRM_CONTRACT_TYPE = "CRM 合同"; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http deleted file mode 100644 index b9e9a4edf8..0000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http +++ /dev/null @@ -1,9 +0,0 @@ -### 合同金额排行榜 -GET {{baseUrl}}/crm/bi-rank/get-contract-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -### 回款金额排行榜 -GET {{baseUrl}}/crm/bi-rank/get-receivable-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index ec1b35db45..505c0ec46f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -126,15 +126,6 @@ public class CrmBusinessController { return businessVO; } - // TODO 芋艿:处理下 - @GetMapping("/list-by-ids") - @Operation(summary = "获得商机列表") - @Parameter(name = "ids", description = "编号", required = true, example = "[1024]") - @PreAuthorize("@ss.hasPermission('crm:business:query')") - public CommonResult> getContactListByIds(@RequestParam("ids") List ids) { - return success(BeanUtils.toBean(businessService.getBusinessList(ids, getLoginUserId()), CrmBusinessRespVO.class)); - } - @GetMapping("/simple-all-list") @Operation(summary = "获得联系人的精简列表") @PreAuthorize("@ss.hasPermission('crm:contact:query')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index 6c27fbb01e..5c7413159d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -105,15 +105,6 @@ public class CrmContactController { return buildContactDetailList(singletonList(contact)).get(0); } - @GetMapping("/list-by-ids") - @Operation(summary = "获得联系人列表") - @Parameter(name = "ids", description = "编号", required = true, example = "[1024]") - @PreAuthorize("@ss.hasPermission('crm:contact:query')") - public CommonResult> getContactListByIds(@RequestParam("ids") List ids) { - List list = contactService.getContactListByIds(ids, getLoginUserId()); - return success(BeanUtils.toBean(list, CrmContactRespVO.class)); - } - @GetMapping("/simple-all-list") @Operation(summary = "获得联系人的精简列表") @PreAuthorize("@ss.hasPermission('crm:contact:query')") @@ -208,6 +199,15 @@ public class CrmContactController { return success(true); } + + @PostMapping("/create-business-list2") + @Operation(summary = "创建联系人与商机的关联") + @PreAuthorize("@ss.hasPermission('crm:contact:create-business')") + public CommonResult createContactBusinessList2(@Valid @RequestBody CrmContactBusiness2ReqVO createReqVO) { + contactBusinessLinkService.createContactBusinessList2(createReqVO); + return success(true); + } + @DeleteMapping("/delete-business-list") @Operation(summary = "删除联系人与联系人的关联") @PreAuthorize("@ss.hasPermission('crm:contact:delete-business')") @@ -216,4 +216,12 @@ public class CrmContactController { return success(true); } + @DeleteMapping("/delete-business-list2") + @Operation(summary = "删除联系人与联系人的关联") + @PreAuthorize("@ss.hasPermission('crm:contact:delete-business')") + public CommonResult deleteContactBusinessList(@Valid @RequestBody CrmContactBusiness2ReqVO deleteReqVO) { + contactBusinessLinkService.deleteContactBusinessList2(deleteReqVO); + return success(true); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusiness2ReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusiness2ReqVO.java new file mode 100644 index 0000000000..5fac57cffe --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusiness2ReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - CRM 联系人商机 Request VO") // 【商机关联联系人】用于关联,取消关联的操作 +@Data +public class CrmContactBusiness2ReqVO { + + @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7638") + @NotNull(message="商机不能为空") + private Long businessId; + + @Schema(description = "联系人编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "20878") + @NotEmpty(message="联系人数组不能为空") + private List contactIds; + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java index 9b360f84b2..7218494b4c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java @@ -7,7 +7,7 @@ import lombok.Data; import java.util.List; -@Schema(description = "管理后台 - CRM 联系人商机 Request VO") // 用于关联,取消关联的操作 +@Schema(description = "管理后台 - CRM 联系人商机 Request VO") // 【联系人关联商机】用于关联,取消关联的操作 @Data public class CrmContactBusinessReqVO { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractConfigController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractConfigController.java new file mode 100644 index 0000000000..a97c3bfd62 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractConfigController.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config.CrmContractConfigRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config.CrmContractConfigSaveReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO; +import cn.iocoder.yudao.module.crm.service.contract.CrmContractConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - CRM 合同配置") +@RestController +@RequestMapping("/crm/contract-config") +@Validated +public class CrmContractConfigController { + + @Resource + private CrmContractConfigService contractConfigService; + + @GetMapping("/get") + @Operation(summary = "获取合同配置") + @PreAuthorize("@ss.hasPermission('crm:contract-config:query')") + public CommonResult getCustomerPoolConfig() { + CrmContractConfigDO config = contractConfigService.getContractConfig(); + return success(BeanUtils.toBean(config, CrmContractConfigRespVO.class)); + } + + @PutMapping("/save") + @Operation(summary = "更新合同配置") + @PreAuthorize("@ss.hasPermission('crm:contract-config:update')") + public CommonResult saveCustomerPoolConfig(@Valid @RequestBody CrmContractConfigSaveReqVO updateReqVO) { + contractConfigService.saveContractConfig(updateReqVO); + return success(true); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 6e818908b8..f04c62c681 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -9,10 +9,10 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractSaveReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; @@ -138,6 +138,14 @@ public class CrmContractController { return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetailList(pageResult.getList()))); } + @GetMapping("/page-by-business") + @Operation(summary = "获得合同分页,基于指定商机") + public CommonResult> getContractPageByBusiness(@Valid CrmContractPageReqVO pageVO) { + Assert.notNull(pageVO.getBusinessId(), "商机编号不能为空"); + PageResult pageResult = contractService.getContractPageByBusinessId(pageVO); + return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetailList(pageResult.getList()))); + } + @GetMapping("/export-excel") @Operation(summary = "导出合同 Excel") @PreAuthorize("@ss.hasPermission('crm:contract:export')") @@ -187,8 +195,8 @@ public class CrmContractController { Map contactMap = convertMap(contactService.getContactList(convertSet(contractList, CrmContractDO::getSignContactId)), CrmContactDO::getId); // 1.4 获取商机 - Map businessMap = convertMap(businessService.getBusinessList(convertSet(contractList, - CrmContractDO::getBusinessId)), CrmBusinessDO::getId); + Map businessMap = businessService.getBusinessMap( + convertSet(contractList, CrmContractDO::getBusinessId)); // 2. 拼接数据 return BeanUtils.toBean(contractList, CrmContractRespVO.class, contractVO -> { // 2.1 设置客户信息 @@ -207,18 +215,18 @@ public class CrmContractController { }); } - @GetMapping("/check-contract-count") + @GetMapping("/audit-count") @Operation(summary = "获得待审核合同数量") @PreAuthorize("@ss.hasPermission('crm:contract:query')") - public CommonResult getCheckContractCount() { - return success(contractService.getCheckContractCount(getLoginUserId())); + public CommonResult getAuditContractCount() { + return success(contractService.getAuditContractCount(getLoginUserId())); } - @GetMapping("/end-contract-count") - @Operation(summary = "获得即将到期的合同数量") + @GetMapping("/remind-count") + @Operation(summary = "获得即将到期(提醒)的合同数量") @PreAuthorize("@ss.hasPermission('crm:contract:query')") - public CommonResult getEndContractCount() { - return success(contractService.getEndContractCount(getLoginUserId())); + public CommonResult getRemindContractCount() { + return success(contractService.getRemindContractCount(getLoginUserId())); } @GetMapping("/list-all-simple-by-customer") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigRespVO.java new file mode 100644 index 0000000000..c39cf92692 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigRespVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - CRM 合同配置 Response VO") +@Data +public class CrmContractConfigRespVO { + + @Schema(description = "是否开启提前提醒", example = "true") + private Boolean notifyEnabled; + + @Schema(description = "提前提醒天数", example = "2") + private Integer notifyDays; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigSaveReqVO.java new file mode 100644 index 0000000000..7ecd650e31 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config; + +import cn.hutool.core.util.BooleanUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.mzt.logapi.starter.annotation.DiffLogField; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import lombok.Data; + +import java.util.Objects; + +@Schema(description = "管理后台 - CRM 合同配置 Request VO") +@Data +public class CrmContractConfigSaveReqVO { + + @Schema(description = "是否开启提前提醒", example = "true") + @DiffLogField(name = "是否开启提前提醒") + private Boolean notifyEnabled; + + @Schema(description = "提前提醒天数", example = "2") + @DiffLogField(name = "提前提醒天数") + private Integer notifyDays; + + @AssertTrue(message = "提前提醒天数不能为空") + @JsonIgnore + public boolean isNotifyDaysValid() { + if (!BooleanUtil.isTrue(getNotifyEnabled())) { + return true; + } + return Objects.nonNull(getNotifyDays()); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractPageReqVO.java similarity index 99% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractPageReqVO.java index c61a64ccf7..74f8008b8f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java similarity index 99% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java index 887bdd80a0..8f5469eb14 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java similarity index 99% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java index 322127f42a..47491eef47 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmBusinessParseFunction; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmContactParseFunction; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractTransferReqVO.java similarity index 98% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractTransferReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractTransferReqVO.java index 88227c560a..4b8245c409 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractTransferReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractTransferReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java index 735f2e887d..64026f15d2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordRespVO; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordSaveReqVO; @@ -13,6 +14,8 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.followup.CrmFollowUpRecordService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -26,7 +29,7 @@ import java.util.ArrayList; import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -44,6 +47,9 @@ public class CrmFollowUpRecordController { @Resource private CrmBusinessService businessService; + @Resource + private AdminUserApi adminUserApi; + @PostMapping("/create") @Operation(summary = "创建跟进记录") @PreAuthorize("@ss.hasPermission('crm:follow-up-record:create')") @@ -74,17 +80,24 @@ public class CrmFollowUpRecordController { @PreAuthorize("@ss.hasPermission('crm:follow-up-record:query')") public CommonResult> getFollowUpRecordPage(@Valid CrmFollowUpRecordPageReqVO pageReqVO) { PageResult pageResult = followUpRecordService.getFollowUpRecordPage(pageReqVO); - /// 拼接数据 - Map contactMap = convertMap(contactService.getContactList( - convertSetByFlatMap(pageResult.getList(), item -> item.getContactIds().stream())), CrmContactDO::getId); - Map businessMap = convertMap(businessService.getBusinessList( - convertSetByFlatMap(pageResult.getList(), item -> item.getBusinessIds().stream())), CrmBusinessDO::getId); + // 1.1 查询联系人和商机 + Map contactMap = contactService.getContactMap( + convertSetByFlatMap(pageResult.getList(), item -> item.getContactIds().stream())); + Map businessMap = businessService.getBusinessMap( + convertSetByFlatMap(pageResult.getList(), item -> item.getBusinessIds().stream())); + // 1.2 查询用户 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), item -> Long.valueOf(item.getCreator()))); + // 2. 拼接数据 PageResult voPageResult = BeanUtils.toBean(pageResult, CrmFollowUpRecordRespVO.class, record -> { - record.setContactNames(new ArrayList<>()).setBusinessNames(new ArrayList<>()); - record.getContactIds().forEach(id -> MapUtils.findAndThen(contactMap, id, - contact -> record.getContactNames().add(contact.getName()))); - record.getContactIds().forEach(id -> MapUtils.findAndThen(businessMap, id, - business -> record.getBusinessNames().add(business.getName()))); + // 2.1 设置联系人和商机信息 + record.setBusinesses(new ArrayList<>()).setContacts(new ArrayList<>()); + record.getContactIds().forEach(id -> MapUtils.findAndThen(contactMap, id, contact -> + record.getContacts().add(new CrmBusinessRespVO().setId(contact.getId()).setName(contact.getName())))); + record.getContactIds().forEach(id -> MapUtils.findAndThen(businessMap, id, business -> + record.getBusinesses().add(new CrmBusinessRespVO().setId(business.getId()).setName(business.getName())))); + // 2.2 设置用户信息 + MapUtils.findAndThen(userMap, Long.valueOf(record.getCreator()), user -> record.setCreatorName(user.getNickname())); }); return success(voPageResult); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java index 83bfd9edc1..1ce10b73e3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.crm.controller.admin.followup.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -36,19 +38,26 @@ public class CrmFollowUpRecordRespVO { @Schema(description = "关联的商机编号数组") private List businessIds; - @Schema(description = "关联的商机名称数组") - private List businessNames; + @Schema(description = "关联的商机数组") + private List businesses; @Schema(description = "关联的联系人编号数组") private List contactIds; @Schema(description = "关联的联系人名称数组") - private List contactNames; + private List contacts; @Schema(description = "图片") private List picUrls; @Schema(description = "附件") private List fileUrls; + @Schema(description = "创建人", example = "1024") + @ExcelProperty("创建人") + private String creator; + @Schema(description = "创建人名字", example = "芋道源码") + @ExcelProperty("创建人名字") + private String creatorName; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index 88b4b30119..428bd07ad8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.permission; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; -import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; @@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import com.google.common.collect.Multimaps; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -29,11 +30,16 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - CRM 数据权限") @@ -98,18 +104,32 @@ public class CrmPermissionController { @PreAuthorize("@ss.hasPermission('crm:permission:query')") public CommonResult> getPermissionList(@RequestParam("bizType") Integer bizType, @RequestParam("bizId") Long bizId) { - List permission = permissionService.getPermissionListByBiz(bizType, bizId); - if (CollUtil.isEmpty(permission)) { + List permissions = permissionService.getPermissionListByBiz(bizType, bizId); + if (CollUtil.isEmpty(permissions)) { return success(Collections.emptyList()); } + // 查询相关数据 + Map userMap = adminUserApi.getUserMap( + convertSet(permissions, CrmPermissionDO::getUserId)); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + Map postMap = postApi.getPostMap( + convertSetByFlatMap(userMap.values(), AdminUserRespDTO::getPostIds, + item -> item != null ? item.stream() : Stream.empty())); // 拼接数据 - List userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId)); - Map deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId)); - Set postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, - item -> item != null ? item.stream() : Stream.empty()); - Map postMap = postApi.getPostMap(postIds); - return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap)); + return success(CollectionUtils.convertList(BeanUtils.toBean(permissions, CrmPermissionRespVO.class), item -> { + findAndThen(userMap, item.getUserId(), user -> { + item.setNickname(user.getNickname()); + findAndThen(deptMap, user.getDeptId(), deptRespDTO -> item.setDeptName(deptRespDTO.getName())); + if (CollUtil.isEmpty(user.getPostIds())) { + item.setPostNames(Collections.emptySet()); + return; + } + List postList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds()); + item.setPostNames(CollectionUtils.convertSet(postList, PostRespDTO::getName)); + }); + return item; + })); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http new file mode 100644 index 0000000000..e878ba1a93 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http @@ -0,0 +1,9 @@ +### 合同金额排行榜 +GET {{baseUrl}}/crm/statistics-rank/get-contract-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + +### 回款金额排行榜 +GET {{baseUrl}}/crm/statistics-rank/get-receivable-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.java similarity index 51% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.java index 21463aed09..e4cf61f7a3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.module.crm.controller.admin.bi; +package cn.iocoder.yudao.module.crm.controller.admin.statistics; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; -import cn.iocoder.yudao.module.crm.service.bi.CrmBiRankingService; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRankReqVO; +import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsRankingService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -19,68 +19,68 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Tag(name = "管理后台 - CRM BI 排行榜") +@Tag(name = "管理后台 - CRM 排行榜统计") @RestController -@RequestMapping("/crm/bi-rank") +@RequestMapping("/crm/statistics-rank") @Validated -public class CrmBiRankController { +public class CrmStatisticsRankController { @Resource - private CrmBiRankingService rankingService; + private CrmStatisticsRankingService rankingService; @GetMapping("/get-contract-price-rank") @Operation(summary = "获得合同金额排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getContractPriceRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getContractPriceRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getContractPriceRank(rankingReqVO)); } @GetMapping("/get-receivable-price-rank") @Operation(summary = "获得回款金额排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getReceivablePriceRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getReceivablePriceRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getReceivablePriceRank(rankingReqVO)); } @GetMapping("/get-contract-count-rank") @Operation(summary = "获得签约合同数量排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getContractCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getContractCountRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getContractCountRank(rankingReqVO)); } @GetMapping("/get-product-sales-rank") @Operation(summary = "获得产品销量排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getProductSalesRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getProductSalesRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getProductSalesRank(rankingReqVO)); } @GetMapping("/get-customer-count-rank") @Operation(summary = "获得新增客户数排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getCustomerCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getCustomerCountRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getCustomerCountRank(rankingReqVO)); } @GetMapping("/get-contacts-count-rank") @Operation(summary = "获得新增联系人数排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getContactsCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getContactsCountRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getContactsCountRank(rankingReqVO)); } @GetMapping("/get-follow-count-rank") @Operation(summary = "获得跟进次数排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getFollowCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getFollowCountRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getFollowCountRank(rankingReqVO)); } @GetMapping("/get-follow-customer-count-rank") @Operation(summary = "获得跟进客户数排行榜") - @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") - public CommonResult> getFollowCustomerCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + @PreAuthorize("@ss.hasPermission('crm:statistics-rank:query')") + public CommonResult> getFollowCustomerCountRank(@Valid CrmStatisticsRankReqVO rankingReqVO) { return success(rankingService.getFollowCustomerCountRank(rankingReqVO)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsRanKRespVO.java similarity index 83% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsRanKRespVO.java index 404ee33520..d5c865fd34 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsRanKRespVO.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "管理后台 - CRM BI 排行榜 Response VO") +@Schema(description = "管理后台 - CRM BI 排行榜统计 Response VO") @Data -public class CrmBiRanKRespVO { +public class CrmStatisticsRanKRespVO { @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long ownerUserId; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsRankReqVO.java similarity index 86% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsRankReqVO.java index 6d36f6d6f7..487921957c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsRankReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; +package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; @@ -11,9 +11,9 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@Schema(description = "管理后台 - CRM BI 排行榜 Request VO") +@Schema(description = "管理后台 - CRM 排行榜统计 Request VO") @Data -public class CrmBiRankReqVO { +public class CrmStatisticsRankReqVO { @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "部门 id 不能为空") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java deleted file mode 100644 index f51544caea..0000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.permission; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import com.google.common.collect.Multimaps; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; - -/** - * Crm 数据权限 Convert - * - * @author HUIHUI - */ -@Mapper -public interface CrmPermissionConvert { - - CrmPermissionConvert INSTANCE = Mappers.getMapper(CrmPermissionConvert.class); - - default List convert(List permissions, List userList, - Map deptMap, Map postMap) { - Map userMap = CollectionUtils.convertMap(userList, AdminUserRespDTO::getId); - return CollectionUtils.convertList(BeanUtils.toBean(permissions, CrmPermissionRespVO.class), item -> { - findAndThen(userMap, item.getUserId(), user -> { - item.setNickname(user.getNickname()); - findAndThen(deptMap, user.getDeptId(), deptRespDTO -> item.setDeptName(deptRespDTO.getName())); - if (CollUtil.isEmpty(user.getPostIds())) { - item.setPostNames(Collections.emptySet()); - return; - } - List postList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds()); - item.setPostNames(CollectionUtils.convertSet(postList, PostRespDTO::getName)); - }); - return item; - }); - } - - default List convertList(CrmPermissionUpdateReqVO updateReqVO) { - return CollectionUtils.convertList(updateReqVO.getIds(), - id -> new CrmPermissionDO().setId(id).setLevel(updateReqVO.getLevel())); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java new file mode 100644 index 0000000000..ab0c2d28e8 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.*; +import lombok.*; + +@TableName("crm_contract_config") +@KeySequence("crm_contract_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmContractConfigDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 是否开启提前提醒 + */ + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private Boolean notifyEnabled; + /** + * 提前提醒天数 + */ + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private Integer notifyDays; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java index 6b2fd84ee1..4718a8d7ae 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java @@ -12,7 +12,6 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; -import java.util.List; /** * 商机 Mapper @@ -54,15 +53,6 @@ public interface CrmBusinessMapper extends BaseMapperX { return selectJoinPage(pageReqVO, CrmBusinessDO.class, query); } - default List selectBatchIds(Collection ids, Long userId) { - MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - // 拼接数据权限的查询条件 - CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); - // 拼接自身的查询条件 - query.selectAll(CrmBusinessDO.class).in(CrmBusinessDO::getId, ids).orderByDesc(CrmBusinessDO::getId); - return selectJoinList(CrmBusinessDO.class, query); - } - default Long selectCountByStatusTypeId(Long statusTypeId) { return selectCount(CrmBusinessDO::getStatusTypeId, statusTypeId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java index 8fd82b90bd..7bff0c2046 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java @@ -27,6 +27,12 @@ public interface CrmContactBusinessMapper extends BaseMapperX contactIds) { + delete(new LambdaQueryWrapper() + .eq(CrmContactBusinessDO::getBusinessId, businessId) + .in(CrmContactBusinessDO::getContactId, contactIds)); + } + default List selectListByContactId(Long contactId) { return selectList(CrmContactBusinessDO::getContactId, contactId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java index 06404b7ab8..4a77665ad7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java @@ -69,14 +69,6 @@ public interface CrmContactMapper extends BaseMapperX { return selectJoinPage(pageReqVO, CrmContactDO.class, query); } - default List selectBatchIds(Collection ids, Long ownerUserId) { - MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - // 拼接数据权限的查询条件 - CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, ownerUserId); - query.selectAll(CrmContactDO.class).in(CrmContactDO::getId, ids).orderByDesc(CrmContactDO::getId); - return selectJoinList(CrmContactDO.class, query); - } - default List selectListByCustomerId(Long customerId) { return selectList(CrmContactDO::getCustomerId, customerId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java new file mode 100644 index 0000000000..64e6f918bc --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.contract; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 合同配置 Mapper + * + * @author Wanwan + */ +@Mapper +public interface CrmContractConfigMapper extends BaseMapperX { + + default CrmContractConfigDO selectOne() { + return selectOne(new QueryWrapperX().limitN(1)); + } + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index 7993224caa..e06afb2571 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -5,7 +5,8 @@ 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.framework.mybatis.core.query.MPJLambdaWrapperX; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; @@ -39,7 +40,17 @@ public interface CrmContractMapper extends BaseMapperX { .orderByDesc(CrmContractDO::getId)); } - default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { + default PageResult selectPageByBusinessId(CrmContractPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) + .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) + .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) + .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) + .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) + .orderByDesc(CrmContractDO::getId)); + } + + default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId, CrmContractConfigDO config) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), @@ -57,10 +68,8 @@ public interface CrmContractMapper extends BaseMapperX { LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); if (CrmContractPageReqVO.EXPIRY_TYPE_ABOUT_TO_EXPIRE.equals(pageReqVO.getExpiryType())) { // 即将到期 - // TODO: @芋艿 需要配置 提前提醒天数 - int REMIND_DAYS = 20; query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) - .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); + .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(config.getNotifyDays())); } else if (CrmContractPageReqVO.EXPIRY_TYPE_EXPIRED.equals(pageReqVO.getExpiryType())) { // 已到期 query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) .lt(CrmContractDO::getEndTime, endOfToday); @@ -85,17 +94,17 @@ public interface CrmContractMapper extends BaseMapperX { return selectCount(CrmContractDO::getBusinessId, businessId); } - default Long selectCheckContractCount(Long userId) { + default Long selectCountByAudit(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - // 未提交 or 审核不通过 - query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus()); + // 未审核 + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.PROCESS.getStatus()); return selectCount(query); } - default Long selectEndContractCount(Long userId) { + default Long selectCountByRemind(Long userId, CrmContractConfigDO config) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), @@ -103,10 +112,8 @@ public interface CrmContractMapper extends BaseMapperX { // 即将到期 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); - // TODO: @dhb52 需要配置 提前提醒天数 - int REMIND_DAYS = 20; - query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) - .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) // 必须审批通过! + .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(config.getNotifyDays())); return selectCount(query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsRankingMapper.java similarity index 52% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsRankingMapper.java index 9b71df7b69..4b51ab2fe9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsRankingMapper.java @@ -1,18 +1,18 @@ -package cn.iocoder.yudao.module.crm.dal.mysql.bi; +package cn.iocoder.yudao.module.crm.dal.mysql.statistics; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRankReqVO; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** - * CRM BI 排行榜 Mapper + * CRM 排行榜统计 Mapper * * @author anhaohao */ @Mapper -public interface CrmBiRankingMapper { +public interface CrmStatisticsRankingMapper { /** * 查询合同金额排行榜 @@ -20,7 +20,7 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 合同金额排行榜 */ - List selectContractPriceRank(CrmBiRankReqVO rankReqVO); + List selectContractPriceRank(CrmStatisticsRankReqVO rankReqVO); /** * 查询回款金额排行榜 @@ -28,7 +28,7 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 回款金额排行榜 */ - List selectReceivablePriceRank(CrmBiRankReqVO rankReqVO); + List selectReceivablePriceRank(CrmStatisticsRankReqVO rankReqVO); /** * 查询签约合同数量排行榜 @@ -36,7 +36,7 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 签约合同数量排行榜 */ - List selectContractCountRank(CrmBiRankReqVO rankReqVO); + List selectContractCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 查询产品销量排行榜 @@ -44,7 +44,7 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 产品销量排行榜 */ - List selectProductSalesRank(CrmBiRankReqVO rankReqVO); + List selectProductSalesRank(CrmStatisticsRankReqVO rankReqVO); /** * 查询新增客户数排行榜 @@ -52,7 +52,7 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 新增客户数排行榜 */ - List selectCustomerCountRank(CrmBiRankReqVO rankReqVO); + List selectCustomerCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 查询联系人数量排行榜 @@ -60,7 +60,7 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 联系人数量排行榜 */ - List selectContactsCountRank(CrmBiRankReqVO rankReqVO); + List selectContactsCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 查询跟进次数排行榜 @@ -68,7 +68,7 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 跟进次数排行榜 */ - List selectFollowCountRank(CrmBiRankReqVO rankReqVO); + List selectFollowCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 查询跟进客户数排行榜 @@ -76,6 +76,6 @@ public interface CrmBiRankingMapper { * @param rankReqVO 参数 * @return 跟进客户数排行榜 */ - List selectFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); + List selectFollowCustomerCountRank(CrmStatisticsRankReqVO rankReqVO); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java index 63ef761a72..ab7982024c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java @@ -16,6 +16,9 @@ import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 商机 Service 接口 @@ -101,15 +104,17 @@ public interface CrmBusinessService { * @param ids 编号 * @return 商机列表 */ - List getBusinessList(Collection ids, Long userId); + List getBusinessList(Collection ids); /** - * 获得商机列表 + * 获得商机 Map * * @param ids 编号 - * @return 商机列表 + * @return 商机 Map */ - List getBusinessList(Collection ids); + default Map getBusinessMap(Collection ids) { + return convertMap(getBusinessList(ids), CrmBusinessDO::getId); + } /** * 获得指定商机编号的产品列表 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 11b6193fce..e709b65472 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -322,14 +322,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { return validateBusinessExists(id); } - @Override - public List getBusinessList(Collection ids, Long userId) { - if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); - } - return businessMapper.selectBatchIds(ids, userId); - } - @Override public List getBusinessList(Collection ids) { if (CollUtil.isEmpty(ids)) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java index 76477c281f..2deaf00093 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.service.contact; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusiness2ReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import jakarta.validation.Valid; @@ -14,19 +15,33 @@ import java.util.List; public interface CrmContactBusinessService { /** - * 创建联系人与商机的关联 + * 创建联系人与商机的关联【通过联系人,关联商机】 * * @param createReqVO 创建信息 */ void createContactBusinessList(@Valid CrmContactBusinessReqVO createReqVO); /** - * 删除联系人与商机的关联 + * 创建联系人与商机的关联【通过商机,关联联系人】 + * + * @param createReqVO 创建信息 + */ + void createContactBusinessList2(@Valid CrmContactBusiness2ReqVO createReqVO); + + /** + * 删除联系人与商机的关联【通过联系人,取关商机】 * * @param deleteReqVO 删除信息 */ void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO); + /** + * 删除联系人与商机的关联【通过商机,取关联系人】 + * + * @param deleteReqVO 删除信息 + */ + void deleteContactBusinessList2(@Valid CrmContactBusiness2ReqVO deleteReqVO); + /** * 删除联系人与商机的关联,基于联系人编号 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java index e975df14ef..c8850e3eb4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.service.contact; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusiness2ReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; @@ -67,6 +68,32 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService } } + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#createReqVO.businessId", level = CrmPermissionLevelEnum.WRITE) + public void createContactBusinessList2(CrmContactBusiness2ReqVO createReqVO) { + CrmBusinessDO business = businessService.getBusiness(createReqVO.getBusinessId()); + if (business == null) { + throw exception(BUSINESS_NOT_EXISTS); + } + // 遍历处理,考虑到一般数量不会太多,代码处理简单 + List saveDOList = new ArrayList<>(); + createReqVO.getContactIds().forEach(contactId -> { + CrmContactDO contact = contactService.getContact(contactId); + if (contact == null) { + throw exception(CONTACT_NOT_EXISTS); + } + // 关联判重 + if (contactBusinessMapper.selectByContactIdAndBusinessId(contactId, createReqVO.getBusinessId()) != null) { + return; + } + saveDOList.add(new CrmContactBusinessDO(null, contactId, createReqVO.getBusinessId())); + }); + // 批量插入 + if (CollUtil.isNotEmpty(saveDOList)) { + contactBusinessMapper.insertBatch(saveDOList); + } + } + @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#deleteReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) public void deleteContactBusinessList(CrmContactBusinessReqVO deleteReqVO) { @@ -79,6 +106,18 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService deleteReqVO.getContactId(), deleteReqVO.getBusinessIds()); } + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#deleteReqVO.businessId", level = CrmPermissionLevelEnum.WRITE) + public void deleteContactBusinessList2(CrmContactBusiness2ReqVO deleteReqVO) { + CrmBusinessDO business = businessService.getBusiness(deleteReqVO.getBusinessId()); + if (business == null) { + throw exception(BUSINESS_NOT_EXISTS); + } + // 直接删除 + contactBusinessMapper.deleteByBusinessIdAndContactId( + deleteReqVO.getBusinessId(), deleteReqVO.getContactIds()); + } + @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#contactId", level = CrmPermissionLevelEnum.WRITE) public void deleteContactBusinessByContactId(Long contactId) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index 822bf095d1..23c29d3bcd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java @@ -95,15 +95,6 @@ public interface CrmContactService { */ void validateContact(Long id); - /** - * 获得联系人列表 - * - * @param ids 编号 - * @param userId 用户编号 - * @return 联系人列表 - */ - List getContactListByIds(Collection ids, Long userId); - /** * 获得联系人列表 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 651da773fc..d8e356124e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -257,14 +257,6 @@ public class CrmContactServiceImpl implements CrmContactService { validateContactExists(id); } - @Override - public List getContactListByIds(Collection ids, Long userId) { - if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); - } - return contactMapper.selectBatchIds(ids, userId); - } - @Override public List getContactList(Collection ids) { if (CollUtil.isEmpty(ids)) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java new file mode 100644 index 0000000000..79471aaf98 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.crm.service.contract; + +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config.CrmContractConfigSaveReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO; +import jakarta.validation.Valid; + +/** + * 合同配置 Service 接口 + * + * @author 芋道源码 + */ +public interface CrmContractConfigService { + + /** + * 获得合同配置 + * + * @return 合同配置 + */ + CrmContractConfigDO getContractConfig(); + + /** + * 保存合同配置 + * + * @param saveReqVO 更新信息 + */ + void saveContractConfig(@Valid CrmContractConfigSaveReqVO saveReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java new file mode 100644 index 0000000000..c9379dcecb --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.crm.service.contract; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config.CrmContractConfigSaveReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO; +import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractConfigMapper; +import com.mzt.logapi.context.LogRecordContext; +import com.mzt.logapi.starter.annotation.LogRecord; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Objects; + +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; + +/** + * 合同配置 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class CrmContractConfigServiceImpl implements CrmContractConfigService { + + @Resource + private CrmContractConfigMapper contractConfigMapper; + + @Override + public CrmContractConfigDO getContractConfig() { + return contractConfigMapper.selectOne(); + } + + @Override + @LogRecord(type = CRM_CONTRACT_CONFIG_TYPE, subType = CRM_CONTRACT_CONFIG_SUB_TYPE, bizNo = "{{#configId}}", + success = CRM_CONTRACT_CONFIG_SUCCESS) + public void saveContractConfig(CrmContractConfigSaveReqVO saveReqVO) { + // 1. 存在,则进行更新 + CrmContractConfigDO dbConfig = getContractConfig(); + CrmContractConfigDO config = BeanUtils.toBean(saveReqVO, CrmContractConfigDO.class); + if (Objects.nonNull(dbConfig)) { + contractConfigMapper.updateById(config.setId(dbConfig.getId())); + // 记录操作日志上下文 + LogRecordContext.putVariable("isConfigUpdate", Boolean.TRUE); + LogRecordContext.putVariable("configId", config.getId()); + return; + } + + // 2. 不存在,则进行插入 + contractConfigMapper.insert(config); + // 记录操作日志上下文 + LogRecordContext.putVariable("isConfigUpdate", Boolean.FALSE); + LogRecordContext.putVariable("configId", config.getId()); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index cbd9cbbe74..3732c17377 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractSaveReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -109,10 +110,20 @@ public interface CrmContractService { * 数据权限:基于 {@link CrmCustomerDO} 读取 * * @param pageReqVO 分页查询 - * @return 联系人分页 + * @return 合同分页 */ PageResult getContractPageByCustomerId(CrmContractPageReqVO pageReqVO); + /** + * 获得合同分页,基于指定商机 + * + * 数据权限:基于 {@link CrmBusinessDO} 读取 + * + * @param pageReqVO 分页查询 + * @return 合同分页 + */ + PageResult getContractPageByBusinessId(CrmContractPageReqVO pageReqVO); + /** * 查询属于某个联系人的合同数量 * @@ -151,14 +162,14 @@ public interface CrmContractService { * @param userId 用户编号 * @return 提醒数量 */ - Long getCheckContractCount(Long userId); + Long getAuditContractCount(Long userId); /** - * 获得即将到期的合同数量 + * 获得即将到期(提醒)的合同数量 * * @param userId 用户编号 * @return 提醒数量 */ - Long getEndContractCount(Long userId); + Long getRemindContractCount(Long userId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index f09f1c0a75..4c8f8eca58 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -10,9 +10,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractSaveReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; @@ -83,6 +84,8 @@ public class CrmContractServiceImpl implements CrmContractService { private CrmBusinessService businessService; @Resource private CrmContactService contactService; + @Resource + private CrmContractConfigService contractConfigService; @Resource private AdminUserApi adminUserApi; @@ -172,8 +175,6 @@ public class CrmContractServiceImpl implements CrmContractService { } } - // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum - /** * 校验关联数据是否存在 * @@ -314,7 +315,7 @@ public class CrmContractServiceImpl implements CrmContractService { contractMapper.updateById(new CrmContractDO().setId(id).setAuditStatus(auditStatus)); } - //======================= 查询相关 ======================= + // ======================= 查询相关 ======================= @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.READ) @@ -332,7 +333,16 @@ public class CrmContractServiceImpl implements CrmContractService { @Override public PageResult getContractPage(CrmContractPageReqVO pageReqVO, Long userId) { - return contractMapper.selectPage(pageReqVO, userId); + // 1. 即将到期,需要查询合同配置 + CrmContractConfigDO config = null; + if (CrmContractPageReqVO.EXPIRY_TYPE_ABOUT_TO_EXPIRE.equals(pageReqVO.getExpiryType())) { + config = contractConfigService.getContractConfig(); + if (config != null && Boolean.FALSE.equals(config.getNotifyEnabled())) { + config = null; + } + } + // 2. 查询分页 + return contractMapper.selectPage(pageReqVO, userId, config); } @Override @@ -341,6 +351,12 @@ public class CrmContractServiceImpl implements CrmContractService { return contractMapper.selectPageByCustomerId(pageReqVO); } + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#pageReqVO.businessId", level = CrmPermissionLevelEnum.READ) + public PageResult getContractPageByBusinessId(CrmContractPageReqVO pageReqVO) { + return contractMapper.selectPageByBusinessId(pageReqVO); + } + @Override public Long getContractCountByContactId(Long contactId) { return contractMapper.selectCountByContactId(contactId); @@ -361,16 +377,18 @@ public class CrmContractServiceImpl implements CrmContractService { return contractProductMapper.selectListByContractId(contactId); } - // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; - @Override - public Long getCheckContractCount(Long userId) { - return contractMapper.selectCheckContractCount(userId); + public Long getAuditContractCount(Long userId) { + return contractMapper.selectCountByAudit(userId); } @Override - public Long getEndContractCount(Long userId) { - return contractMapper.selectEndContractCount(userId); + public Long getRemindContractCount(Long userId) { + CrmContractConfigDO config = contractConfigService.getContractConfig(); + if (config == null || Boolean.FALSE.equals(config.getNotifyEnabled())) { + return 0L; + } + return contractMapper.selectCountByRemind(userId, config); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java index 303a758d20..9099b19548 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java @@ -26,26 +26,16 @@ public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigSe @Resource private CrmCustomerPoolConfigMapper customerPoolConfigMapper; - /** - * 获得客户公海配置 - * - * @return 客户公海配置 - */ @Override public CrmCustomerPoolConfigDO getCustomerPoolConfig() { return customerPoolConfigMapper.selectOne(); } - /** - * 保存客户公海配置 - * - * @param saveReqVO 更新信息 - */ @Override @LogRecord(type = CRM_CUSTOMER_POOL_CONFIG_TYPE, subType = CRM_CUSTOMER_POOL_CONFIG_SUB_TYPE, bizNo = "{{#poolConfigId}}", success = CRM_CUSTOMER_POOL_CONFIG_SUCCESS) public void saveCustomerPoolConfig(CrmCustomerPoolConfigSaveReqVO saveReqVO) { - // 存在,则进行更新 + // 1. 存在,则进行更新 CrmCustomerPoolConfigDO dbConfig = getCustomerPoolConfig(); CrmCustomerPoolConfigDO poolConfig = BeanUtils.toBean(saveReqVO, CrmCustomerPoolConfigDO.class); if (Objects.nonNull(dbConfig)) { @@ -55,7 +45,8 @@ public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigSe LogRecordContext.putVariable("poolConfigId", poolConfig.getId()); return; } - // 不存在,则进行插入 + + // 2. 不存在,则进行插入 customerPoolConfigMapper.insert(poolConfig); // 记录操作日志上下文 LogRecordContext.putVariable("isPoolConfigUpdate", Boolean.FALSE); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 03245b2712..314349865b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -258,11 +258,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override public CrmCustomerImportRespVO importCustomerList(List importCustomers, CrmCustomerImportReqVO importReqVO) { + // 校验非空 + importCustomers = filterList(importCustomers, item -> Objects.nonNull(item.getName())); if (CollUtil.isEmpty(importCustomers)) { throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); } - // 因为有下拉所以需要过滤掉空行 - importCustomers = filterList(importCustomers, item -> Objects.nonNull(item.getName())); + + // 逐条处理 CrmCustomerImportRespVO respVO = CrmCustomerImportRespVO.builder().createCustomerNames(new ArrayList<>()) .updateCustomerNames(new ArrayList<>()).failureCustomerNames(new LinkedHashMap<>()).build(); importCustomers.forEach(importCustomer -> { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index ab9c5df5be..31c62d32af 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -69,6 +69,9 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { crmFollowUpRecordMapper.insert(record); // 2. 更新 bizId 对应的记录 + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), record.getBizType())) { // 更新客户跟进信息 + customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); + } if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息 businessService.updateBusinessFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } @@ -81,9 +84,6 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), record.getBizType())) { // 更新合同跟进信息 contractService.updateContractFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } - if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), record.getBizType())) { // 更新客户跟进信息 - customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); - } // 3.1 更新 contactIds 对应的记录,只更新 nextTime if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 3c19302022..7191df8806 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -2,16 +2,16 @@ package cn.iocoder.yudao.module.crm.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; -import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -74,8 +74,9 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { // 1. 校验存在 validatePermissionExists(updateReqVO.getIds()); // 2. 更新 - List updateDO = CrmPermissionConvert.INSTANCE.convertList(updateReqVO); - permissionMapper.updateBatch(updateDO); + List updateList = CollectionUtils.convertList(updateReqVO.getIds(), + id -> new CrmPermissionDO().setId(id).setLevel(updateReqVO.getLevel())); + permissionMapper.updateBatch(updateList); } private void validatePermissionExists(Collection ids) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankingService.java similarity index 52% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankingService.java index 2ff28d3857..c9455708c1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankingService.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.module.crm.service.bi; +package cn.iocoder.yudao.module.crm.service.statistics; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRankReqVO; import java.util.List; /** - * CRM BI 排行榜 Service 接口 + * CRM 排行榜统计 Service 接口 * * @author anhaohao */ -public interface CrmBiRankingService { +public interface CrmStatisticsRankingService { /** * 获得合同金额排行榜 @@ -19,7 +19,7 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 合同金额排行榜 */ - List getContractPriceRank(CrmBiRankReqVO rankReqVO); + List getContractPriceRank(CrmStatisticsRankReqVO rankReqVO); /** * 获得回款金额排行榜 @@ -27,7 +27,7 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 回款金额排行榜 */ - List getReceivablePriceRank(CrmBiRankReqVO rankReqVO); + List getReceivablePriceRank(CrmStatisticsRankReqVO rankReqVO); /** * 获得签约合同数量排行榜 @@ -35,7 +35,7 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 签约合同数量排行榜 */ - List getContractCountRank(CrmBiRankReqVO rankReqVO); + List getContractCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 获得产品销量排行榜 @@ -43,7 +43,7 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 产品销量排行榜 */ - List getProductSalesRank(CrmBiRankReqVO rankReqVO); + List getProductSalesRank(CrmStatisticsRankReqVO rankReqVO); /** * 获得新增客户数排行榜 @@ -51,7 +51,7 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 新增客户数排行榜 */ - List getCustomerCountRank(CrmBiRankReqVO rankReqVO); + List getCustomerCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 获得联系人数量排行榜 @@ -59,7 +59,7 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 联系人数量排行榜 */ - List getContactsCountRank(CrmBiRankReqVO rankReqVO); + List getContactsCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 获得跟进次数排行榜 @@ -67,7 +67,7 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 跟进次数排行榜 */ - List getFollowCountRank(CrmBiRankReqVO rankReqVO); + List getFollowCountRank(CrmStatisticsRankReqVO rankReqVO); /** * 获得跟进客户数排行榜 @@ -75,6 +75,6 @@ public interface CrmBiRankingService { * @param rankReqVO 排行参数 * @return 跟进客户数排行榜 */ - List getFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); + List getFollowCustomerCountRank(CrmStatisticsRankReqVO rankReqVO); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankingServiceImpl.java similarity index 54% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankingServiceImpl.java index 60e1b4ecb2..428ec17637 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankingServiceImpl.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.module.crm.service.bi; +package cn.iocoder.yudao.module.crm.service.statistics; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; -import cn.iocoder.yudao.module.crm.dal.mysql.bi.CrmBiRankingMapper; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRankReqVO; +import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsRankingMapper; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -23,16 +23,16 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; /** - * CRM BI 排行榜 Service 实现类 + * CRM 排行榜统计 Service 实现类 * * @author anhaohao */ @Service @Validated -public class CrmBiRankingServiceImpl implements CrmBiRankingService { +public class CrmStatisticsRankingServiceImpl implements CrmStatisticsRankingService { @Resource - private CrmBiRankingMapper biRankingMapper; + private CrmStatisticsRankingMapper rankMapper; @Resource private AdminUserApi adminUserApi; @@ -40,43 +40,43 @@ public class CrmBiRankingServiceImpl implements CrmBiRankingService { private DeptApi deptApi; @Override - public List getContractPriceRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectContractPriceRank); + public List getContractPriceRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectContractPriceRank); } @Override - public List getReceivablePriceRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectReceivablePriceRank); + public List getReceivablePriceRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectReceivablePriceRank); } @Override - public List getContractCountRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectContractCountRank); + public List getContractCountRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectContractCountRank); } @Override - public List getProductSalesRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectProductSalesRank); + public List getProductSalesRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectProductSalesRank); } @Override - public List getCustomerCountRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectCustomerCountRank); + public List getCustomerCountRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectCustomerCountRank); } @Override - public List getContactsCountRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectContactsCountRank); + public List getContactsCountRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectContactsCountRank); } @Override - public List getFollowCountRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectFollowCountRank); + public List getFollowCountRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectFollowCountRank); } @Override - public List getFollowCustomerCountRank(CrmBiRankReqVO rankReqVO) { - return getRank(rankReqVO, biRankingMapper::selectFollowCustomerCountRank); + public List getFollowCustomerCountRank(CrmStatisticsRankReqVO rankReqVO) { + return getRank(rankReqVO, rankMapper::selectFollowCustomerCountRank); } /** @@ -86,18 +86,18 @@ public class CrmBiRankingServiceImpl implements CrmBiRankingService { * @param rankFunction 排行榜方法 * @return 排行版数据 */ - private List getRank(CrmBiRankReqVO rankReqVO, Function> rankFunction) { + private List getRank(CrmStatisticsRankReqVO rankReqVO, Function> rankFunction) { // 1. 获得用户编号数组 rankReqVO.setUserIds(getUserIds(rankReqVO.getDeptId())); if (CollUtil.isEmpty(rankReqVO.getUserIds())) { return Collections.emptyList(); } // 2. 获得排行数据 - List ranks = rankFunction.apply(rankReqVO); + List ranks = rankFunction.apply(rankReqVO); if (CollUtil.isEmpty(ranks)) { return Collections.emptyList(); } - ranks.sort(Comparator.comparing(CrmBiRanKRespVO::getCount).reversed()); + ranks.sort(Comparator.comparing(CrmStatisticsRanKRespVO::getCount).reversed()); // 3. 拼接用户信息 appendUserInfo(ranks); return ranks; @@ -108,8 +108,8 @@ public class CrmBiRankingServiceImpl implements CrmBiRankingService { * * @param ranks 排行榜数据 */ - private void appendUserInfo(List ranks) { - Map userMap = adminUserApi.getUserMap(convertSet(ranks, CrmBiRanKRespVO::getOwnerUserId)); + private void appendUserInfo(List ranks) { + Map userMap = adminUserApi.getUserMap(convertSet(ranks, CrmStatisticsRanKRespVO::getOwnerUserId)); Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); ranks.forEach(rank -> MapUtils.findAndThen(userMap, rank.getOwnerUserId(), user -> { rank.setNickname(user.getNickname()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml index 10030e0a74..c193873ce0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml @@ -1,10 +1,10 @@ - + + resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsRanKRespVO"> SELECT COUNT(1) AS count, owner_user_id FROM crm_contract WHERE deleted = 0 @@ -64,7 +64,7 @@