From a5d33692c1d6967ee6d9dd34fa0d84b4339d18df Mon Sep 17 00:00:00 2001 From: dhb52 Date: Fri, 16 Feb 2024 22:45:37 +0800 Subject: [PATCH 01/54] =?UTF-8?q?refactor:=20TodayCustomer=E5=88=A9?= =?UTF-8?q?=E7=94=A8CrmCustomerController#getCustomerPage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/backlog/CrmBacklogController.java | 41 -------------- .../backlog/vo/CrmTodayCustomerPageReqVO.java | 37 ------------ .../admin/customer/CrmCustomerController.java | 3 +- .../customer/vo/CrmCustomerPageReqVO.java | 19 +++++++ .../dal/mysql/customer/CrmCustomerMapper.java | 56 ++++++++----------- .../service/message/CrmBacklogService.java | 23 -------- .../message/CrmBacklogServiceImpl.java | 28 ---------- 7 files changed, 43 insertions(+), 164 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java deleted file mode 100644 index 9b8841e2e..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.backlog; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.message.CrmBacklogService; -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.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - CRM待办消息") -@RestController -@RequestMapping("/crm/backlog") -@Validated -public class CrmBacklogController { - - @Resource - private CrmBacklogService crmMessageService; - - // TODO 芋艿:未来可能合并到 CrmCustomerController - @GetMapping("/today-customer-page") - @Operation(summary = "今日需联系客户") - @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getTodayCustomerPage(@Valid CrmTodayCustomerPageReqVO pageReqVO) { - PageResult pageResult = crmMessageService.getTodayCustomerPage(pageReqVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, CrmCustomerRespVO.class)); - } - -} \ 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/backlog/vo/CrmTodayCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java deleted file mode 100644 index 21fd88c0b..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.backlog.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 今日需联系客户 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmTodayCustomerPageReqVO extends PageParam { - - /** - * 联系状态 - 今日需联系 - */ - public static final int CONTACT_TODAY = 1; - /** - * 联系状态 - 已逾期 - */ - public static final int CONTACT_EXPIRED = 2; - /** - * 联系状态 - 已联系 - */ - public static final int CONTACT_ALREADY = 3; - - @Schema(description = "联系状态", example = "1") - private Integer contactStatus; - - @Schema(description = "场景类型", example = "1") - @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; - -} \ 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/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index ddd2a7f70..a2420bc81 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -130,8 +130,7 @@ public class CrmCustomerController { CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); if (ObjUtil.isNull(poolConfigDO) || Boolean.FALSE.equals(poolConfigDO.getEnabled()) - || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled()) - ) { // TODO @dbh52:这个括号,一般不换行,在 java 这里; + || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java index bded50473..c30a6af91 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java @@ -14,6 +14,19 @@ import lombok.ToString; @ToString(callSuper = true) public class CrmCustomerPageReqVO extends PageParam { + /** + * 联系状态 - 今日需联系 + */ + public static final int CONTACT_TODAY = 1; + /** + * 联系状态 - 已逾期 + */ + public static final int CONTACT_EXPIRED = 2; + /** + * 联系状态 - 已联系 + */ + public static final int CONTACT_ALREADY = 3; + @Schema(description = "客户名称", example = "赵六") private String name; @@ -36,4 +49,10 @@ public class CrmCustomerPageReqVO extends PageParam { @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 + @Schema(description = "联系状态", example = "1") + private Integer contactStatus; // backlog查询条件, null 则表示为不做查询 + + @Schema(description = "跟进状态", example = "true") + private Boolean followUpStatus; // backlog查询条件, null 则表示为不做查询 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 29cd47c66..da2ea92f3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.ObjUtil; 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.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; @@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import java.time.LocalDateTime; import java.util.Collection; @@ -58,6 +59,24 @@ public interface CrmCustomerMapper extends BaseMapperX { .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId()) .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel()) .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()); + + // backlog 查询 + if (ObjUtil.isNotNull(pageReqVO.getContactStatus())) { + Assert.isNull(pageReqVO.getPool(), "[是否为公海数据]必须是null"); + + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); + if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 + query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); + } else if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_EXPIRED)) { // 已逾期 + query.lt(CrmCustomerDO::getContactNextTime, beginOfToday); + } else if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_ALREADY)) { // 已联系 + query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); + } else { + throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus()); + } + } + return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } @@ -70,37 +89,6 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectJoinList(CrmCustomerDO.class, query); } - /** - * 待办事项 - 今日需联系客户 - * - * @param pageReqVO 分页请求参数 - * @param userId 当前用户ID - * @return 分页结果 - */ - default PageResult selectTodayCustomerPage(CrmTodayCustomerPageReqVO pageReqVO, Long userId) { - MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); - - // 拼接自身的查询条件 - query.selectAll(CrmCustomerDO.class); - if (pageReqVO.getContactStatus() != null) { - LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); - LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); - if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 - query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); - } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_EXPIRED)) { // 已逾期 - query.lt(CrmCustomerDO::getContactNextTime, beginOfToday); - } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_ALREADY)) { // 已联系 - query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); - } else { - throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus()); - } - } - return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); - } - default List selectListByLockAndNotPool(Boolean lockStatus) { return selectList(new LambdaQueryWrapper() .eq(CrmCustomerDO::getLockStatus, lockStatus) @@ -118,7 +106,9 @@ public interface CrmCustomerMapper extends BaseMapperX { // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); - // TODO @dhb52:lock 的情况,不需要提醒哈; + + // 锁定状态不需要提醒 + query.ne(CrmCustomerDO::getLockStatus, true); // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java deleted file mode 100644 index f13514c25..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.message; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import jakarta.validation.Valid; - -/** - * CRM 待办消息 Service 接口 - * - * @author dhb52 - */ -public interface CrmBacklogService { - - /** - * 根据【联系状态】、【场景类型】筛选客户分页 - * - * @param pageReqVO 分页查询 - * @return 分页数据 - */ - PageResult getTodayCustomerPage(@Valid CrmTodayCustomerPageReqVO pageReqVO, Long userId); - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java deleted file mode 100644 index 5c2417266..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.message; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; -import org.springframework.validation.annotation.Validated; - -/** - * 待办消息 Service 实现类 - * - * @author dhb52 - */ -@Component -@Validated -public class CrmBacklogServiceImpl implements CrmBacklogService { - - @Resource - private CrmCustomerMapper customerMapper; - - @Override - public PageResult getTodayCustomerPage(CrmTodayCustomerPageReqVO pageReqVO, Long userId) { - return customerMapper.selectTodayCustomerPage(pageReqVO, userId); - } - -} From d23dfd4276716dfbcefded0b6ed980ceac180777 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Sun, 18 Feb 2024 00:03:11 +0800 Subject: [PATCH 02/54] =?UTF-8?q?feat:=20CRM/backlog=20=E6=8F=90=E9=86=92?= =?UTF-8?q?=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/CrmClueController.java | 7 ++ .../admin/contract/CrmContractController.java | 15 +++ .../admin/customer/CrmCustomerController.java | 36 ++++++ .../receivable/CrmReceivableController.java | 8 ++ .../CrmReceivablePlanController.java | 8 ++ .../crm/dal/mysql/clue/CrmClueMapper.java | 14 +++ .../dal/mysql/contract/CrmContractMapper.java | 30 +++++ .../dal/mysql/customer/CrmCustomerMapper.java | 105 ++++++++++++------ .../mysql/receivable/CrmReceivableMapper.java | 16 +++ .../receivable/CrmReceivablePlanMapper.java | 16 +++ .../crm/service/clue/CrmClueService.java | 8 ++ .../crm/service/clue/CrmClueServiceImpl.java | 5 + .../service/contract/CrmContractService.java | 17 +++ .../contract/CrmContractServiceImpl.java | 11 ++ .../service/customer/CrmCustomerService.java | 38 ++++++- .../customer/CrmCustomerServiceImpl.java | 18 +++ .../receivable/CrmReceivablePlanService.java | 7 ++ .../CrmReceivablePlanServiceImpl.java | 6 +- .../receivable/CrmReceivableService.java | 8 ++ .../receivable/CrmReceivableServiceImpl.java | 6 +- 20 files changed, 343 insertions(+), 36 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index 8be62ae26..a3acd04f6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -104,4 +104,11 @@ public class CrmClueController { return success(Boolean.TRUE); } + @GetMapping("/follow-leads-count") + @Operation(summary = "获得分配给我的线索数量") + @PreAuthorize("@ss.hasPermission('crm:clue:query')") + public CommonResult getFollowLeadsCount() { + return success(clueService.getFollowLeadsCount(getLoginUserId())); + } + } 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 aaaccbd81..8de96587e 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 @@ -192,4 +192,19 @@ public class CrmContractController { return success(true); } + @GetMapping("/check-contract-count") + @Operation(summary = "获得待审核合同数量") + @PreAuthorize("@ss.hasPermission('crm:contract:query')") + public CommonResult getCheckContractCount() { + return success(contractService.getCheckContractCount(getLoginUserId())); + } + + + @GetMapping("/end-contract-count") + @Operation(summary = "获得即将到期的合同数量") + @PreAuthorize("@ss.hasPermission('crm:contract:query')") + public CommonResult getEndContractCount() { + return success(contractService.getEndContractCount(getLoginUserId())); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index a2420bc81..83e6274a0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -149,6 +150,41 @@ public class CrmCustomerController { return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); } + @GetMapping("/put-in-pool-remind-count") + @Operation(summary = "获得待进入公海客户数量") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult getPutInPoolRemindCustomerCount() { + // 获取公海配置 TODO @dbh52:合并到 getPutInPoolRemindCustomerPage 会更合适哈; + CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); + if (ObjUtil.isNull(poolConfigDO) + || Boolean.FALSE.equals(poolConfigDO.getEnabled()) + || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { + throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); + } + + CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO(); + pageVO.setPool(null); + pageVO.setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY); + pageVO.setSceneType(CrmSceneTypeEnum.OWNER.getType()); + + return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId())); + } + + @GetMapping("/today-customer-count") + @Operation(summary = "获得今日需联系客户数量") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult getTodayCustomerCount() { + return success(customerService.getTodayCustomerCount(getLoginUserId())); + } + + @GetMapping("/follow-customer-count") + @Operation(summary = "获得分配给我的客户数量") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult getFollowCustomerCount() { + return success(customerService.getFollowCustomerCount(getLoginUserId())); + } + + /** * 获取距离进入公海的时间 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java index 8516ebd66..f29bc5139 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java @@ -144,4 +144,12 @@ public class CrmReceivableController { return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList); } + + @GetMapping("/check-receivables-count") + @Operation(summary = "获得待审核回款数量") + @PreAuthorize("@ss.hasPermission('crm:receivable:query')") + public CommonResult getCheckReceivablesCount() { + return success(receivableService.getCheckReceivablesCount(getLoginUserId())); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java index 252d714f4..6144ae6d3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java @@ -153,4 +153,12 @@ public class CrmReceivablePlanController { return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); } + + @GetMapping("/remind-receivable-plan-count") + @Operation(summary = "获得待回款提醒数量") + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") + public CommonResult getRemindReceivablesCount() { + return success(receivablePlanService.getRemindReceivablePlanCount(getLoginUserId())); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index cab4c4662..a60ecdbcc 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -53,4 +54,17 @@ public interface CrmClueMapper extends BaseMapperX { return selectJoinList(CrmClueDO.class, query); } + default Long getFollowLeadsCount(Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + + // 我负责的, 非公海 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), + CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + + // 未跟进, 未转化 + query.ne(CrmClueDO::getFollowUpStatus, true) + .ne(CrmClueDO::getTransformStatus, true); + + return selectCount(query); + } } 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 d553962ee..3f27400d1 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 @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR 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; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -90,4 +91,33 @@ public interface CrmContractMapper extends BaseMapperX { return selectCount(CrmContractDO::getBusinessId, businessId); } + default Long getCheckContractCount(Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + + // 我负责的, 非公海 + CrmQueryWrapperUtils.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()); + + return selectCount(query); + } + + default Long getEndContractCount(Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + + // 我负责的, 非公海 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), + CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + + // 即将到期 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); + int REMIND_DAYS = 20; + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) + .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); + + return selectCount(query); + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index da2ea92f3..8bfd9cb44 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -7,9 +7,11 @@ 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.customer.vo.CrmCustomerPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; @@ -29,6 +31,40 @@ import java.util.List; @Mapper public interface CrmCustomerMapper extends BaseMapperX { + private static MPJLambdaWrapperX buildPutInPoolRemindCustomerWrapper(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfigDO, Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); + + // 锁定状态不需要提醒 + query.ne(CrmCustomerDO::getLockStatus, true); + + // 情况一:未成交提醒日期区间 + Integer dealExpireDays = poolConfigDO.getDealExpireDays(); + LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) + .minusDays(dealExpireDays); + LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) + .minusDays(Math.max(dealExpireDays - poolConfigDO.getNotifyDays(), 0)); + // 情况二:未跟进提醒日期区间 + Integer contactExpireDays = poolConfigDO.getContactExpireDays(); + LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) + .minusDays(contactExpireDays); + LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) + .minusDays(Math.max(contactExpireDays - poolConfigDO.getNotifyDays(), 0)); + query + // 情况一:1. 未成交放入公海提醒 + .eq(CrmCustomerDO::getDealStatus, false) + .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate) + // 情况二:未跟进放入公海提醒 + .or() // 2.1 contactLastTime 为空 TODO 芋艿:这个要不要搞个默认值; + .isNull(CrmCustomerDO::getContactLastTime) + .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate) + .or() // 2.2 ContactLastTime 不为空 + .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate); + return query; + } + default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { return selectCount(new LambdaUpdateWrapper() .eq(CrmCustomerDO::getLockStatus, lockStatus) @@ -102,39 +138,42 @@ public interface CrmCustomerMapper extends BaseMapperX { default PageResult selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfigDO, Long userId) { - MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); - - // 锁定状态不需要提醒 - query.ne(CrmCustomerDO::getLockStatus, true); - - // 拼接自身的查询条件 - query.selectAll(CrmCustomerDO.class); - // 情况一:未成交提醒日期区间 - Integer dealExpireDays = poolConfigDO.getDealExpireDays(); - LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) - .minusDays(dealExpireDays); - LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) - .minusDays(Math.max(dealExpireDays - poolConfigDO.getNotifyDays(), 0)); - // 情况二:未跟进提醒日期区间 - Integer contactExpireDays = poolConfigDO.getContactExpireDays(); - LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) - .minusDays(contactExpireDays); - LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) - .minusDays(Math.max(contactExpireDays - poolConfigDO.getNotifyDays(), 0)); - query - // 情况一:1. 未成交放入公海提醒 - .eq(CrmCustomerDO::getDealStatus, false) - .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate) - // 情况二:未跟进放入公海提醒 - .or() // 2.1 contactLastTime 为空 TODO 芋艿:这个要不要搞个默认值; - .isNull(CrmCustomerDO::getContactLastTime) - .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate) - .or() // 2.2 ContactLastTime 不为空 - .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate); - return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); + final MPJLambdaWrapperX query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId); + return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class)); } + default Long selectPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, + CrmCustomerPoolConfigDO poolConfigDO, + Long userId) { + final MPJLambdaWrapperX query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId); + return selectCount(query); + } + + default Long getTodayCustomerCount(Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + + // 我负责的, 非公海 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + + // 今天需联系 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); + query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); + + return selectCount(query); + } + + default Long getFollowCustomerCount(Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + + // 我负责的, 非公海 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + + // 未跟进 + query.ne(CrmClueDO::getFollowUpStatus, true); + + return selectCount(query); + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index 28b2298ec..36345f01f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -5,8 +5,11 @@ 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.receivable.vo.receivable.CrmReceivablePageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -59,4 +62,17 @@ public interface CrmReceivableMapper extends BaseMapperX { return selectJoinList(CrmReceivableDO.class, query); } + default Long getCheckReceivablesCount(Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + + // 我负责的, 非公海 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), + CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + + // 未提交 or 审核不通过 + query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus()); + + return selectCount(query); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index 618a95750..780d611cb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -80,4 +81,19 @@ public interface CrmReceivablePlanMapper extends BaseMapperX query = new MPJLambdaWrapperX<>(); + + // 我负责的, 非公海 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), + CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + + // 待回款 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + query.isNull(CrmReceivablePlanDO::getReceivableId) + .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday) + .apply("to_days(return_time) <= to_days(now())+ remind_days"); + + return selectCount(query); + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 1472bf02f..6c37305c7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -90,4 +90,12 @@ public interface CrmClueService { */ void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId); + /** + * 获得分配给我的线索数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getFollowLeadsCount(Long userId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index dfb044f50..209b54fbc 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -276,4 +276,9 @@ public class CrmClueServiceImpl implements CrmClueService { return SpringUtil.getBean(getClass()); } + @Override + public Long getFollowLeadsCount(Long userId) { + return clueMapper.getFollowLeadsCount(userId); + } + } 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 3e79b73ed..919cc293c 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 @@ -134,4 +134,21 @@ public interface CrmContractService { */ Long getContractCountByBusinessId(Long businessId); + + /** + * 获得待审核合同数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getCheckContractCount(Long userId); + + /** + * 获得即将到期的合同数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getEndContractCount(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 4af609edd..4c7feb4a9 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 @@ -314,4 +314,15 @@ public class CrmContractServiceImpl implements CrmContractService { return contractMapper.selectCountByBusinessId(businessId); } // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; + + @Override + public Long getCheckContractCount(Long userId) { + return contractMapper.getCheckContractCount(userId); + } + + @Override + public Long getEndContractCount(Long userId) { + return contractMapper.getEndContractCount(userId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 259812e4b..31553f9c0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -141,7 +141,43 @@ public interface CrmCustomerService { */ int autoPutCustomerPool(); + /** + * 获得放入公海提醒的客户分页数据 + * + * @param pageVO 分页查询 + * @param poolConfigDO 公海配置 + * @param userId 用户编号 + * @return 客户分页 + */ PageResult getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, CrmCustomerPoolConfigDO poolConfigDO, - Long loginUserId); + Long userId); + + /** + * 获得今日需联系客户数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getTodayCustomerCount(Long userId); + + /** + * 获得待进入公海的客户数量 + * + * @param pageVO 分页查询 + * @param poolConfigDO 公海配置 + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageVO, + CrmCustomerPoolConfigDO poolConfigDO, + Long userId); + + /** + * 获得分配给我的客户数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getFollowCustomerCount(Long userId); } 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 eeea1efdf..26d144ea7 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 @@ -465,12 +465,30 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customerMapper.selectPage(pageReqVO, userId); } + @Override public PageResult getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfigDO, Long userId) { return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId); } + @Override + public Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, + CrmCustomerPoolConfigDO poolConfigDO, + Long userId) { + return customerMapper.selectPutInPoolRemindCustomerCount(pageReqVO, poolConfigDO, userId); + } + + @Override + public Long getTodayCustomerCount(Long userId) { + return customerMapper.getTodayCustomerCount(userId); + } + + @Override + public Long getFollowCustomerCount(Long userId) { + return customerMapper.getFollowCustomerCount(userId); + } + // ======================= 校验相关 ======================= /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java index ded059b28..ebc80f25c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java @@ -77,4 +77,11 @@ public interface CrmReceivablePlanService { */ PageResult getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO); + /** + * 获得待回款提醒数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getRemindReceivablePlanCount(Long userId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index 9ac2e7f43..88ba22e14 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -24,7 +24,6 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -163,4 +162,9 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { return receivablePlanMapper.selectPageByCustomerId(pageReqVO); } + @Override + public Long getRemindReceivablePlanCount(Long userId) { + return receivablePlanMapper.getRemindReceivablePlanCount(userId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java index 8e9cfa0ea..f92db6a4d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java @@ -78,4 +78,12 @@ public interface CrmReceivableService { */ PageResult getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO); + /** + * 获得待审核回款数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getCheckReceivablesCount(Long userId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index effe0d720..e931286d7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -27,7 +27,6 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -183,4 +182,9 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { return receivableMapper.selectPageByCustomerId(pageReqVO); } + @Override + public Long getCheckReceivablesCount(Long userId) { + return receivableMapper.getCheckReceivablesCount(userId); + } + } From 1ba2b7b60086373cf1700d24455797fda65db49a Mon Sep 17 00:00:00 2001 From: dhb52 Date: Sun, 18 Feb 2024 00:21:10 +0800 Subject: [PATCH 03/54] =?UTF-8?q?fix:=20Customer,Clue=E5=A2=9E=E5=8A=A0fol?= =?UTF-8?q?lowUpStatus=E8=87=AA=E5=8A=A8=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java | 3 +++ .../crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java | 3 +++ .../iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java | 1 + .../yudao/module/crm/dal/mysql/contract/CrmContractMapper.java | 1 + .../yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java | 3 ++- 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java index 3ba823d54..be8d30dbe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java @@ -39,4 +39,7 @@ public class CrmCluePageReqVO extends PageParam { @Schema(description = "客户来源", example = "1") private Integer source; + @Schema(description = "跟进状态", example = "true") + private Boolean followUpStatus; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java index c30a6af91..1fd2a1981 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java @@ -55,4 +55,7 @@ public class CrmCustomerPageReqVO extends PageParam { @Schema(description = "跟进状态", example = "true") private Boolean followUpStatus; // backlog查询条件, null 则表示为不做查询 + @Schema(description = "跟进状态", example = "true") + private Boolean followUpStatus; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index a60ecdbcc..9d5594d06 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -41,6 +41,7 @@ public interface CrmClueMapper extends BaseMapperX { .eqIfPresent(CrmClueDO::getIndustryId, pageReqVO.getIndustryId()) .eqIfPresent(CrmClueDO::getLevel, pageReqVO.getLevel()) .eqIfPresent(CrmClueDO::getSource, pageReqVO.getSource()) + .eqIfPresent(CrmClueDO::getFollowUpStatus, pageReqVO.getFollowUpStatus()) .orderByDesc(CrmClueDO::getId); return selectJoinPage(pageReqVO, CrmClueDO.class, query); } 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 7b4a7712e..4a842a2a0 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 @@ -6,6 +6,7 @@ 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.dal.dataobject.clue.CrmClueDO; 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; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 8bfd9cb44..c0507b3d3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -94,7 +94,8 @@ public interface CrmCustomerMapper extends BaseMapperX { .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile()) .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId()) .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel()) - .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()); + .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()) + .eqIfPresent(CrmCustomerDO::getFollowUpStatus, pageReqVO.getFollowUpStatus()); // backlog 查询 if (ObjUtil.isNotNull(pageReqVO.getContactStatus())) { From 9ea7bde7512459564886870043216d5ccbb2f2c5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 18 Feb 2024 19:05:40 +0800 Subject: [PATCH 04/54] =?UTF-8?q?=F0=9F=93=96=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E9=A6=96=E9=A1=B5=E7=9A=84=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/date/LocalDateTimeUtils.java | 36 ++++++++++ .../ErpPurchaseStatisticsController.java | 69 +++++++++++++++++++ .../ErpSaleStatisticsController.http | 11 +++ .../ErpSaleStatisticsController.java | 69 +++++++++++++++++++ .../vo/purchase/ErpPurchaseSummaryRespVO.java | 24 +++++++ .../ErpPurchaseTimeSummaryRespVO.java | 18 +++++ .../vo/sale/ErpSaleSummaryRespVO.java | 24 +++++++ .../vo/sale/ErpSaleTimeSummaryRespVO.java | 18 +++++ .../ErpPurchaseStatisticsMapper.java | 20 ++++++ .../statistics/ErpSaleStatisticsMapper.java | 20 ++++++ .../purchase/ErpPurchaseInServiceImpl.java | 2 +- .../ErpPurchaseReturnServiceImpl.java | 2 +- .../service/sale/ErpSaleOutServiceImpl.java | 2 +- .../sale/ErpSaleReturnServiceImpl.java | 2 +- .../ErpPurchaseStatisticsService.java | 24 +++++++ .../ErpPurchaseStatisticsServiceImpl.java | 26 +++++++ .../statistics/ErpSaleStatisticsService.java | 24 +++++++ .../ErpSaleStatisticsServiceImpl.java | 26 +++++++ .../mapper/finance/ErpAccountMapper.xml | 12 ---- .../mapper/product/ErpProductUnitMapper.xml | 12 ---- .../mapper/sale/ErpCustomerMapper.xml | 12 ---- .../ErpPurchaseStatisticsMapper.xml | 23 +++++++ .../statistics/ErpSaleStatisticsMapper.xml | 23 +++++++ .../mapper/stock/ErpWarehouseMapper.xml | 12 ---- .../mapper/supplier/ErpSupplierMapper.xml | 12 ---- .../member/MemberStatisticsController.java | 7 -- .../infra/ApiAccessLogStatisticsMapper.java | 2 - .../mysql/member/MemberStatisticsMapper.java | 5 -- .../mysql/pay/PayWalletStatisticsMapper.java | 5 -- .../trade/AfterSaleStatisticsMapper.java | 2 - .../trade/BrokerageStatisticsMapper.java | 2 - .../trade/TradeOrderStatisticsMapper.java | 10 --- .../mysql/trade/TradeStatisticsMapper.java | 3 - .../infra/ApiAccessLogStatisticsService.java | 2 - .../member/MemberStatisticsService.java | 6 -- .../pay/PayWalletStatisticsService.java | 3 - .../trade/AfterSaleStatisticsService.java | 2 - .../trade/BrokerageStatisticsService.java | 2 - .../trade/TradeOrderStatisticsService.java | 6 -- .../service/trade/TradeStatisticsService.java | 3 - yudao-server/pom.xml | 10 +-- 41 files changed, 464 insertions(+), 129 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpPurchaseStatisticsController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.http create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseSummaryRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseTimeSummaryRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleSummaryRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleTimeSummaryRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpPurchaseStatisticsMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpSaleStatisticsMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsServiceImpl.java delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 59656cbdd..87c20798e 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -132,4 +132,40 @@ public class LocalDateTimeUtils { return LocalDateTimeUtil.between(dateTime, LocalDateTime.now(), ChronoUnit.DAYS); } + /** + * 获取今天的开始时间 + * + * @return 今天 + */ + public static LocalDateTime getToday() { + return LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + } + + /** + * 获取昨天的开始时间 + * + * @return 昨天 + */ + public static LocalDateTime getYesterday() { + return LocalDateTimeUtil.beginOfDay(LocalDateTime.now().minusDays(1)); + } + + /** + * 获取本月的开始时间 + * + * @return 本月 + */ + public static LocalDateTime getMonth() { + return beginOfMonth(LocalDateTime.now()); + } + + /** + * 获取本年的开始时间 + * + * @return 本年 + */ + public static LocalDateTime getYear() { + return LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN); + } + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpPurchaseStatisticsController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpPurchaseStatisticsController.java new file mode 100644 index 000000000..5e0657a75 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpPurchaseStatisticsController.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.erp.controller.admin.statistics; + +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.purchase.ErpPurchaseSummaryRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.purchase.ErpPurchaseTimeSummaryRespVO; +import cn.iocoder.yudao.module.erp.service.statistics.ErpPurchaseStatisticsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static cn.hutool.core.date.DatePattern.NORM_MONTH_PATTERN; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - ERP 采购统计") +@RestController +@RequestMapping("/erp/purchase-statistics") +@Validated +public class ErpPurchaseStatisticsController { + + @Resource + private ErpPurchaseStatisticsService purchaseStatisticsService; + + @GetMapping("/summary") + @Operation(summary = "获得采购统计") + @PreAuthorize("@ss.hasPermission('erp:statistics:query')") + public CommonResult getPurchaseSummary() { + LocalDateTime today = LocalDateTimeUtils.getToday(); + LocalDateTime yesterday = LocalDateTimeUtils.getYesterday(); + LocalDateTime month = LocalDateTimeUtils.getMonth(); + LocalDateTime year = LocalDateTimeUtils.getYear(); + ErpPurchaseSummaryRespVO summary = new ErpPurchaseSummaryRespVO() + .setTodayPrice(purchaseStatisticsService.getPurchasePrice(today, null)) + .setYesterdayPrice(purchaseStatisticsService.getPurchasePrice(yesterday, today)) + .setMonthPrice(purchaseStatisticsService.getPurchasePrice(month, null)) + .setYearPrice(purchaseStatisticsService.getPurchasePrice(year, null)); + return success(summary); + } + + @GetMapping("/time-summary") + @Operation(summary = "获得采购时间段统计") + @Parameter(name = "count", description = "时间段数量", example = "6") + @PreAuthorize("@ss.hasPermission('erp:statistics:query')") + public CommonResult> getPurchaseTimeSummary( + @RequestParam(value = "count", defaultValue = "6") Integer count) { + List summaryList = new ArrayList<>(); + for (int i = count - 1; i >= 0; i--) { + LocalDateTime startTime = LocalDateTimeUtils.beginOfMonth(LocalDateTime.now().minusMonths(i)); + LocalDateTime endTime = LocalDateTimeUtils.endOfMonth(startTime); + summaryList.add(new ErpPurchaseTimeSummaryRespVO() + .setTime(LocalDateTimeUtil.format(startTime, NORM_MONTH_PATTERN)) + .setPrice(purchaseStatisticsService.getPurchasePrice(startTime, endTime))); + } + return success(summaryList); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.http b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.http new file mode 100644 index 000000000..5f5cab109 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.http @@ -0,0 +1,11 @@ +### 请求 /erp/sale-statistics/summary 接口 => 成功 +GET {{baseUrl}}/erp/sale-statistics/summary +Content-Type: application/json +tenant-id: {{adminTenentId}} +Authorization: Bearer {{token}} + +### 请求 /erp/sale-statistics/time-summary 接口 => 成功 +GET {{baseUrl}}/erp/sale-statistics/time-summary +Content-Type: application/json +tenant-id: {{adminTenentId}} +Authorization: Bearer {{token}} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.java new file mode 100644 index 000000000..3fcaf22e9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/ErpSaleStatisticsController.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.erp.controller.admin.statistics; + +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale.ErpSaleSummaryRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale.ErpSaleTimeSummaryRespVO; +import cn.iocoder.yudao.module.erp.service.statistics.ErpSaleStatisticsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static cn.hutool.core.date.DatePattern.NORM_MONTH_PATTERN; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - ERP 销售统计") +@RestController +@RequestMapping("/erp/sale-statistics") +@Validated +public class ErpSaleStatisticsController { + + @Resource + private ErpSaleStatisticsService saleStatisticsService; + + @GetMapping("/summary") + @Operation(summary = "获得销售统计") + @PreAuthorize("@ss.hasPermission('erp:statistics:query')") + public CommonResult getSaleSummary() { + LocalDateTime today = LocalDateTimeUtils.getToday(); + LocalDateTime yesterday = LocalDateTimeUtils.getYesterday(); + LocalDateTime month = LocalDateTimeUtils.getMonth(); + LocalDateTime year = LocalDateTimeUtils.getYear(); + ErpSaleSummaryRespVO summary = new ErpSaleSummaryRespVO() + .setTodayPrice(saleStatisticsService.getSalePrice(today, null)) + .setYesterdayPrice(saleStatisticsService.getSalePrice(yesterday, today)) + .setMonthPrice(saleStatisticsService.getSalePrice(month, null)) + .setYearPrice(saleStatisticsService.getSalePrice(year, null)); + return success(summary); + } + + @GetMapping("/time-summary") + @Operation(summary = "获得销售时间段统计") + @Parameter(name = "count", description = "时间段数量", example = "6") + @PreAuthorize("@ss.hasPermission('erp:statistics:query')") + public CommonResult> getSaleTimeSummary( + @RequestParam(value = "count", defaultValue = "6") Integer count) { + List summaryList = new ArrayList<>(); + for (int i = count - 1; i >= 0; i--) { + LocalDateTime startTime = LocalDateTimeUtils.beginOfMonth(LocalDateTime.now().minusMonths(i)); + LocalDateTime endTime = LocalDateTimeUtils.endOfMonth(startTime); + summaryList.add(new ErpSaleTimeSummaryRespVO() + .setTime(LocalDateTimeUtil.format(startTime, NORM_MONTH_PATTERN)) + .setPrice(saleStatisticsService.getSalePrice(startTime, endTime))); + } + return success(summaryList); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseSummaryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseSummaryRespVO.java new file mode 100644 index 000000000..22635e745 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseSummaryRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.purchase; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 采购全局统计 Response VO") +@Data +public class ErpPurchaseSummaryRespVO { + + @Schema(description = "今日采购金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private BigDecimal todayPrice; + + @Schema(description = "昨日采购金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + private BigDecimal yesterdayPrice; + + @Schema(description = "本月采购金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private BigDecimal monthPrice; + + @Schema(description = "今年采购金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "88888") + private BigDecimal yearPrice; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseTimeSummaryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseTimeSummaryRespVO.java new file mode 100644 index 000000000..15ae817de --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/purchase/ErpPurchaseTimeSummaryRespVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.purchase; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 采购某个时间段的统计 Response VO") +@Data +public class ErpPurchaseTimeSummaryRespVO { + + @Schema(description = "时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022-03") + private String time; + + @Schema(description = "采购金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private BigDecimal price; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleSummaryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleSummaryRespVO.java new file mode 100644 index 000000000..575d7da5e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleSummaryRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 销售全局统计 Response VO") +@Data +public class ErpSaleSummaryRespVO { + + @Schema(description = "今日销售金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private BigDecimal todayPrice; + + @Schema(description = "昨日销售金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + private BigDecimal yesterdayPrice; + + @Schema(description = "本月销售金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private BigDecimal monthPrice; + + @Schema(description = "今年销售金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "88888") + private BigDecimal yearPrice; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleTimeSummaryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleTimeSummaryRespVO.java new file mode 100644 index 000000000..48b9b6e9a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/statistics/vo/sale/ErpSaleTimeSummaryRespVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 销售某个时间段的统计 Response VO") +@Data +public class ErpSaleTimeSummaryRespVO { + + @Schema(description = "时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022-03") + private String time; + + @Schema(description = "销售金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private BigDecimal price; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpPurchaseStatisticsMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpPurchaseStatisticsMapper.java new file mode 100644 index 000000000..14b4e517b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpPurchaseStatisticsMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.statistics; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 采购统计 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseStatisticsMapper { + + BigDecimal getPurchasePrice(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpSaleStatisticsMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpSaleStatisticsMapper.java new file mode 100644 index 000000000..b29f1944d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/statistics/ErpSaleStatisticsMapper.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.statistics; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 销售统计 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleStatisticsMapper { + + BigDecimal getSalePrice(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java index 5d6ad6230..8a521d5ac 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -164,7 +164,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL); } // 1.3 校验已付款 - if (approve && purchaseIn.getPaymentPrice().compareTo(BigDecimal.ZERO) > 0) { + if (!approve && purchaseIn.getPaymentPrice().compareTo(BigDecimal.ZERO) > 0) { throw exception(PURCHASE_IN_PROCESS_FAIL_EXISTS_PAYMENT); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java index 05960e896..9403c0b14 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java @@ -160,7 +160,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL); } // 1.3 校验已退款 - if (approve && purchaseReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { + if (!approve && purchaseReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { throw exception(PURCHASE_RETURN_PROCESS_FAIL_EXISTS_REFUND); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index d930c16bf..5f3566ae6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -172,7 +172,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { throw exception(approve ? SALE_OUT_APPROVE_FAIL : SALE_OUT_PROCESS_FAIL); } // 1.3 校验已退款 - if (approve && saleOut.getReceiptPrice().compareTo(BigDecimal.ZERO) > 0) { + if (!approve && saleOut.getReceiptPrice().compareTo(BigDecimal.ZERO) > 0) { throw exception(SALE_OUT_PROCESS_FAIL_EXISTS_RECEIPT); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index 85d798e72..61a6fe1c4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -172,7 +172,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { throw exception(approve ? SALE_RETURN_APPROVE_FAIL : SALE_RETURN_PROCESS_FAIL); } // 1.3 校验已退款 - if (approve && saleReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { + if (!approve && saleReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { throw exception(SALE_RETURN_PROCESS_FAIL_EXISTS_REFUND); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsService.java new file mode 100644 index 000000000..913409487 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsService.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.service.statistics; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 采购统计 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpPurchaseStatisticsService { + + /** + * 获得采购金额 + * + * 计算逻辑:采购出库的金额 - 采购退货的金额 + * + * @param beginTime >= 开始时间 + * @param endTime < 结束时间 + * @return 采购金额 + */ + BigDecimal getPurchasePrice(LocalDateTime beginTime, LocalDateTime endTime); + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsServiceImpl.java new file mode 100644 index 000000000..b7a8be2a8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpPurchaseStatisticsServiceImpl.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp.service.statistics; + +import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpPurchaseStatisticsMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 采购统计 Service 实现类 + * + * @author 芋道源码 + */ +@Service +public class ErpPurchaseStatisticsServiceImpl implements ErpPurchaseStatisticsService { + + @Resource + private ErpPurchaseStatisticsMapper purchaseStatisticsMapper; + + @Override + public BigDecimal getPurchasePrice(LocalDateTime beginTime, LocalDateTime endTime) { + return purchaseStatisticsMapper.getPurchasePrice(beginTime, endTime); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsService.java new file mode 100644 index 000000000..3c28bc327 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsService.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.service.statistics; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 销售统计 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSaleStatisticsService { + + /** + * 获得销售金额 + * + * 计算逻辑:销售出库的金额 - 销售退货的金额 + * + * @param beginTime >= 开始时间 + * @param endTime < 结束时间 + * @return 销售金额 + */ + BigDecimal getSalePrice(LocalDateTime beginTime, LocalDateTime endTime); + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsServiceImpl.java new file mode 100644 index 000000000..c487bf53e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/statistics/ErpSaleStatisticsServiceImpl.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp.service.statistics; + +import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpSaleStatisticsMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 销售统计 Service 实现类 + * + * @author 芋道源码 + */ +@Service +public class ErpSaleStatisticsServiceImpl implements ErpSaleStatisticsService { + + @Resource + private ErpSaleStatisticsMapper saleStatisticsMapper; + + @Override + public BigDecimal getSalePrice(LocalDateTime beginTime, LocalDateTime endTime) { + return saleStatisticsMapper.getSalePrice(beginTime, endTime); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml deleted file mode 100644 index a3cf6877b..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml deleted file mode 100644 index 4666e48d4..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml deleted file mode 100644 index c012f4467..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml new file mode 100644 index 000000000..e2b25992a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml new file mode 100644 index 000000000..8e74606c9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml deleted file mode 100644 index be2bc61cb..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml deleted file mode 100644 index 54849af3f..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java index ec2192608..b89bc4d3f 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java @@ -39,7 +39,6 @@ public class MemberStatisticsController { @Resource private ApiAccessLogStatisticsService apiAccessLogStatisticsService; - // TODO 芋艿:已经 review @GetMapping("/summary") @Operation(summary = "获得会员统计(实时统计)") @PreAuthorize("@ss.hasPermission('statistics:member:query')") @@ -47,7 +46,6 @@ public class MemberStatisticsController { return success(memberStatisticsService.getMemberSummary()); } - // TODO 芋艿:已经 review @GetMapping("/analyse") @Operation(summary = "获得会员分析数据") @PreAuthorize("@ss.hasPermission('statistics:member:query')") @@ -76,7 +74,6 @@ public class MemberStatisticsController { return success(MemberStatisticsConvert.INSTANCE.convert(visitUserCount, orderUserCount, payUserCount, atv, comparisonData)); } - // TODO 芋艿:已经 review @GetMapping("/area-statistics-list") @Operation(summary = "按照省份,获得会员统计列表") @PreAuthorize("@ss.hasPermission('statistics:member:query')") @@ -84,7 +81,6 @@ public class MemberStatisticsController { return success(memberStatisticsService.getMemberAreaStatisticsList()); } - // TODO 芋艿:已经 review @GetMapping("/sex-statistics-list") @Operation(summary = "按照性别,获得会员统计列表") @PreAuthorize("@ss.hasPermission('statistics:member:query')") @@ -92,7 +88,6 @@ public class MemberStatisticsController { return success(memberStatisticsService.getMemberSexStatisticsList()); } - // TODO 芋艿:已经 review @GetMapping("/terminal-statistics-list") @Operation(summary = "按照终端,获得会员统计列表") @PreAuthorize("@ss.hasPermission('statistics:member:query')") @@ -100,7 +95,6 @@ public class MemberStatisticsController { return success(memberStatisticsService.getMemberTerminalStatisticsList()); } - // TODO 芋艿:已经 review // TODO @疯狂:要注意 date 的排序; @GetMapping("/user-count-comparison") @Operation(summary = "获得用户数量对照") @@ -109,7 +103,6 @@ public class MemberStatisticsController { return success(memberStatisticsService.getUserCountComparison()); } - // TODO 芋艿:已经 review @GetMapping("/register-count-list") @Operation(summary = "获得会员注册数量列表") @PreAuthorize("@ss.hasPermission('statistics:member:query')") diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java index cf7f98a0e..5f76b58fd 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java @@ -16,12 +16,10 @@ import java.time.LocalDateTime; @SuppressWarnings("rawtypes") public interface ApiAccessLogStatisticsMapper extends BaseMapperX { - // TODO 芋艿:已经 review Integer selectIpCountByUserTypeAndCreateTimeBetween(@Param("userType") Integer userType, @Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review Integer selectUserCountByUserTypeAndCreateTimeBetween(@Param("userType") Integer userType, @Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java index 1d215b818..595e93d9e 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java @@ -20,20 +20,15 @@ import java.util.List; @SuppressWarnings("rawtypes") public interface MemberStatisticsMapper extends BaseMapperX { - // TODO @芋艿:已经 review List selectSummaryListByAreaId(); - // TODO @芋艿:已经 review List selectSummaryListBySex(); - // TODO @芋艿:已经 review List selectSummaryListByRegisterTerminal(); - // TODO @芋艿:已经 review Integer selectUserCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO @芋艿:已经 review /** * 获得用户的每天注册数量列表 * diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java index 90ab0e0c6..b9b38fbbe 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java @@ -17,27 +17,22 @@ import java.time.LocalDateTime; @SuppressWarnings("rawtypes") public interface PayWalletStatisticsMapper extends BaseMapperX { - // TODO 芋艿:已经 review; WalletSummaryRespBO selectRechargeSummaryByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime, @Param("payStatus") Boolean payStatus); - // TODO 芋艿:已经 review; WalletSummaryRespBO selectRechargeSummaryByRefundTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime, @Param("refundStatus") Integer refundStatus); - // TODO 芋艿:已经 review; Integer selectPriceSummaryByBizTypeAndCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime, @Param("bizType") Integer bizType); - // TODO 芋艿:已经 review; RechargeSummaryRespBO selectRechargeSummaryGroupByWalletId(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime, @Param("payStatus") Boolean payStatus); - // TODO 芋艿:已经 review; Integer selectRechargePriceSummary(@Param("payStatus") Integer payStatus); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/AfterSaleStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/AfterSaleStatisticsMapper.java index 1d2bb8814..7de0cb07b 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/AfterSaleStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/AfterSaleStatisticsMapper.java @@ -16,11 +16,9 @@ import java.time.LocalDateTime; @Mapper public interface AfterSaleStatisticsMapper extends BaseMapperX { - // TODO 芋艿:已 review AfterSaleSummaryRespBO selectSummaryByRefundTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review Long selectCountByStatus(@Param("status") Integer status); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/BrokerageStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/BrokerageStatisticsMapper.java index 46d651a75..94ad06812 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/BrokerageStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/BrokerageStatisticsMapper.java @@ -15,13 +15,11 @@ import java.time.LocalDateTime; @Mapper public interface BrokerageStatisticsMapper extends BaseMapperX { - // TODO 芋艿:已经 review Integer selectSummaryPriceByStatusAndUnfreezeTimeBetween(@Param("bizType") Integer bizType, @Param("status") Integer status, @Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review Long selectWithdrawCountByStatus(@Param("status") Integer status); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeOrderStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeOrderStatisticsMapper.java index 43b4c4dfd..1d7ffb644 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeOrderStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeOrderStatisticsMapper.java @@ -19,30 +19,23 @@ import java.util.List; @Mapper public interface TradeOrderStatisticsMapper extends BaseMapperX { - // TODO 芋艿:已经 review List selectSummaryListByAreaId(); - // TODO 芋艿:已经 review Integer selectCountByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review Integer selectCountByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review Integer selectSummaryPriceByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review Integer selectUserCountByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review Integer selectUserCountByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 按照支付时间统计订单(按天分组) * @@ -53,7 +46,6 @@ public interface TradeOrderStatisticsMapper extends BaseMapperX selectListByPayTimeBetweenAndGroupByDay(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 按照支付时间统计订单(按月分组) * @@ -64,10 +56,8 @@ public interface TradeOrderStatisticsMapper extends BaseMapperX selectListByPayTimeBetweenAndGroupByMonth(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO @芋艿:已经 review Long selectCountByStatusAndDeliveryType(@Param("status") Integer status, @Param("deliveryType") Integer deliveryType); - // TODO 芋艿:已经 review TradeOrderSummaryRespVO selectPaySummaryByStatusAndPayTimeBetween(@Param("status") Integer status, @Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java index d5ed54cec..67d2d5007 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java @@ -25,17 +25,14 @@ public interface TradeStatisticsMapper extends BaseMapperX { TradeTrendSummaryRespVO selectVoByTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO @芋艿:已经 review default List selectListByTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { return selectList(new LambdaQueryWrapperX() .between(TradeStatisticsDO::getTime, beginTime, endTime)); } - // TODO @芋艿:已经 review Integer selectExpensePriceByTimeBetween(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); - // TODO @芋艿:已经 review default TradeStatisticsDO selectByTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { return selectOne(new LambdaQueryWrapperX() .between(TradeStatisticsDO::getTime, beginTime, endTime)); diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java index f4042730b..6c200fdef 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java @@ -9,7 +9,6 @@ import java.time.LocalDateTime; */ public interface ApiAccessLogStatisticsService { - // TODO 芋艿:已经 review /** * 获取活跃用户数量 * @@ -20,7 +19,6 @@ public interface ApiAccessLogStatisticsService { */ Integer getUserCount(Integer userType, LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取访问用户数量 * diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java index 324905e59..253cba68a 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java @@ -13,7 +13,6 @@ import java.util.List; */ public interface MemberStatisticsService { - // TODO 芋艿:已经 review /** * 获取会员统计(实时统计) * @@ -21,7 +20,6 @@ public interface MemberStatisticsService { */ MemberSummaryRespVO getMemberSummary(); - // TODO 芋艿:已经 review /** * 获取会员分析对照数据 * @@ -32,7 +30,6 @@ public interface MemberStatisticsService { DataComparisonRespVO getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 按照省份,获得会员统计列表 * @@ -40,7 +37,6 @@ public interface MemberStatisticsService { */ List getMemberAreaStatisticsList(); - // TODO 芋艿:已经 review /** * 按照性别,获得会员统计列表 * @@ -55,7 +51,6 @@ public interface MemberStatisticsService { */ List getMemberTerminalStatisticsList(); - // TODO 芋艿:已经 review /** * 获取用户注册数量列表 * @@ -65,7 +60,6 @@ public interface MemberStatisticsService { */ List getMemberRegisterCountList(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获得用户数量量统计对照 * diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java index 4801ad186..d43a57682 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java @@ -12,7 +12,6 @@ import java.time.LocalDateTime; */ public interface PayWalletStatisticsService { - // TODO 芋艿:已经 review /** * 获取钱包统计 * @@ -22,7 +21,6 @@ public interface PayWalletStatisticsService { */ WalletSummaryRespBO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取钱包充值统计 * @@ -32,7 +30,6 @@ public interface PayWalletStatisticsService { */ RechargeSummaryRespBO getUserRechargeSummary(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取充值金额合计 * diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java index 3904387d6..f584c3dc7 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java @@ -12,7 +12,6 @@ import java.time.LocalDateTime; */ public interface AfterSaleStatisticsService { - // TODO 芋艿:已经 review /** * 获取售后单统计 * @@ -22,7 +21,6 @@ public interface AfterSaleStatisticsService { */ AfterSaleSummaryRespBO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取指定状态的售后订单数量 * diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java index 5f856778d..6845b608a 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java @@ -11,7 +11,6 @@ import java.time.LocalDateTime; */ public interface BrokerageStatisticsService { - // TODO 芋艿:已经 review /** * 获取已结算的佣金金额 * @@ -21,7 +20,6 @@ public interface BrokerageStatisticsService { */ Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取指定状态的提现记录数量 * diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java index 982957e24..2197515c4 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java @@ -24,7 +24,6 @@ public interface TradeOrderStatisticsService { */ TradeOrderSummaryRespBO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取地区订单统计 * @@ -32,7 +31,6 @@ public interface TradeOrderStatisticsService { */ List getSummaryListByAreaId(); - // TODO 芋艿:已经 review /** * 获取下单用户数量 * @@ -42,7 +40,6 @@ public interface TradeOrderStatisticsService { */ Integer getOrderUserCount(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取支付用户数量 * @@ -52,7 +49,6 @@ public interface TradeOrderStatisticsService { */ Integer getPayUserCount(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review /** * 获取支付金额 * @@ -69,7 +65,6 @@ public interface TradeOrderStatisticsService { */ Long getCountByStatusAndDeliveryType(Integer status, Integer deliveryType); - // TODO 芋艿:已经 review /** * 交易订单销售额对照 * @@ -77,7 +72,6 @@ public interface TradeOrderStatisticsService { */ DataComparisonRespVO getOrderComparison(); - // TODO 芋艿:已经 review /** * 获得订单量趋势统计 * diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java index 225bccf9f..e175985fb 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java @@ -41,7 +41,6 @@ public interface TradeStatisticsService { */ List getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime); - // TODO 芋艿:已经 review; /** * 统计指定天数的交易数据 * @@ -49,7 +48,6 @@ public interface TradeStatisticsService { */ String statisticsTrade(Integer days); - // TODO 芋艿:已经 review /** * 统计指定日期的交易数据 * @@ -58,7 +56,6 @@ public interface TradeStatisticsService { */ TradeSummaryRespBO getTradeSummaryByDays(int days); - // TODO 芋艿:已经 review /** * 统计指定月份的交易数据 * diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 4ead0bba8..ff17b298d 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -88,11 +88,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-crm-biz + ${revision} + From 4bf4432f937fdf593c745709a0d729c2c7d34f06 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 18 Feb 2024 21:11:43 +0800 Subject: [PATCH 05/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=8D=95?= =?UTF-8?q?=E6=B5=8B=E6=9A=82=E6=97=B6=E4=B8=8D=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BusinessStatusTypeServiceImplTest.java | 119 ---------- .../business/CrmBusinessServiceImplTest.java | 181 --------------- .../service/clue/CrmClueServiceImplTest.java | 207 ------------------ .../contract/ContractServiceImplTest.java | 135 ------------ .../customer/CrmCustomerServiceImplTest.java | 141 ------------ ...CrmCustomerLimitConfigServiceImplTest.java | 119 ---------- .../CrmCrmReceivablePlanServiceImplTest.java | 137 ------------ .../CrmCrmReceivableServiceImplTest.java | 143 ------------ 8 files changed, 1182 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/BusinessStatusTypeServiceImplTest.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customerlimitconfig/CrmCustomerLimitConfigServiceImplTest.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/BusinessStatusTypeServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/BusinessStatusTypeServiceImplTest.java deleted file mode 100644 index 3c039f644..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/BusinessStatusTypeServiceImplTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import jakarta.annotation.Resource; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -// TODO 芋艿:后续再 review -/** - * {@link CrmBusinessStatusTypeServiceImpl} 的单元测试类 - * - * @author ljlleo - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(CrmBusinessStatusTypeServiceImpl.class) -public class BusinessStatusTypeServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmBusinessStatusTypeServiceImpl businessStatusTypeService; - - @Resource - private CrmBusinessStatusTypeMapper businessStatusTypeMapper; - - @Test - public void testCreateBusinessStatusType_success() { - // 准备参数 - CrmBusinessStatusTypeSaveReqVO createReqVO = randomPojo(CrmBusinessStatusTypeSaveReqVO.class).setId(null); - - // 调用 - Long businessStatusTypeId = businessStatusTypeService.createBusinessStatusType(createReqVO); - // 断言 - assertNotNull(businessStatusTypeId); - // 校验记录的属性是否正确 - CrmBusinessStatusTypeDO businessStatusType = businessStatusTypeMapper.selectById(businessStatusTypeId); - assertPojoEquals(createReqVO, businessStatusType, "id"); - } - - @Test - public void testUpdateBusinessStatusType_success() { - // mock 数据 - CrmBusinessStatusTypeDO dbBusinessStatusType = randomPojo(CrmBusinessStatusTypeDO.class); - businessStatusTypeMapper.insert(dbBusinessStatusType);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmBusinessStatusTypeSaveReqVO updateReqVO = randomPojo(CrmBusinessStatusTypeSaveReqVO.class, o -> { - o.setId(dbBusinessStatusType.getId()); // 设置更新的 ID - }); - - // 调用 - businessStatusTypeService.updateBusinessStatusType(updateReqVO); - // 校验是否更新正确 - CrmBusinessStatusTypeDO businessStatusType = businessStatusTypeMapper.selectById(updateReqVO.getId()); // 获取最新的 - assertPojoEquals(updateReqVO, businessStatusType); - } - - @Test - public void testUpdateBusinessStatusType_notExists() { - // 准备参数 - CrmBusinessStatusTypeSaveReqVO updateReqVO = randomPojo(CrmBusinessStatusTypeSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> businessStatusTypeService.updateBusinessStatusType(updateReqVO), BUSINESS_STATUS_TYPE_NOT_EXISTS); - } - - @Test - public void testDeleteBusinessStatusType_success() { - // mock 数据 - CrmBusinessStatusTypeDO dbBusinessStatusType = randomPojo(CrmBusinessStatusTypeDO.class); - businessStatusTypeMapper.insert(dbBusinessStatusType);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbBusinessStatusType.getId(); - - // 调用 - businessStatusTypeService.deleteBusinessStatusType(id); - // 校验数据不存在了 - assertNull(businessStatusTypeMapper.selectById(id)); - } - - @Test - public void testDeleteBusinessStatusType_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> businessStatusTypeService.deleteBusinessStatusType(id), BUSINESS_STATUS_TYPE_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetBusinessStatusTypePage() { - // mock 数据 - CrmBusinessStatusTypeDO dbBusinessStatusType = randomPojo(CrmBusinessStatusTypeDO.class, o -> { // 等会查询到 - }); - businessStatusTypeMapper.insert(dbBusinessStatusType); - // 准备参数 - CrmBusinessStatusTypePageReqVO reqVO = new CrmBusinessStatusTypePageReqVO(); - - // 调用 - PageResult pageResult = businessStatusTypeService.getBusinessStatusTypePage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbBusinessStatusType, pageResult.getList().get(0)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java deleted file mode 100644 index 0fd3c447f..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java +++ /dev/null @@ -1,181 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; - -/** - * {@link CrmBusinessServiceImpl} 的单元测试类 - * - * @author ljlleo - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(CrmBusinessServiceImpl.class) -public class CrmBusinessServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmBusinessServiceImpl businessService; - - @Resource - private CrmBusinessMapper businessMapper; - - @Test - public void testCreateBusiness_success() { - // 准备参数 - CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class); - - // 调用 - Long businessId = businessService.createBusiness(reqVO, getLoginUserId()); - // 断言 - assertNotNull(businessId); - // 校验记录的属性是否正确 - CrmBusinessDO business = businessMapper.selectById(businessId); - assertPojoEquals(reqVO, business); - } - - @Test - public void testUpdateBusiness_success() { - // mock 数据 - CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class); - businessMapper.insert(dbBusiness);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class, o -> { - o.setId(dbBusiness.getId()); // 设置更新的 ID - }); - - // 调用 - businessService.updateBusiness(reqVO); - // 校验是否更新正确 - CrmBusinessDO business = businessMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, business); - } - - @Test - public void testUpdateBusiness_notExists() { - // 准备参数 - CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> businessService.updateBusiness(reqVO), BUSINESS_NOT_EXISTS); - } - - @Test - public void testDeleteBusiness_success() { - // mock 数据 - CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class); - businessMapper.insert(dbBusiness);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbBusiness.getId(); - - // 调用 - businessService.deleteBusiness(id); - // 校验数据不存在了 - assertNull(businessMapper.selectById(id)); - } - - @Test - public void testDeleteBusiness_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> businessService.deleteBusiness(id), BUSINESS_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetBusinessPage() { - // mock 数据 - CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class, o -> { // 等会查询到 - o.setName(null); - o.setStatusTypeId(null); - o.setStatusId(null); - o.setContactNextTime(null); - o.setCustomerId(null); - o.setDealTime(null); - o.setPrice(null); - o.setDiscountPercent(null); - o.setProductPrice(null); - o.setRemark(null); - o.setCreateTime(null); - o.setEndStatus(null); - o.setEndRemark(null); - o.setContactLastTime(null); - o.setFollowUpStatus(null); - }); - businessMapper.insert(dbBusiness); - // 测试 name 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setName(null))); - // 测试 statusTypeId 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setStatusTypeId(null))); - // 测试 statusId 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setStatusId(null))); - // 测试 contactNextTime 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setContactNextTime(null))); - // 测试 customerId 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setCustomerId(null))); - // 测试 dealTime 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setDealTime(null))); - // 测试 price 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setPrice(null))); - // 测试 discountPercent 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setDiscountPercent(null))); - // 测试 productPrice 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setProductPrice(null))); - // 测试 remark 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setRemark(null))); - // 测试 createTime 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setCreateTime(null))); - // 测试 endStatus 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setEndStatus(null))); - // 测试 endRemark 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setEndRemark(null))); - // 测试 contactLastTime 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setContactLastTime(null))); - // 测试 followUpStatus 不匹配 - businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setFollowUpStatus(null))); - //// 准备参数 - //CrmBusinessPageReqVO reqVO = new CrmBusinessPageReqVO(); - //reqVO.setName(null); - //reqVO.setStatusTypeId(null); - //reqVO.setStatusId(null); - //reqVO.setContactNextTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - //reqVO.setCustomerId(null); - //reqVO.setDealTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - //reqVO.setPrice(null); - //reqVO.setDiscountPercent(null); - //reqVO.setProductPrice(null); - //reqVO.setRemark(null); - //reqVO.setOwnerUserId(null); - //reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - //reqVO.setRoUserIds(null); - //reqVO.setRwUserIds(null); - //reqVO.setEndStatus(null); - //reqVO.setEndRemark(null); - //reqVO.setContactLastTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - //reqVO.setFollowUpStatus(null); - // - //// 调用 - //PageResult pageResult = businessService.getBusinessPage(reqVO); - //// 断言 - //assertEquals(1, pageResult.getTotal()); - //assertEquals(1, pageResult.getList().size()); - //assertPojoEquals(dbBusiness, pageResult.getList().get(0)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java deleted file mode 100644 index d73921f3d..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java +++ /dev/null @@ -1,207 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.clue; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; -import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -// TODO 芋艿:单测后续补; - -/** - * {@link CrmClueServiceImpl} 的单元测试类 - * - * @author Wanwan - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(CrmClueServiceImpl.class) -public class CrmClueServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmClueServiceImpl clueService; - - @Resource - private CrmClueMapper clueMapper; - - @Test - public void testCreateClue_success() { - // 准备参数 - CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class); - - // 调用 - Long clueId = clueService.createClue(reqVO, getLoginUserId()); - // 断言 - assertNotNull(clueId); - // 校验记录的属性是否正确 - CrmClueDO clue = clueMapper.selectById(clueId); - assertPojoEquals(reqVO, clue); - } - - @Test - public void testUpdateClue_success() { - // mock 数据 - CrmClueDO dbClue = randomPojo(CrmClueDO.class); - clueMapper.insert(dbClue);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class, o -> { - o.setId(dbClue.getId()); // 设置更新的 ID - }); - - // 调用 - clueService.updateClue(reqVO); - // 校验是否更新正确 - CrmClueDO clue = clueMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, clue); - } - - @Test - public void testUpdateClue_notExists() { - // 准备参数 - CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> clueService.updateClue(reqVO), CLUE_NOT_EXISTS); - } - - @Test - public void testDeleteClue_success() { - // mock 数据 - CrmClueDO dbClue = randomPojo(CrmClueDO.class); - clueMapper.insert(dbClue);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbClue.getId(); - - // 调用 - clueService.deleteClue(id); - // 校验数据不存在了 - assertNull(clueMapper.selectById(id)); - } - - @Test - public void testDeleteClue_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> clueService.deleteClue(id), CLUE_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetCluePage() { - // mock 数据 - CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 - o.setTransformStatus(null); - o.setFollowUpStatus(null); - o.setName(null); - o.setCustomerId(null); - o.setContactNextTime(null); - o.setTelephone(null); - o.setMobile(null); - o.setAddress(null); - o.setContactLastTime(null); - o.setCreateTime(null); - }); - clueMapper.insert(dbClue); - // 测试 transformStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); - // 测试 followUpStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); - // 测试 name 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); - // 测试 customerId 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); - // 测试 contactNextTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); - // 测试 telephone 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); - // 测试 mobile 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); - // 测试 address 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); - // 测试 contactLastTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); - // 测试 createTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); - // 准备参数 - CrmCluePageReqVO reqVO = new CrmCluePageReqVO(); - reqVO.setName(null); - reqVO.setTelephone(null); - reqVO.setMobile(null); - - // 调用 - PageResult pageResult = clueService.getCluePage(reqVO, 1L); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbClue, pageResult.getList().get(0)); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetClueList() { - // mock 数据 - CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 - o.setTransformStatus(null); - o.setFollowUpStatus(null); - o.setName(null); - o.setCustomerId(null); - o.setContactNextTime(null); - o.setTelephone(null); - o.setMobile(null); - o.setAddress(null); - o.setContactLastTime(null); - o.setCreateTime(null); - }); - clueMapper.insert(dbClue); - // 测试 transformStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); - // 测试 followUpStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); - // 测试 name 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); - // 测试 customerId 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); - // 测试 contactNextTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); - // 测试 telephone 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); - // 测试 mobile 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); - // 测试 address 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); - // 测试 contactLastTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); - // 测试 createTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); - // 准备参数 - CrmCluePageReqVO reqVO = new CrmCluePageReqVO(); - reqVO.setName(null); - reqVO.setTelephone(null); - reqVO.setMobile(null); - reqVO.setPageSize(PAGE_SIZE_NONE); - // 调用 - List list = clueService.getCluePage(reqVO, 1L).getList(); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbClue, list.get(0)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java deleted file mode 100644 index a511e7c1b..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.contract; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; -import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -/** - * {@link CrmContractServiceImpl} 的单元测试类 - * - * @author dhb52 - */ -@Import(CrmContractServiceImpl.class) -public class ContractServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmContractServiceImpl contractService; - - @Resource - private CrmContractMapper contractMapper; - - @Test - public void testCreateContract_success() { - // 准备参数 - CrmContractSaveReqVO reqVO = randomPojo(CrmContractSaveReqVO.class); - - // 调用 - Long contractId = contractService.createContract(reqVO, getLoginUserId()); - // 断言 - assertNotNull(contractId); - // 校验记录的属性是否正确 - CrmContractDO contract = contractMapper.selectById(contractId); - assertPojoEquals(reqVO, contract); - } - - @Test - public void testUpdateContract_success() { - // mock 数据 - CrmContractDO dbContract = randomPojo(CrmContractDO.class); - contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmContractSaveReqVO reqVO = randomPojo(CrmContractSaveReqVO.class, o -> { - o.setId(dbContract.getId()); // 设置更新的 ID - }); - - // 调用 - contractService.updateContract(reqVO); - // 校验是否更新正确 - CrmContractDO contract = contractMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, contract); - } - - @Test - public void testUpdateContract_notExists() { - // 准备参数 - CrmContractSaveReqVO reqVO = randomPojo(CrmContractSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> contractService.updateContract(reqVO), CONTRACT_NOT_EXISTS); - } - - @Test - public void testDeleteContract_success() { - // mock 数据 - CrmContractDO dbContract = randomPojo(CrmContractDO.class); - contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbContract.getId(); - - // 调用 - contractService.deleteContract(id); - // 校验数据不存在了 - assertNull(contractMapper.selectById(id)); - } - - @Test - public void testDeleteContract_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> contractService.deleteContract(id), CONTRACT_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetContractPage() { - // mock 数据 - CrmContractDO dbContract = randomPojo(CrmContractDO.class, o -> { // 等会查询到 - o.setName(null); - o.setCustomerId(null); - o.setBusinessId(null); - o.setOrderDate(null); - o.setNo(null); - o.setDiscountPercent(null); - o.setProductPrice(null); - }); - contractMapper.insert(dbContract); - // 测试 name 不匹配 - contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setName(null))); - // 测试 customerId 不匹配 - contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setCustomerId(null))); - // 测试 no 不匹配 - contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setNo(null))); - // 准备参数 - CrmContractPageReqVO reqVO = new CrmContractPageReqVO(); - reqVO.setName(null); - reqVO.setCustomerId(null); - reqVO.setBusinessId(null); - reqVO.setNo(null); - - // 调用 - PageResult pageResult = contractService.getContractPage(reqVO, getLoginUserId()); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbContract, pageResult.getList().get(0)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java deleted file mode 100644 index 8f701d987..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.customer; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; -import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -// TODO 芋艿:单测后续补 - -/** - * {@link CrmCustomerServiceImpl} 的单元测试类 - * - * @author Wanwan - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(CrmCustomerServiceImpl.class) -public class CrmCustomerServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmCustomerServiceImpl customerService; - - @Resource - private CrmCustomerMapper customerMapper; - @MockBean - private CrmPermissionService permissionService; - - @Test - public void testCreateCustomer_success() { - // 准备参数 - CrmCustomerSaveReqVO reqVO = randomPojo(CrmCustomerSaveReqVO.class); - - // 调用 - Long customerId = customerService.createCustomer(reqVO, getLoginUserId()); - // 断言 - assertNotNull(customerId); - // 校验记录的属性是否正确 - CrmCustomerDO customer = customerMapper.selectById(customerId); - assertPojoEquals(reqVO, customer); - } - - @Test - public void testUpdateCustomer_success() { - // mock 数据 - CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class); - customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmCustomerSaveReqVO reqVO = randomPojo(CrmCustomerSaveReqVO.class, o -> { - o.setId(dbCustomer.getId()); // 设置更新的 ID - }); - - // 调用 - customerService.updateCustomer(reqVO); - // 校验是否更新正确 - CrmCustomerDO customer = customerMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, customer); - } - - @Test - public void testUpdateCustomer_notExists() { - // 准备参数 - CrmCustomerSaveReqVO reqVO = randomPojo(CrmCustomerSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> customerService.updateCustomer(reqVO), CUSTOMER_NOT_EXISTS); - } - - @Test - public void testDeleteCustomer_success() { - // mock 数据 - CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class); - customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbCustomer.getId(); - - // 调用 - customerService.deleteCustomer(id); - // 校验数据不存在了 - assertNull(customerMapper.selectById(id)); - } - - @Test - public void testDeleteCustomer_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> customerService.deleteCustomer(id), CUSTOMER_NOT_EXISTS); - } - - @Test - public void testGetCustomerPage() { - // mock 数据 - CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到 - o.setName("张三"); - o.setMobile("13888888888"); - o.setTelephone("13888888888"); - o.setWebsite("https://yudao.com"); - }); - //customerMapper.insert(dbCustomer); - // 测试 name 不匹配 - //customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(""))); - // 测试 mobile 不匹配 - //customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); - // 测试 telephone 不匹配 - //customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); - // 测试 website 不匹配 - //customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null))); - // 准备参数 - CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO(); - reqVO.setName("张三"); - reqVO.setMobile("13888888888"); - //reqVO.setTelephone(null); - //reqVO.setWebsite(null); - - // 调用 - PageResult pageResult = customerService.getCustomerPage(reqVO, 1L); - // 断言 - //assertEquals(1, pageResult.getTotal()); - //assertEquals(1, pageResult.getList().size()); - //assertPojoEquals(dbCustomer, pageResult.getList().get(0)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customerlimitconfig/CrmCustomerLimitConfigServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customerlimitconfig/CrmCustomerLimitConfigServiceImplTest.java deleted file mode 100644 index ecda14822..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customerlimitconfig/CrmCustomerLimitConfigServiceImplTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.customerlimitconfig; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; -import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper; -import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerLimitConfigServiceImpl; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -// TODO 芋艿:单测后面搞 -/** - * {@link CrmCustomerLimitConfigServiceImpl} 的单元测试类 - * - * @author Wanwan - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(CrmCustomerLimitConfigServiceImpl.class) -public class CrmCustomerLimitConfigServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmCustomerLimitConfigServiceImpl customerLimitConfigService; - - @Resource - private CrmCustomerLimitConfigMapper customerLimitConfigMapper; - - @Test - public void testCreateCustomerLimitConfig_success() { - // 准备参数 - CrmCustomerLimitConfigSaveReqVO reqVO = randomPojo(CrmCustomerLimitConfigSaveReqVO.class); - - // 调用 - Long customerLimitConfigId = customerLimitConfigService.createCustomerLimitConfig(reqVO); - // 断言 - assertNotNull(customerLimitConfigId); - // 校验记录的属性是否正确 - CrmCustomerLimitConfigDO customerLimitConfig = customerLimitConfigMapper.selectById(customerLimitConfigId); - assertPojoEquals(reqVO, customerLimitConfig); - } - - @Test - public void testUpdateCustomerLimitConfig_success() { - // mock 数据 - CrmCustomerLimitConfigDO dbCustomerLimitConfig = randomPojo(CrmCustomerLimitConfigDO.class); - customerLimitConfigMapper.insert(dbCustomerLimitConfig);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmCustomerLimitConfigSaveReqVO reqVO = randomPojo(CrmCustomerLimitConfigSaveReqVO.class, o -> { - o.setId(dbCustomerLimitConfig.getId()); // 设置更新的 ID - }); - - // 调用 - customerLimitConfigService.updateCustomerLimitConfig(reqVO); - // 校验是否更新正确 - CrmCustomerLimitConfigDO customerLimitConfig = customerLimitConfigMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, customerLimitConfig); - } - - @Test - public void testUpdateCustomerLimitConfig_notExists() { - // 准备参数 - CrmCustomerLimitConfigSaveReqVO reqVO = randomPojo(CrmCustomerLimitConfigSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> customerLimitConfigService.updateCustomerLimitConfig(reqVO), CUSTOMER_LIMIT_CONFIG_NOT_EXISTS); - } - - @Test - public void testDeleteCustomerLimitConfig_success() { - // mock 数据 - CrmCustomerLimitConfigDO dbCustomerLimitConfig = randomPojo(CrmCustomerLimitConfigDO.class); - customerLimitConfigMapper.insert(dbCustomerLimitConfig);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbCustomerLimitConfig.getId(); - - // 调用 - customerLimitConfigService.deleteCustomerLimitConfig(id); - // 校验数据不存在了 - assertNull(customerLimitConfigMapper.selectById(id)); - } - - @Test - public void testDeleteCustomerLimitConfig_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> customerLimitConfigService.deleteCustomerLimitConfig(id), CUSTOMER_LIMIT_CONFIG_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetCustomerLimitConfigPage() { - // mock 数据 - CrmCustomerLimitConfigDO dbCustomerLimitConfig = randomPojo(CrmCustomerLimitConfigDO.class, o -> { // 等会查询到 - }); - customerLimitConfigMapper.insert(dbCustomerLimitConfig); - // 准备参数 - CrmCustomerLimitConfigPageReqVO reqVO = new CrmCustomerLimitConfigPageReqVO(); - - // 调用 - PageResult pageResult = customerLimitConfigService.getCustomerLimitConfigPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbCustomerLimitConfig, pageResult.getList().get(0)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java deleted file mode 100644 index 4f17abcba..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java +++ /dev/null @@ -1,137 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.receivable; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; -import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_PLAN_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -// TODO 芋艿:后续,需要补充测试用例 - -/** - * {@link CrmReceivablePlanServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(CrmReceivablePlanServiceImpl.class) -public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmReceivablePlanServiceImpl receivablePlanService; - - @Resource - private CrmReceivablePlanMapper crmReceivablePlanMapper; - - @Test - public void testCreateReceivablePlan_success() { - // 准备参数 - CrmReceivablePlanCreateReqVO reqVO = randomPojo(CrmReceivablePlanCreateReqVO.class); - - // 调用 - Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO, 1L); - // 断言 - assertNotNull(receivablePlanId); - // 校验记录的属性是否正确 - CrmReceivablePlanDO receivablePlan = crmReceivablePlanMapper.selectById(receivablePlanId); - assertPojoEquals(reqVO, receivablePlan); - } - - @Test - public void testUpdateReceivablePlan_success() { - // mock 数据 - CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class); - crmReceivablePlanMapper.insert(dbReceivablePlan);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmReceivablePlanUpdateReqVO reqVO = randomPojo(CrmReceivablePlanUpdateReqVO.class, o -> { - o.setId(dbReceivablePlan.getId()); // 设置更新的 ID - }); - - // 调用 - receivablePlanService.updateReceivablePlan(reqVO); - // 校验是否更新正确 - CrmReceivablePlanDO receivablePlan = crmReceivablePlanMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, receivablePlan); - } - - @Test - public void testUpdateReceivablePlan_notExists() { - // 准备参数 - CrmReceivablePlanUpdateReqVO reqVO = randomPojo(CrmReceivablePlanUpdateReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> receivablePlanService.updateReceivablePlan(reqVO), RECEIVABLE_PLAN_NOT_EXISTS); - } - - @Test - public void testDeleteReceivablePlan_success() { - // mock 数据 - CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class); - crmReceivablePlanMapper.insert(dbReceivablePlan);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbReceivablePlan.getId(); - - // 调用 - receivablePlanService.deleteReceivablePlan(id); - // 校验数据不存在了 - assertNull(crmReceivablePlanMapper.selectById(id)); - } - - @Test - public void testDeleteReceivablePlan_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> receivablePlanService.deleteReceivablePlan(id), RECEIVABLE_PLAN_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetReceivablePlanPage() { - // mock 数据 - CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到 - o.setPeriod(null); - o.setReturnTime(null); - o.setRemindDays(null); - o.setRemindTime(null); - o.setCustomerId(null); - o.setContractId(null); - o.setOwnerUserId(null); - o.setRemark(null); - o.setCreateTime(null); - }); - crmReceivablePlanMapper.insert(dbReceivablePlan); - // 测试 customerId 不匹配 - crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null))); - // 测试 contractId 不匹配 - crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null))); - // 准备参数 - CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO(); - reqVO.setCustomerId(null); - reqVO.setContractId(null); - reqVO.setPageSize(PAGE_SIZE_NONE); - // 调用 - PageResult pageResult = receivablePlanService.getReceivablePlanPage(reqVO, 1L); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java deleted file mode 100644 index 04c466924..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.receivable; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; -import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.*; - -// TODO 芋艿:等实现完,在校验下; -/** - * {@link CrmReceivableServiceImpl} 的单元测试类 - * - * @author 赤焰 - */ -@Disabled // TODO 芋艿:后续 fix 补充的单测 -@Import(CrmReceivableServiceImpl.class) -public class CrmCrmReceivableServiceImplTest extends BaseDbUnitTest { - - @Resource - private CrmReceivableServiceImpl receivableService; - - @Resource - private CrmReceivableMapper crmReceivableMapper; - - @Test - public void testCreateReceivable_success() { - // 准备参数 - CrmReceivableCreateReqVO reqVO = randomPojo(CrmReceivableCreateReqVO.class); - - // 调用 - Long receivableId = receivableService.createReceivable(reqVO, getLoginUserId()); - // 断言 - assertNotNull(receivableId); - // 校验记录的属性是否正确 - CrmReceivableDO receivable = crmReceivableMapper.selectById(receivableId); - assertPojoEquals(reqVO, receivable); - } - - @Test - public void testUpdateReceivable_success() { - // mock 数据 - CrmReceivableDO dbReceivable = randomPojo(CrmReceivableDO.class); - crmReceivableMapper.insert(dbReceivable);// @Sql: 先插入出一条存在的数据 - // 准备参数 - CrmReceivableUpdateReqVO reqVO = randomPojo(CrmReceivableUpdateReqVO.class, o -> { - o.setId(dbReceivable.getId()); // 设置更新的 ID - }); - - // 调用 - receivableService.updateReceivable(reqVO); - // 校验是否更新正确 - CrmReceivableDO receivable = crmReceivableMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, receivable); - } - - @Test - public void testUpdateReceivable_notExists() { - // 准备参数 - CrmReceivableUpdateReqVO reqVO = randomPojo(CrmReceivableUpdateReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> receivableService.updateReceivable(reqVO), RECEIVABLE_NOT_EXISTS); - } - - @Test - public void testDeleteReceivable_success() { - // mock 数据 - CrmReceivableDO dbReceivable = randomPojo(CrmReceivableDO.class); - crmReceivableMapper.insert(dbReceivable);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbReceivable.getId(); - - // 调用 - receivableService.deleteReceivable(id); - // 校验数据不存在了 - assertNull(crmReceivableMapper.selectById(id)); - } - - @Test - public void testDeleteReceivable_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> receivableService.deleteReceivable(id), RECEIVABLE_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetReceivablePage() { - // mock 数据 - CrmReceivableDO dbReceivable = randomPojo(CrmReceivableDO.class, o -> { // 等会查询到 - o.setNo(null); - o.setPlanId(null); - o.setCustomerId(null); - o.setContractId(null); - o.setProcessInstanceId(null); - o.setReturnTime(null); - o.setReturnType(null); - o.setPrice(null); - o.setOwnerUserId(null); - o.setSort(null); - o.setAuditStatus(null); - o.setRemark(null); - o.setCreateTime(null); - }); - crmReceivableMapper.insert(dbReceivable); - // 测试 no 不匹配 - crmReceivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setNo(null))); - // 测试 planId 不匹配 - crmReceivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setPlanId(null))); - // 测试 customerId 不匹配 - crmReceivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setCustomerId(null))); - // 准备参数 - CrmReceivablePageReqVO reqVO = new CrmReceivablePageReqVO(); - reqVO.setNo(null); - reqVO.setPlanId(null); - reqVO.setCustomerId(null); - - // 调用 - PageResult pageResult = receivableService.getReceivablePage(reqVO, 1L); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbReceivable, pageResult.getList().get(0)); - } - -} From 1bfb4060416046128693507fe506ae397d294787 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 18 Feb 2024 21:47:36 +0800 Subject: [PATCH 06/54] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20review?= =?UTF-8?q?=20=E5=BE=85=E6=8F=90=E9=86=92=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/vo/CrmClueRespVO.java | 101 +++++++++--------- .../admin/clue/vo/CrmClueSaveReqVO.java | 69 ++++++------ .../admin/contract/CrmContractController.java | 1 - .../admin/customer/CrmCustomerController.java | 13 +-- .../customer/vo/CrmCustomerPageReqVO.java | 5 +- .../crm/dal/dataobject/clue/CrmClueDO.java | 96 +++++++++-------- .../dataobject/customer/CrmCustomerDO.java | 88 +++++++-------- .../crm/dal/mysql/clue/CrmClueMapper.java | 9 +- .../dal/mysql/contract/CrmContractMapper.java | 15 ++- .../dal/mysql/customer/CrmCustomerMapper.java | 19 ++-- .../mysql/receivable/CrmReceivableMapper.java | 6 +- .../receivable/CrmReceivablePlanMapper.java | 9 +- .../service/customer/CrmCustomerService.java | 1 + 13 files changed, 213 insertions(+), 219 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index 35d30956e..b36c0a51d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -24,73 +24,47 @@ public class CrmClueRespVO { @ExcelProperty("编号") private Long id; - @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @ExcelProperty(value = "转化状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.BOOLEAN_STRING) - private Boolean transformStatus; + @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx") + @ExcelProperty("线索名称") + private String name; @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") @ExcelProperty(value = "跟进状态", converter = DictConvert.class) @DictFormat(DictTypeConstants.BOOLEAN_STRING) private Boolean followUpStatus; - @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx") - @ExcelProperty("线索名称") - private String name; - - @Schema(description = "客户 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "520") - // TODO 这里需要导出成客户名称 - @ExcelProperty("客户id") - private Long customerId; + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ExcelProperty("下次联系时间") private LocalDateTime contactNextTime; - @Schema(description = "电话", example = "18000000000") - @ExcelProperty("电话") - private String telephone; + @Schema(description = "负责人编号") + @ExcelProperty("负责人的用户编号") + // TODO 这里需要导出成负责人的名字 + private Long ownerUserId; + + @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "转化状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean transformStatus; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "520") + // TODO 这里需要导出成客户名称 + @ExcelProperty("客户编号") + private Long customerId; @Schema(description = "手机号", example = "18000000000") @ExcelProperty("手机号") private String mobile; - @Schema(description = "地址", example = "北京市海淀区") - @ExcelProperty("地址") - private String address; - - @Schema(description = "负责人编号") - @ExcelProperty("负责人的用户编号") - private Long ownerUserId; - - @Schema(description = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @ExcelProperty("最后跟进时间") - private LocalDateTime contactLastTime; - - @Schema(description = "备注", example = "随便") - @ExcelProperty("备注") - private String remark; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - - @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - @ExcelProperty(value = "所属行业", converter = DictConvert.class) - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY) - private Integer industryId; - - @Schema(description = "客户等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - @ExcelProperty(value = "客户等级", converter = DictConvert.class) - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL) - private Integer level; - - @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - @ExcelProperty(value = "客户来源", converter = DictConvert.class) - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) - private Integer source; + @Schema(description = "电话", example = "18000000000") + @ExcelProperty("电话") + private String telephone; @Schema(description = "网址", example = "25682") @ExcelProperty("网址") @@ -108,8 +82,35 @@ public class CrmClueRespVO { @ExcelProperty("email") private String email; + @Schema(description = "地址", example = "北京市海淀区") + @ExcelProperty("地址") + private String address; + + @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @ExcelProperty(value = "所属行业", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @Schema(description = "客户等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @ExcelProperty(value = "客户等级", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL) + private Integer level; + + @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @ExcelProperty(value = "客户来源", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) + private Integer source; + @Schema(description = "客户描述", example = "25682") @ExcelProperty("客户描述") private String description; + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index 4ca004a59..e121438bb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -21,7 +21,7 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; -@Schema(description = "管理后台 - CRM 线索 创建/更新 Request VO") +@Schema(description = "管理后台 - CRM 线索创建/更新 Request VO") @Data public class CrmClueSaveReqVO { @@ -33,50 +33,28 @@ public class CrmClueSaveReqVO { @NotEmpty(message = "线索名称不能为空") private String name; + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @DiffLogField(name = "最后跟进时间") + private LocalDateTime contactLastTime; + @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") @DiffLogField(name = "下次联系时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime contactNextTime; - @Schema(description = "电话", example = "18000000000") - @DiffLogField(name = "电话") - @Telephone - private String telephone; + @Schema(description = "负责人编号", example = "2048") + private Long ownerUserId; @Schema(description = "手机号", example = "18000000000") @DiffLogField(name = "手机号") @Mobile private String mobile; - @Schema(description = "地址", example = "北京市海淀区") - @DiffLogField(name = "地址") - private String address; - - @Schema(description = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @DiffLogField(name = "最后跟进时间") - private LocalDateTime contactLastTime; - - @Schema(description = "负责人编号", example = "2048") - private Long ownerUserId; - - @Schema(description = "备注", example = "随便") - @DiffLogField(name = "备注") - private String remark; - - @Schema(description = "所属行业", example = "1") - @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME) - @DictFormat(CRM_CUSTOMER_INDUSTRY) - private Integer industryId; - - @Schema(description = "客户等级", example = "2") - @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME) - @InEnum(CrmCustomerLevelEnum.class) - private Integer level; - - @Schema(description = "客户来源", example = "3") - @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME) - private Integer source; + @Schema(description = "电话", example = "18000000000") + @DiffLogField(name = "电话") + @Telephone + private String telephone; @Schema(description = "网址", example = "https://www.baidu.com") @DiffLogField(name = "网址") @@ -98,8 +76,31 @@ public class CrmClueSaveReqVO { @Size(max = 255, message = "邮箱长度不能超过 255 个字符") private String email; + @Schema(description = "地址", example = "北京市海淀区") + @DiffLogField(name = "地址") + private String address; + + @Schema(description = "所属行业", example = "1") + @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME) + @DictFormat(CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @Schema(description = "客户等级", example = "2") + @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME) + @InEnum(CrmCustomerLevelEnum.class) + private Integer level; + + @Schema(description = "客户来源", example = "3") + @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME) + private Integer source; + @Schema(description = "客户描述", example = "任意文字") @DiffLogField(name = "客户描述") @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") private String description; + + @Schema(description = "备注", example = "随便") + @DiffLogField(name = "备注") + private String remark; + } 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 c283f4acd..3951d1ebd 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 @@ -191,7 +191,6 @@ public class CrmContractController { return success(contractService.getCheckContractCount(getLoginUserId())); } - @GetMapping("/end-contract-count") @Operation(summary = "获得即将到期的合同数量") @PreAuthorize("@ss.hasPermission('crm:contract:query')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 51eb7c3e6..3c1806d51 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -152,19 +152,17 @@ public class CrmCustomerController { @Operation(summary = "获得待进入公海客户数量") @PreAuthorize("@ss.hasPermission('crm:customer:query')") public CommonResult getPutInPoolRemindCustomerCount() { - // 获取公海配置 TODO @dbh52:合并到 getPutInPoolRemindCustomerPage 会更合适哈; + // 获取公海配置 CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); if (ObjUtil.isNull(poolConfigDO) || Boolean.FALSE.equals(poolConfigDO.getEnabled()) || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); } - - CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO(); - pageVO.setPool(null); - pageVO.setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY); - pageVO.setSceneType(CrmSceneTypeEnum.OWNER.getType()); - + CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO() + .setPool(null) + .setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY) + .setSceneType(CrmSceneTypeEnum.OWNER.getType()); return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId())); } @@ -182,7 +180,6 @@ public class CrmCustomerController { return success(customerService.getFollowCustomerCount(getLoginUserId())); } - /** * 获取距离进入公海的时间 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java index 1fd2a1981..15b0529e6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java @@ -50,10 +50,7 @@ public class CrmCustomerPageReqVO extends PageParam { private Boolean pool; // null 则表示为不是公海数据 @Schema(description = "联系状态", example = "1") - private Integer contactStatus; // backlog查询条件, null 则表示为不做查询 - - @Schema(description = "跟进状态", example = "true") - private Boolean followUpStatus; // backlog查询条件, null 则表示为不做查询 + private Integer contactStatus; // backlog 查询条件 @Schema(description = "跟进状态", example = "true") private Boolean followUpStatus; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java index 5ea1dea28..44a628503 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -10,7 +10,6 @@ import lombok.*; import java.time.LocalDateTime; -// TODO 芋艿:字段的顺序,需要整理下; /** * 线索 DO * @@ -32,67 +31,51 @@ public class CrmClueDO extends BaseDO { @TableId private Long id; /** - * 转化状态 + * 线索名称 */ - private Boolean transformStatus; + private String name; + /** * 跟进状态 */ private Boolean followUpStatus; /** - * 线索名称 + * 最后跟进时间 TODO 添加跟进记录时更新该值 */ - private String name; - /** - * 客户 id - * - * 关联 {@link CrmCustomerDO#getId()} - */ - private Long customerId; + private LocalDateTime contactLastTime; /** * 下次联系时间 */ private LocalDateTime contactNextTime; + /** - * 电话 + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 */ - private String telephone; + private Long ownerUserId; + + /** + * 转化状态 + * + * true 表示已转换,会更新 {@link #customerId} 字段 + */ + private Boolean transformStatus; + /** + * 客户编号 + * + * 关联 {@link CrmCustomerDO#getId()} + */ + private Long customerId; + /** * 手机号 */ private String mobile; /** - * 地址 + * 电话 */ - private String address; - /** - * 最后跟进时间 TODO 添加跟进记录时更新该值 - */ - private LocalDateTime contactLastTime; - /** - * 备注 - */ - private String remark; - /** - * 负责人的用户编号 - * 关联 AdminUserDO 的 id 字段 - */ - private Long ownerUserId; - /** - * 所属行业 - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} - */ - private Integer industryId; - /** - * 客户等级 - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} - */ - private Integer level; - /** - * 客户来源 - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} - */ - private Integer source; + private String telephone; /** * 网址 */ @@ -109,8 +92,35 @@ public class CrmClueDO extends BaseDO { * email */ private String email; + /** + * 地址 + */ + private String address; + /** + * 所属行业 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} + */ + private Integer industryId; + /** + * 客户等级 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} + */ + private Integer level; + /** + * 客户来源 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} + */ + private Integer source; /** * 客户描述 */ private String description; + /** + * 备注 + */ + private String remark; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index 2bd614f57..bf94c053a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -9,8 +9,6 @@ import lombok.*; import java.time.LocalDateTime; -// TODO 芋艿:调整下字段 - /** * CRM 客户 DO * @@ -35,10 +33,35 @@ public class CrmCustomerDO extends BaseDO { * 客户名称 */ private String name; + /** * 跟进状态 */ private Boolean followUpStatus; + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 最后跟进内容 + */ + private String contactLastContent; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + /** + * 最后接收时间 + */ + private LocalDateTime receiveTime; + /** * 锁定状态 */ @@ -47,24 +70,7 @@ public class CrmCustomerDO extends BaseDO { * 成交状态 */ private Boolean dealStatus; - /** - * 所属行业 - * - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} - */ - private Integer industryId; - /** - * 客户等级 - * - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} - */ - private Integer level; - /** - * 客户来源 - * - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} - */ - private Integer source; + /** * 手机 */ @@ -89,20 +95,6 @@ public class CrmCustomerDO extends BaseDO { * email */ private String email; - /** - * 客户描述 - */ - private String description; - /** - * 备注 - */ - private String remark; - /** - * 负责人的用户编号 - * - * 关联 AdminUserDO 的 id 字段 - */ - private Long ownerUserId; /** * 所在地 * @@ -113,23 +105,31 @@ public class CrmCustomerDO extends BaseDO { * 详细地址 */ private String detailAddress; - /** - * 最后接收时间 + * 所属行业 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} */ - private LocalDateTime receiveTime; + private Integer industryId; /** - * 最后跟进时间 + * 客户等级 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} */ - private LocalDateTime contactLastTime; - + private Integer level; /** - * 最后跟进内容 + * 客户来源 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} */ - private String contactLastContent; + private Integer source; /** - * 下次联系时间 + * 客户描述 */ - private LocalDateTime contactNextTime; + private String description; + /** + * 备注 + */ + private String remark; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index 9d5594d06..4c5206472 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -55,17 +55,16 @@ public interface CrmClueMapper extends BaseMapperX { return selectJoinList(CrmClueDO.class, query); } + // TODO @dhb52:db 统一都是 select 关键字; default Long getFollowLeadsCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - - // 我负责的, 非公海 + // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - - // 未跟进, 未转化 + // 未跟进 + 未转化 TODO @dhb52:是不是 eq 会更好哈;mysql 不等于,对索引不友好 query.ne(CrmClueDO::getFollowUpStatus, true) .ne(CrmClueDO::getTransformStatus, true); - return selectCount(query); } + } 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 4a842a2a0..b96c0eeb2 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 @@ -6,7 +6,6 @@ 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.dal.dataobject.clue.CrmClueDO; 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; @@ -89,33 +88,31 @@ public interface CrmContractMapper extends BaseMapperX { return selectCount(CrmContractDO::getBusinessId, businessId); } + // TODO @dhb52:db 统一都是 select 关键字; default Long getCheckContractCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - - // 我负责的, 非公海 + // 我负责的 + 非公海 CrmQueryWrapperUtils.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()); - return selectCount(query); } + // TODO @dhb52:db 统一都是 select 关键字; default Long getEndContractCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - - // 我负责的, 非公海 + // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - // 即将到期 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); + // TODO: @芋艿 需要配置 提前提醒天数 int REMIND_DAYS = 20; query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); - return selectCount(query); } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index c0507b3d3..075f55fb3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -99,8 +99,7 @@ public interface CrmCustomerMapper extends BaseMapperX { // backlog 查询 if (ObjUtil.isNotNull(pageReqVO.getContactStatus())) { - Assert.isNull(pageReqVO.getPool(), "[是否为公海数据]必须是null"); - + Assert.isNull(pageReqVO.getPool(), "pool 必须是 null"); LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 @@ -113,7 +112,6 @@ public interface CrmCustomerMapper extends BaseMapperX { throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus()); } } - return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } @@ -150,31 +148,28 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectCount(query); } + // TODO @dhb52:db 统一都是 select 关键字; default Long getTodayCustomerCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - - // 我负责的, 非公海 + // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - // 今天需联系 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); - return selectCount(query); } + // TODO @dhb52:db 统一都是 select 关键字; default Long getFollowCustomerCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - - // 我负责的, 非公海 + // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - - // 未跟进 + // 未跟进 TODO @dhb52:是不是 eq 会更好哈;mysql 不等于,对索引不友好 query.ne(CrmClueDO::getFollowUpStatus, true); - return selectCount(query); } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index 36345f01f..faa8f5449 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -62,16 +62,14 @@ public interface CrmReceivableMapper extends BaseMapperX { return selectJoinList(CrmReceivableDO.class, query); } + // TODO @dhb52:db 统一都是 select 关键字; default Long getCheckReceivablesCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - - // 我负责的, 非公海 + // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - // 未提交 or 审核不通过 query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus()); - return selectCount(query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index 14c0a4ed9..778aa9369 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -79,19 +79,18 @@ public interface CrmReceivablePlanMapper extends BaseMapperX query = new MPJLambdaWrapperX<>(); - - // 我负责的, 非公海 + // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - - // 待回款 + // 待回款 TODO @dhb52:to_days(return_time) <= to_days(now())+ remind_days 看看怎么改成,不用数据库自己去计算这样的时间; LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); query.isNull(CrmReceivablePlanDO::getReceivableId) .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday) .apply("to_days(return_time) <= to_days(now())+ remind_days"); - return selectCount(query); } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 5485cd637..cd1f5ece3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -179,4 +179,5 @@ public interface CrmCustomerService { * @return 提醒数量 */ Long getFollowCustomerCount(Long userId); + } From dca262c64b1d460e8fb92ceffd9534c5f3327d95 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Sun, 18 Feb 2024 22:58:23 +0800 Subject: [PATCH 07/54] =?UTF-8?q?fix:=20=E6=A0=B9=E6=8D=AEcode-review?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/dal/mysql/clue/CrmClueMapper.java | 9 ++++----- .../dal/mysql/contract/CrmContractMapper.java | 8 +++----- .../dal/mysql/customer/CrmCustomerMapper.java | 10 ++++------ .../mysql/receivable/CrmReceivableMapper.java | 3 +-- .../receivable/CrmReceivablePlanMapper.java | 20 +++++++++---------- .../crm/service/clue/CrmClueServiceImpl.java | 2 +- .../service/contract/CrmContractService.java | 1 + .../contract/CrmContractServiceImpl.java | 4 ++-- .../customer/CrmCustomerServiceImpl.java | 4 ++-- .../CrmReceivablePlanServiceImpl.java | 2 +- .../receivable/CrmReceivableServiceImpl.java | 2 +- 11 files changed, 29 insertions(+), 36 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index 4c5206472..f434fd40b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -55,15 +55,14 @@ public interface CrmClueMapper extends BaseMapperX { return selectJoinList(CrmClueDO.class, query); } - // TODO @dhb52:db 统一都是 select 关键字; - default Long getFollowLeadsCount(Long userId) { + default Long selectFollowLeadsCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - // 未跟进 + 未转化 TODO @dhb52:是不是 eq 会更好哈;mysql 不等于,对索引不友好 - query.ne(CrmClueDO::getFollowUpStatus, true) - .ne(CrmClueDO::getTransformStatus, true); + // 未跟进 + 未转化 + query.eq(CrmClueDO::getFollowUpStatus, false) + .eq(CrmClueDO::getTransformStatus, false); return selectCount(query); } 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 b96c0eeb2..690bc5302 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 @@ -88,8 +88,7 @@ public interface CrmContractMapper extends BaseMapperX { return selectCount(CrmContractDO::getBusinessId, businessId); } - // TODO @dhb52:db 统一都是 select 关键字; - default Long getCheckContractCount(Long userId) { + default Long selectCheckContractCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), @@ -99,8 +98,7 @@ public interface CrmContractMapper extends BaseMapperX { return selectCount(query); } - // TODO @dhb52:db 统一都是 select 关键字; - default Long getEndContractCount(Long userId) { + default Long selectEndContractCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), @@ -108,7 +106,7 @@ public interface CrmContractMapper extends BaseMapperX { // 即将到期 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); - // TODO: @芋艿 需要配置 提前提醒天数 + // TODO: @dhb52 需要配置 提前提醒天数 int REMIND_DAYS = 20; query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 075f55fb3..7f649bc6c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -148,8 +148,7 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectCount(query); } - // TODO @dhb52:db 统一都是 select 关键字; - default Long getTodayCustomerCount(Long userId) { + default Long selectTodayCustomerCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), @@ -161,14 +160,13 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectCount(query); } - // TODO @dhb52:db 统一都是 select 关键字; - default Long getFollowCustomerCount(Long userId) { + default Long selectFollowCustomerCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - // 未跟进 TODO @dhb52:是不是 eq 会更好哈;mysql 不等于,对索引不友好 - query.ne(CrmClueDO::getFollowUpStatus, true); + // 未跟进 + query.eq(CrmClueDO::getFollowUpStatus, false); return selectCount(query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index faa8f5449..eb525d346 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -62,8 +62,7 @@ public interface CrmReceivableMapper extends BaseMapperX { return selectJoinList(CrmReceivableDO.class, query); } - // TODO @dhb52:db 统一都是 select 关键字; - default Long getCheckReceivablesCount(Long userId) { + default Long selectCheckReceivablesCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index 778aa9369..119af7b37 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -50,21 +50,19 @@ public interface CrmReceivablePlanMapper extends BaseMapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); - // 待回款 TODO @dhb52:to_days(return_time) <= to_days(now())+ remind_days 看看怎么改成,不用数据库自己去计算这样的时间; + // TODO: @dhb52 需要配置 提前提醒天数 + int REMIND_DAYS = 20; LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); query.isNull(CrmReceivablePlanDO::getReceivableId) - .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday) - .apply("to_days(return_time) <= to_days(now())+ remind_days"); + .between(CrmReceivablePlanDO::getReturnTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); return selectCount(query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 209b54fbc..414e6ddbe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -278,7 +278,7 @@ public class CrmClueServiceImpl implements CrmClueService { @Override public Long getFollowLeadsCount(Long userId) { - return clueMapper.getFollowLeadsCount(userId); + return clueMapper.selectFollowLeadsCount(userId); } } 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 919cc293c..4553f391d 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 @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR 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.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; 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 2a1c1924a..71b9446e4 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 @@ -364,12 +364,12 @@ public class CrmContractServiceImpl implements CrmContractService { @Override public Long getCheckContractCount(Long userId) { - return contractMapper.getCheckContractCount(userId); + return contractMapper.selectCheckContractCount(userId); } @Override public Long getEndContractCount(Long userId) { - return contractMapper.getEndContractCount(userId); + return contractMapper.selectEndContractCount(userId); } } 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 bd2fc421c..8cb25d9ae 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 @@ -482,12 +482,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override public Long getTodayCustomerCount(Long userId) { - return customerMapper.getTodayCustomerCount(userId); + return customerMapper.selectTodayCustomerCount(userId); } @Override public Long getFollowCustomerCount(Long userId) { - return customerMapper.getFollowCustomerCount(userId); + return customerMapper.selectFollowCustomerCount(userId); } // ======================= 校验相关 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index 88ba22e14..d74219a6e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -164,7 +164,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { @Override public Long getRemindReceivablePlanCount(Long userId) { - return receivablePlanMapper.getRemindReceivablePlanCount(userId); + return receivablePlanMapper.selectRemindReceivablePlanCount(userId); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index e931286d7..d2f7db036 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -184,7 +184,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @Override public Long getCheckReceivablesCount(Long userId) { - return receivableMapper.getCheckReceivablesCount(userId); + return receivableMapper.selectCheckReceivablesCount(userId); } } From 49bc70ed82eac0281d13f45017f45bd0b97fe194 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 19 Feb 2024 13:02:41 +0800 Subject: [PATCH 08/54] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E7=BA=BF?= =?UTF-8?q?=E7=B4=A2=20clue=20=E5=88=97=E8=A1=A8=E7=9A=84=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/CrmClueController.java | 51 +++++++++++++++++-- .../admin/clue/vo/CrmClueRespVO.java | 33 ++++++++---- .../admin/customer/CrmCustomerController.java | 1 + .../crm/dal/dataobject/clue/CrmClueDO.java | 6 ++- .../crm/service/clue/CrmClueServiceImpl.java | 4 +- .../service/contract/CrmContractService.java | 10 +++- .../service/customer/CrmCustomerService.java | 13 +++++ 7 files changed, 103 insertions(+), 15 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index a3acd04f6..f1087c4ec 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -1,13 +1,22 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue; +import cn.hutool.core.collection.CollUtil; 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.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.clue.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +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; +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; @@ -19,10 +28,15 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; +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.pojo.PageParam.PAGE_SIZE_NONE; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -34,6 +48,13 @@ public class CrmClueController { @Resource private CrmClueService clueService; + @Resource + private CrmCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; @PostMapping("/create") @Operation(summary = "创建线索") @@ -73,7 +94,7 @@ public class CrmClueController { @PreAuthorize("@ss.hasPermission('crm:clue:query')") public CommonResult> getCluePage(@Valid CrmCluePageReqVO pageVO) { PageResult pageResult = clueService.getCluePage(pageVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, CrmClueRespVO.class)); + return success(new PageResult<>(buildClueDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/export-excel") @@ -84,8 +105,32 @@ public class CrmClueController { pageReqVO.setPageSize(PAGE_SIZE_NONE); List list = clueService.getCluePage(pageReqVO, getLoginUserId()).getList(); // 导出 Excel - List datas = BeanUtils.toBean(list, CrmClueRespVO.class); - ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, datas); + ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, buildClueDetailList(list)); + } + + private List buildClueDetailList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1.1 获取客户列表 + Map customerMap = customerService.getCustomerMap( + convertSet(list, CrmClueDO::getCustomerId)); + // 1.2 获取创建人、负责人列表 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(list, + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + // 2. 转换成 VO + return BeanUtils.toBean(list, CrmClueRespVO.class, clueVO -> { + // 2.1 设置客户名称 + MapUtils.findAndThen(customerMap, clueVO.getCustomerId(), customer -> clueVO.setCustomerName(customer.getName())); + // 2.2 设置创建人、负责人名称 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(clueVO.getCreator()), + user -> clueVO.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, clueVO.getOwnerUserId(), user -> { + clueVO.setOwnerUserName(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> clueVO.setOwnerUserDeptName(dept.getName())); + }); + }); } @PutMapping("/transfer") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index b36c0a51d..880e818ef 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -8,12 +8,9 @@ import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - @Schema(description = "管理后台 - 线索 Response VO") @Data @ToString(callSuper = true) @@ -34,19 +31,25 @@ public class CrmClueRespVO { private Boolean followUpStatus; @Schema(description = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ExcelProperty("最后跟进时间") private LocalDateTime contactLastTime; + @Schema(description = "最后跟进内容", example = "吃饭、睡觉、打逗逗") + @ExcelProperty("最后跟进内容") + private String contactLastContent; + @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ExcelProperty("下次联系时间") private LocalDateTime contactNextTime; @Schema(description = "负责人编号") - @ExcelProperty("负责人的用户编号") - // TODO 这里需要导出成负责人的名字 private Long ownerUserId; + @Schema(description = "负责人名字", example = "25682") + @ExcelProperty("负责人名字") + private String ownerUserName; + @Schema(description = "负责人部门") + @ExcelProperty("负责人部门") + private String ownerUserDeptName; @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") @ExcelProperty(value = "转化状态", converter = DictConvert.class) @@ -54,9 +57,10 @@ public class CrmClueRespVO { private Boolean transformStatus; @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "520") - // TODO 这里需要导出成客户名称 - @ExcelProperty("客户编号") private Long customerId; + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "客户名称") + @ExcelProperty("客户名称") + private String customerName; @Schema(description = "手机号", example = "18000000000") @ExcelProperty("手机号") @@ -109,8 +113,19 @@ public class CrmClueRespVO { @ExcelProperty("备注") private String remark; + @Schema(description = "创建人", example = "1024") + @ExcelProperty("创建人") + private String creator; + @Schema(description = "创建人名字", example = "芋道源码") + @ExcelProperty("创建人名字") + private String creatorName; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") private LocalDateTime createTime; + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("更新时间") + private LocalDateTime updateTime; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 3c1806d51..b89eb9feb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -56,6 +56,7 @@ public class CrmCustomerController { private CrmCustomerService customerService; @Resource private CrmCustomerPoolConfigService customerPoolConfigService; + @Resource private DeptApi deptApi; @Resource diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java index 44a628503..5ff910e1a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -40,9 +40,13 @@ public class CrmClueDO extends BaseDO { */ private Boolean followUpStatus; /** - * 最后跟进时间 TODO 添加跟进记录时更新该值 + * 最后跟进时间 */ private LocalDateTime contactLastTime; + /** + * 最后跟进内容 + */ + private String contactLastContent; /** * 下次联系时间 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 209b54fbc..56f760795 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -35,6 +35,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -81,7 +82,8 @@ public class CrmClueServiceImpl implements CrmClueService { } // 2. 插入 - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class).setId(null); + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class) + .setContactLastTime(LocalDateTime.now()); clueMapper.insert(clue); // 3. 创建数据权限 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 919cc293c..300ca86a2 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 @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR 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.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -127,13 +128,20 @@ public interface CrmContractService { Long getContractCountByCustomerId(Long customerId); /** - * 根据商机ID获取关联客户的合同数量 + * 根据商机编号,获取关联客户的合同数量 * * @param businessId 商机编号 * @return 数量 */ Long getContractCountByBusinessId(Long businessId); + /** + * 根据合同编号,获得合同的产品列表 + * + * @param contactId 合同编号 + * @return 产品列表 + */ + List getContractProductListByContractId(Long contactId); /** * 获得待审核合同数量 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index cd1f5ece3..5e675e0ed 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -10,6 +10,9 @@ import jakarta.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 客户 Service 接口 @@ -58,6 +61,16 @@ public interface CrmCustomerService { */ List getCustomerList(Collection ids); + /** + * 获得客户 Map + * + * @param ids 客户编号数组 + * @return 客户 Map + */ + default Map getCustomerMap(Collection ids) { + return convertMap(getCustomerList(ids), CrmCustomerDO::getId); + } + /** * 获得客户分页 * From fe330482b35ada5c948b9bec3f3feea55243a169 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 19 Feb 2024 19:02:12 +0800 Subject: [PATCH 09/54] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E7=BA=BF?= =?UTF-8?q?=E7=B4=A2=20clue=20=E6=96=B0=E5=A2=9E/=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=9A=84=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/vo/CrmClueRespVO.java | 20 +-- .../admin/clue/vo/CrmClueSaveReqVO.java | 15 +- .../admin/customer/CrmCustomerController.java | 4 +- .../customer/vo/CrmCustomerImportExcelVO.java | 3 - .../admin/customer/vo/CrmCustomerRespVO.java | 8 - .../customer/vo/CrmCustomerSaveReqVO.java | 4 - .../crm/dal/dataobject/clue/CrmClueDO.java | 18 +- .../dataobject/customer/CrmCustomerDO.java | 8 - .../customer/bo/CrmCustomerCreateReqBO.java | 4 - .../src/test/resources/sql/clean.sql | 11 -- .../src/test/resources/sql/create_tables.sql | 162 ------------------ 11 files changed, 27 insertions(+), 230 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index 880e818ef..56e5c2561 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -70,10 +70,6 @@ public class CrmClueRespVO { @ExcelProperty("电话") private String telephone; - @Schema(description = "网址", example = "25682") - @ExcelProperty("网址") - private String website; - @Schema(description = "QQ", example = "25682") @ExcelProperty("QQ") private String qq; @@ -86,9 +82,15 @@ public class CrmClueRespVO { @ExcelProperty("email") private String email; - @Schema(description = "地址", example = "北京市海淀区") - @ExcelProperty("地址") - private String address; + @Schema(description = "地区编号", example = "1024") + @ExcelProperty("地区编号") + private Integer areaId; + @Schema(description = "地区名称", example = "北京市") + @ExcelProperty("地区名称") + private String areaName; + @Schema(description = "详细地址", example = "北京市成华大道") + @ExcelProperty("详细地址") + private String detailAddress; @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") @ExcelProperty(value = "所属行业", converter = DictConvert.class) @@ -105,10 +107,6 @@ public class CrmClueRespVO { @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) private Integer source; - @Schema(description = "客户描述", example = "25682") - @ExcelProperty("客户描述") - private String description; - @Schema(description = "备注", example = "随便") @ExcelProperty("备注") private String remark; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index e121438bb..ca45d5ee1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerIndustryParseFunction; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerLevelParseFunction; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerSourceParseFunction; +import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAreaParseFunction; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Email; @@ -56,10 +57,6 @@ public class CrmClueSaveReqVO { @Telephone private String telephone; - @Schema(description = "网址", example = "https://www.baidu.com") - @DiffLogField(name = "网址") - private String website; - @Schema(description = "QQ", example = "123456789") @DiffLogField(name = "QQ") @Size(max = 20, message = "QQ长度不能超过 20 个字符") @@ -76,9 +73,13 @@ public class CrmClueSaveReqVO { @Size(max = 255, message = "邮箱长度不能超过 255 个字符") private String email; - @Schema(description = "地址", example = "北京市海淀区") - @DiffLogField(name = "地址") - private String address; + @Schema(description = "地区编号", example = "20158") + @DiffLogField(name = "地区编号", function = SysAreaParseFunction.NAME) + private Integer areaId; + + @Schema(description = "详细地址", example = "北京市海淀区") + @DiffLogField(name = "详细地址") + private String detailAddress; @Schema(description = "所属行业", example = "1") @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index b89eb9feb..4c5d948c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -239,10 +239,10 @@ public class CrmCustomerController { // 手动创建导出 demo List list = Arrays.asList( CrmCustomerImportExcelVO.builder().name("芋道").industryId(1).level(1).source(1).mobile("15601691300").telephone("") - .website("https://doc.iocoder.cn/").qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") + .qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") .areaId(null).detailAddress("").build(), CrmCustomerImportExcelVO.builder().name("源码").industryId(1).level(1).source(1).mobile("15601691300").telephone("") - .website("https://doc.iocoder.cn/").qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") + .qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") .areaId(null).detailAddress("").build() ); // 输出 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java index 4f57564dd..dda607147 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java @@ -43,9 +43,6 @@ public class CrmCustomerImportExcelVO { @ExcelProperty("电话") private String telephone; - @ExcelProperty("网址") - private String website; - @ExcelProperty("QQ") private String qq; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java index 69c75856f..031bc66c1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java @@ -64,10 +64,6 @@ public class CrmCustomerRespVO { @ExcelProperty("电话") private String telephone; - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("网址") - private String website; - @Schema(description = "负责人的用户编号", example = "25682") @ExcelProperty("QQ") private String qq; @@ -80,10 +76,6 @@ public class CrmCustomerRespVO { @ExcelProperty("email") private String email; - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("客户描述") - private String description; - @Schema(description = "负责人的用户编号", example = "25682") @ExcelProperty("备注") private String remark; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java index d6d73b142..b8e3d244a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java @@ -58,10 +58,6 @@ public class CrmCustomerSaveReqVO { @Telephone private String telephone; - @Schema(description = "网址", example = "https://www.baidu.com") - @DiffLogField(name = "网址") - private String website; - @Schema(description = "QQ", example = "123456789") @DiffLogField(name = "QQ") @Size(max = 20, message = "QQ长度不能超过 20 个字符") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java index 5ff910e1a..48e600be6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -80,10 +80,6 @@ public class CrmClueDO extends BaseDO { * 电话 */ private String telephone; - /** - * 网址 - */ - private String website; /** * QQ */ @@ -97,9 +93,15 @@ public class CrmClueDO extends BaseDO { */ private String email; /** - * 地址 + * 所在地 + * + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 */ - private String address; + private Integer areaId; + /** + * 详细地址 + */ + private String detailAddress; /** * 所属行业 * @@ -118,10 +120,6 @@ public class CrmClueDO extends BaseDO { * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} */ private Integer source; - /** - * 客户描述 - */ - private String description; /** * 备注 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index bf94c053a..a39e92bdb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -79,10 +79,6 @@ public class CrmCustomerDO extends BaseDO { * 电话 */ private String telephone; - /** - * 网址 - */ - private String website; /** * QQ */ @@ -123,10 +119,6 @@ public class CrmCustomerDO extends BaseDO { * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} */ private Integer source; - /** - * 客户描述 - */ - private String description; /** * 备注 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java index 6d80b0e4c..58d1476c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java @@ -64,10 +64,6 @@ public class CrmCustomerCreateReqBO { */ @Telephone private String telephone; - /** - * 网址 - */ - private String website; /** * QQ */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql deleted file mode 100644 index 138780eed..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql +++ /dev/null @@ -1,11 +0,0 @@ -DELETE FROM "crm_contract"; - -DELETE FROM "crm_clue"; - -DELETE FROM "crm_receivable"; - -DELETE FROM "crm_receivable_plan"; - -DELETE FROM "crm_customer"; - -DELETE FROM "crm_customer_limit_config"; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql deleted file mode 100644 index 9528f3dde..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql +++ /dev/null @@ -1,162 +0,0 @@ -CREATE TABLE IF NOT EXISTS "crm_contract" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "name" varchar NOT NULL, - "customer_id" bigint, - "business_id" bigint, - "process_instance_id" bigint, - "order_date" varchar, - "owner_user_id" bigint, - "no" varchar, - "start_time" varchar, - "end_time" varchar, - "price" int, - "discount_percent" int, - "product_price" int, - "ro_user_ids" varchar, - "rw_user_ids" varchar, - "contact_id" bigint, - "sign_user_id" bigint, - "contact_last_time" varchar, - "remark" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '合同表'; - -CREATE TABLE IF NOT EXISTS "crm_clue" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "transform_status" bit NOT NULL, - "follow_up_status" bit NOT NULL, - "name" varchar NOT NULL, - "customer_id" bigint NOT NULL, - "contact_next_time" varchar, - "telephone" varchar, - "mobile" varchar, - "address" varchar, - "owner_user_id" bigint, - "contact_last_time" varchar, - "remark" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint NOT NULL, - PRIMARY KEY ("id") -) COMMENT '线索表'; - -CREATE TABLE IF NOT EXISTS "crm_receivable" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "no" varchar, - "plan_id" bigint, - "customer_id" bigint, - "contract_id" bigint, - "check_status" int, - "process_instance_id" bigint, - "return_time" varchar, - "return_type" varchar, - "price" varchar, - "owner_user_id" bigint, - "batch_id" bigint, - "sort" int, - "data_scope" int, - "data_scope_dept_ids" varchar, - "status" int NOT NULL, - "remark" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '回款'; - -CREATE TABLE IF NOT EXISTS "crm_receivable_plan" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "index_no" bigint, - "receivable_id" bigint, - "status" int NOT NULL, - "check_status" varchar, - "process_instance_id" bigint, - "price" varchar, - "return_time" varchar, - "remind_days" bigint, - "remind_time" varchar, - "customer_id" bigint, - "contract_id" bigint, - "owner_user_id" bigint, - "sort" int, - "remark" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '回款计划'; - -CREATE TABLE IF NOT EXISTS "crm_customer" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "name" varchar(255), - "follow_up_status" int NOT NULL, - "lock_status" int NOT NULL, - "deal_status" int NOT NULL, - "industry_id" int, - "level" int, - "source" int, - "mobile" varchar(255), - "telephone" varchar(255), - "website" varchar(255), - "qq" varchar(255), - "wechat" varchar(255), - "email" varchar(255), - "description" varchar(255), - "remark" varchar(255), - "owner_user_id" bigint, - "area_id" int, - "detail_address" varchar(255), - "contact_last_time" datetime, - "contact_next_time" datetime, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint NOT NULL, - PRIMARY KEY ("id") -) COMMENT '客户表'; - -CREATE TABLE IF NOT EXISTS "crm_customer_limit_config" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "type" int NOT NULL, - "user_ids" varchar, - "dept_ids" varchar, - "max_count" int NOT NULL, - "deal_count_enabled" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint NOT NULL, - PRIMARY KEY ("id") -) COMMENT '客户限制配置表'; - -CREATE TABLE IF NOT EXISTS "crm_permission" -( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "biz_id" bigint NOT NULL, - "biz_type" int NOT NULL, - "user_id" bigint NOT NULL, - "level" int NOT NULL, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint NOT NULL, - PRIMARY KEY ("id") -) COMMENT '客户限制配置表'; \ No newline at end of file From 38e410cae079fcdfdea8bcca3fd7330528db568a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 19 Feb 2024 20:41:10 +0800 Subject: [PATCH 10/54] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E7=BA=BF?= =?UTF-8?q?=E7=B4=A2=E7=9A=84=E8=BD=AC=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 5 +-- .../admin/clue/CrmClueController.java | 23 ++++++---- .../admin/clue/vo/CrmCluePageReqVO.java | 3 ++ .../admin/clue/vo/CrmClueSaveReqVO.java | 2 + .../admin/clue/vo/CrmClueTranslateReqVO.java | 17 -------- .../crm/dal/mysql/clue/CrmClueMapper.java | 1 + .../crm/service/clue/CrmClueService.java | 8 ++-- .../crm/service/clue/CrmClueServiceImpl.java | 42 ++++++++----------- 8 files changed, 45 insertions(+), 56 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index d536d8a40..aa09b2032 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -16,8 +16,8 @@ public interface ErrorCodeConstants { // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); - ErrorCode CLUE_ANY_CLUE_NOT_EXISTS = new ErrorCode(1_020_001_001, "线索【{}】不存在"); - ErrorCode CLUE_ANY_CLUE_ALREADY_TRANSLATED = new ErrorCode(1_020_001_002, "线索【{}】已经转化过了,请勿重复转化"); + ErrorCode CLUE_NOT_EXISTS_ANY = new ErrorCode(1_020_001_001, "线索【{}】不存在"); + ErrorCode CLUE_TRANSFORM_FAIL_ALREADY = new ErrorCode(1_020_001_002, "线索【{}】已经转化过了,请勿重复转化"); // ========== 商机管理 1-020-002-000 ========== ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); @@ -25,7 +25,6 @@ public interface ErrorCodeConstants { // TODO @lilleo:商机状态、商机类型,都单独错误码段 - // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index f1087c4ec..726afc549 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 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.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; @@ -35,8 +36,7 @@ import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -60,7 +60,7 @@ public class CrmClueController { @Operation(summary = "创建线索") @PreAuthorize("@ss.hasPermission('crm:clue:create')") public CommonResult createClue(@Valid @RequestBody CrmClueSaveReqVO createReqVO) { - return success(clueService.createClue(createReqVO, getLoginUserId())); + return success(clueService.createClue(createReqVO)); } @PutMapping("/update") @@ -86,7 +86,14 @@ public class CrmClueController { @PreAuthorize("@ss.hasPermission('crm:clue:query')") public CommonResult getClue(@RequestParam("id") Long id) { CrmClueDO clue = clueService.getClue(id); - return success(BeanUtils.toBean(clue, CrmClueRespVO.class)); + return success(buildClueDetail(clue)); + } + + public CrmClueRespVO buildClueDetail(CrmClueDO clue) { + if (clue == null) { + return null; + } + return buildClueDetailList(Collections.singletonList(clue)).get(0); } @GetMapping("/page") @@ -121,6 +128,7 @@ public class CrmClueController { Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); // 2. 转换成 VO return BeanUtils.toBean(list, CrmClueRespVO.class, clueVO -> { + clueVO.setAreaName(AreaUtils.format(clueVO.getAreaId())); // 2.1 设置客户名称 MapUtils.findAndThen(customerMap, clueVO.getCustomerId(), customer -> clueVO.setCustomerName(customer.getName())); // 2.2 设置创建人、负责人名称 @@ -141,11 +149,12 @@ public class CrmClueController { return success(true); } - @PostMapping("/transform") + @PutMapping("/transform") @Operation(summary = "线索转化为客户") + @Parameter(name = "ids", description = "线索编号数组", required = true) @PreAuthorize("@ss.hasPermission('crm:clue:update')") - public CommonResult translateCustomer(@Valid @RequestBody CrmClueTranslateReqVO reqVO) { - clueService.translateCustomer(reqVO, getLoginUserId()); + public CommonResult transformClue(@RequestParam("ids") List ids) { + clueService.transformClue(ids, getLoginUserId()); return success(Boolean.TRUE); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java index be8d30dbe..a63d946e9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java @@ -17,6 +17,9 @@ public class CrmCluePageReqVO extends PageParam { @Schema(description = "线索名称", example = "线索xxx") private String name; + @Schema(description = "转化状态", example = "2048") + private Boolean transformStatus; + @Schema(description = "电话", example = "18000000000") private String telephone; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index ca45d5ee1..a27de7059 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -13,6 +13,7 @@ import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; @@ -45,6 +46,7 @@ public class CrmClueSaveReqVO { private LocalDateTime contactNextTime; @Schema(description = "负责人编号", example = "2048") + @NotNull(message = "负责人编号不能为空") private Long ownerUserId; @Schema(description = "手机号", example = "18000000000") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java deleted file mode 100644 index 03a4d78f1..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; - -import java.util.Set; - -@Schema(description = "管理后台 - 线索转化为客户 Request VO") -@Data -public class CrmClueTranslateReqVO { - - @Schema(description = "线索编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1024, 1025]") - @NotEmpty(message = "线索编号不能为空") - private Set ids; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index 4c5206472..4bef3112a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -36,6 +36,7 @@ public interface CrmClueMapper extends BaseMapperX { // 拼接自身的查询条件 query.selectAll(CrmClueDO.class) .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) + .eqIfPresent(CrmClueDO::getTransformStatus, pageReqVO.getTransformStatus()) .likeIfPresent(CrmClueDO::getTelephone, pageReqVO.getTelephone()) .likeIfPresent(CrmClueDO::getMobile, pageReqVO.getMobile()) .eqIfPresent(CrmClueDO::getIndustryId, pageReqVO.getIndustryId()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 6c37305c7..26245bc9c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTranslateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -23,10 +22,9 @@ public interface CrmClueService { * 创建线索 * * @param createReqVO 创建信息 - * @param userId 用户编号 * @return 编号 */ - Long createClue(@Valid CrmClueSaveReqVO createReqVO, Long userId); + Long createClue(@Valid CrmClueSaveReqVO createReqVO); /** * 更新线索 @@ -85,10 +83,10 @@ public interface CrmClueService { /** * 线索转化为客户 * - * @param reqVO 线索编号 + * @param ids 线索编号数组 * @param userId 用户编号 */ - void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId); + void transformClue(List ids, Long userId); /** * 获得分配给我的线索数量 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 56f760795..1b7ba634a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -10,7 +10,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTranslateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; @@ -36,14 +35,16 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; -import static java.util.Collections.singletonList; /** * 线索 Service 实现类 @@ -71,17 +72,13 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", success = CRM_LEADS_CREATE_SUCCESS) - public Long createClue(CrmClueSaveReqVO createReqVO, Long userId) { + public Long createClue(CrmClueSaveReqVO createReqVO) { // 1.1 校验关联数据 validateRelationDataExists(createReqVO); // 1.2 校验负责人是否存在 - if (createReqVO.getOwnerUserId() != null) { - adminUserApi.validateUserList(singletonList(createReqVO.getOwnerUserId())); - } else { - createReqVO.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 - } + adminUserApi.validateUser(createReqVO.getOwnerUserId()); - // 2. 插入 + // 2. 插入线索 CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class) .setContactLastTime(LocalDateTime.now()); clueMapper.insert(clue); @@ -103,12 +100,12 @@ public class CrmClueServiceImpl implements CrmClueService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) public void updateClue(CrmClueSaveReqVO updateReq) { Assert.notNull(updateReq.getId(), "线索编号不能为空"); - // 1. 校验线索是否存在 + // 1.1 校验线索是否存在 CrmClueDO oldClue = validateClueExists(updateReq.getId()); - // 2. 校验关联数据 + // 1.2 校验关联数据 validateRelationDataExists(updateReq); - // 3. 更新 + // 2. 更新线索 CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class); clueMapper.updateById(updateObj); @@ -130,7 +127,6 @@ public class CrmClueServiceImpl implements CrmClueService { // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); LogRecordContext.putVariable("clueName", oldClue.getName()); - } @Override @@ -155,12 +151,11 @@ public class CrmClueServiceImpl implements CrmClueService { LogRecordContext.putVariable("clueName", clue.getName()); } - @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", success = CRM_LEADS_TRANSFER_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { // 1 校验线索是否存在 CrmClueDO clue = validateClueExists(reqVO.getId()); @@ -176,20 +171,19 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) - public void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId) { + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#ids", level = CrmPermissionLevelEnum.OWNER) + public void transformClue(List ids, Long userId) { // 1.1 校验线索都存在 - Set clueIds = reqVO.getIds(); - List clues = getClueList(clueIds, userId); - if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), clueIds.size())) { - clueIds.removeAll(convertSet(clues, CrmClueDO::getId)); - throw exception(CLUE_ANY_CLUE_NOT_EXISTS, clueIds); + List clues = getClueList(ids, userId); + if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), ids.size())) { + ids.removeAll(convertSet(clues, CrmClueDO::getId)); + throw exception(CLUE_NOT_EXISTS_ANY, ids); } // 1.2 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 List translatedClues = filterList(clues, clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus())); if (CollUtil.isNotEmpty(translatedClues)) { - throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId)); + throw exception(CLUE_TRANSFORM_FAIL_ALREADY, convertSet(translatedClues, CrmClueDO::getId)); } // 2.1 遍历线索(未转化的线索),创建对应的客户 From 69a974ef02f1ce829dbf20acb9fca72199c12862 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 19 Feb 2024 22:47:28 +0800 Subject: [PATCH 11/54] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E7=BA=BF?= =?UTF-8?q?=E7=B4=A2=E7=9A=84=E8=B7=9F=E8=BF=9B=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 3 +- .../module/crm/enums/LogRecordConstants.java | 26 +-- .../crm/enums/common/CrmBizTypeEnum.java | 2 +- .../admin/clue/CrmClueController.java | 22 ++- .../operatelog/CrmOperateLogController.java | 2 +- .../crm/convert/clue/CrmClueConvert.java | 22 --- .../crm/dal/mysql/clue/CrmClueMapper.java | 15 +- .../crm/service/clue/CrmClueService.java | 18 +- .../crm/service/clue/CrmClueServiceImpl.java | 154 +++++++----------- .../CrmFollowUpRecordServiceImpl.java | 4 +- .../bo/CrmPermissionTransferReqBO.java | 4 + 11 files changed, 109 insertions(+), 163 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index aa09b2032..29909cf4f 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -16,8 +16,7 @@ public interface ErrorCodeConstants { // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); - ErrorCode CLUE_NOT_EXISTS_ANY = new ErrorCode(1_020_001_001, "线索【{}】不存在"); - ErrorCode CLUE_TRANSFORM_FAIL_ALREADY = new ErrorCode(1_020_001_002, "线索【{}】已经转化过了,请勿重复转化"); + ErrorCode CLUE_TRANSFORM_FAIL_ALREADY = new ErrorCode(1_020_001_001, "线索已经转化过了,请勿重复转化"); // ========== 商机管理 1-020-002-000 ========== ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); 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 98a66d2c9..6ed048f66 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 @@ -8,19 +8,21 @@ package cn.iocoder.yudao.module.crm.enums; */ public interface LogRecordConstants { - // ======================= CRM_LEADS 线索 ======================= + // ======================= CRM_CLUE 线索 ======================= - String CRM_LEADS_TYPE = "CRM 线索"; - String CRM_LEADS_CREATE_SUB_TYPE = "创建线索"; - String CRM_LEADS_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; - String CRM_LEADS_UPDATE_SUB_TYPE = "更新线索"; - String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}"; - String CRM_LEADS_DELETE_SUB_TYPE = "删除线索"; - String CRM_LEADS_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; - String CRM_LEADS_TRANSFER_SUB_TYPE = "转移线索"; - String CRM_LEADS_TRANSFER_SUCCESS = "将线索【{{#clue.name}}】的负责人从【{getAdminUserById{#clue.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; - String CRM_LEADS_TRANSLATE_SUB_TYPE = "线索转化为客户"; - String CRM_LEADS_TRANSLATE_SUCCESS = "将线索【{{#clue.name}}】转化为客户"; + String CRM_CLUE_TYPE = "CRM 线索"; + String CRM_CLUE_CREATE_SUB_TYPE = "创建线索"; + String CRM_CLUE_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; + String CRM_CLUE_UPDATE_SUB_TYPE = "更新线索"; + String CRM_CLUE_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}"; + String CRM_CLUE_DELETE_SUB_TYPE = "删除线索"; + String CRM_CLUE_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; + String CRM_CLUE_TRANSFER_SUB_TYPE = "转移线索"; + String CRM_CLUE_TRANSFER_SUCCESS = "将线索【{{#clue.name}}】的负责人从【{getAdminUserById{#clue.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String CRM_CLUE_TRANSLATE_SUB_TYPE = "线索转化为客户"; + String CRM_CLUE_TRANSLATE_SUCCESS = "将线索【{{#clueName}}】转化为客户"; + String CRM_CLUE_FOLLOW_UP_SUB_TYPE = "线索跟进"; + String CRM_CLUE_FOLLOW_UP_SUCCESS = "线索跟进【{{#clueName}}】"; // ======================= CRM_CUSTOMER 客户 ======================= diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java index f0784cab2..8402ad288 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java @@ -17,7 +17,7 @@ import java.util.Arrays; @Getter public enum CrmBizTypeEnum implements IntArrayValuable { - CRM_LEADS(1, "线索"), + CRM_CLUE(1, "线索"), CRM_CUSTOMER(2, "客户"), CRM_CONTACT(3, "联系人"), CRM_BUSINESS(4, "商机"), diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index 726afc549..044b39d34 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -9,7 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; @@ -36,7 +39,8 @@ import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -151,18 +155,18 @@ public class CrmClueController { @PutMapping("/transform") @Operation(summary = "线索转化为客户") - @Parameter(name = "ids", description = "线索编号数组", required = true) + @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('crm:clue:update')") - public CommonResult transformClue(@RequestParam("ids") List ids) { - clueService.transformClue(ids, getLoginUserId()); + public CommonResult transformClue(@RequestParam("id") Long id) { + clueService.transformClue(id, getLoginUserId()); return success(Boolean.TRUE); } - @GetMapping("/follow-leads-count") - @Operation(summary = "获得分配给我的线索数量") + @GetMapping("/follow-count") + @Operation(summary = "获得分配给我的、待跟进的线索数量") @PreAuthorize("@ss.hasPermission('crm:clue:query')") - public CommonResult getFollowLeadsCount() { - return success(clueService.getFollowLeadsCount(getLoginUserId())); + public CommonResult getFollowClueCount() { + return success(clueService.getFollowClueCount(getLoginUserId())); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java index 982ad3c0b..e048d85d8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java @@ -41,7 +41,7 @@ public class CrmOperateLogController { private static final Map BIZ_TYPE_MAP = new HashMap<>(); static { - BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_LEADS.getType(), CRM_LEADS_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CLUE.getType(), CRM_CLUE_TYPE); BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CUSTOMER.getType(), CRM_CUSTOMER_TYPE); BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTACT.getType(), CRM_CONTACT_TYPE); BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_BUSINESS.getType(), CRM_BUSINESS_TYPE); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java deleted file mode 100644 index 39e607bcb..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.clue; - -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -/** - * 线索 Convert - * - * @author Wanwan - */ -@Mapper -public interface CrmClueConvert { - - CrmClueConvert INSTANCE = Mappers.getMapper(CrmClueConvert.class); - - @Mapping(target = "bizId", source = "reqVO.id") - CrmPermissionTransferReqBO convert(CrmClueTransferReqVO reqVO, Long userId); - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index 0a23295cc..9d1cae206 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; @@ -22,16 +21,10 @@ import java.util.List; @Mapper public interface CrmClueMapper extends BaseMapperX { - default int updateOwnerUserIdById(Long id, Long ownerUserId) { - return update(new LambdaUpdateWrapper() - .eq(CrmClueDO::getId, id) - .set(CrmClueDO::getOwnerUserId, ownerUserId)); - } - default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); // 拼接自身的查询条件 query.selectAll(CrmClueDO.class) @@ -50,16 +43,16 @@ public interface CrmClueMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), ids, userId); query.selectAll(CrmClueDO.class).in(CrmClueDO::getId, ids).orderByDesc(CrmClueDO::getId); // 拼接自身的查询条件 return selectJoinList(CrmClueDO.class, query); } - default Long selectFollowLeadsCount(Long userId) { + default Long selectCountByFollow(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 未跟进 + 未转化 query.eq(CrmClueDO::getFollowUpStatus, false) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 26245bc9c..b84c6d51c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -5,9 +5,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -36,9 +36,11 @@ public interface CrmClueService { /** * 更新线索相关的跟进信息 * - * @param clueUpdateFollowUpReqBO 信息 + * @param id 编号 + * @param contactNextTime 下次联系时间 + * @param contactLastContent 最后联系内容 */ - void updateClueFollowUp(CrmUpdateFollowUpReqBO clueUpdateFollowUpReqBO); + void updateClueFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); /** * 删除线索 @@ -83,17 +85,17 @@ public interface CrmClueService { /** * 线索转化为客户 * - * @param ids 线索编号数组 + * @param id 线索编号 * @param userId 用户编号 */ - void transformClue(List ids, Long userId); + void transformClue(Long id, Long userId); /** - * 获得分配给我的线索数量 + * 获得分配给我的、待跟进的线索数量 * * @param userId 用户编号 - * @return 提醒数量 + * @return 数量 */ - Long getFollowLeadsCount(Long userId); + Long getFollowClueCount(Long userId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index ee7721593..935524948 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -3,15 +3,12 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; -import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; @@ -25,6 +22,7 @@ import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 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.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; @@ -37,12 +35,13 @@ import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.singleton; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_TRANSFORM_FAIL_ALREADY; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; @@ -60,18 +59,18 @@ public class CrmClueServiceImpl implements CrmClueService { @Resource private CrmCustomerService customerService; - @Resource private CrmPermissionService crmPermissionService; @Resource private CrmFollowUpRecordService followUpRecordService; + @Resource private AdminUserApi adminUserApi; @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", - success = CRM_LEADS_CREATE_SUCCESS) + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", + success = CRM_CLUE_CREATE_SUCCESS) public Long createClue(CrmClueSaveReqVO createReqVO) { // 1.1 校验关联数据 validateRelationDataExists(createReqVO); @@ -84,7 +83,7 @@ public class CrmClueServiceImpl implements CrmClueService { clueMapper.insert(clue); // 3. 创建数据权限 - CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_LEADS.getType()) + CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CLUE.getType()) .setBizId(clue.getId()).setUserId(clue.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); crmPermissionService.createPermission(createReqBO); @@ -95,9 +94,9 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", - success = CRM_LEADS_UPDATE_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", + success = CRM_CLUE_UPDATE_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) public void updateClue(CrmClueSaveReqVO updateReq) { Assert.notNull(updateReq.getId(), "线索编号不能为空"); // 1.1 校验线索是否存在 @@ -114,15 +113,25 @@ public class CrmClueServiceImpl implements CrmClueService { LogRecordContext.putVariable("clueName", oldClue.getName()); } + private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { + // 校验负责人 + if (Objects.nonNull(reqVO.getOwnerUserId()) && + Objects.isNull(adminUserApi.getUser(reqVO.getOwnerUserId()))) { + throw exception(USER_NOT_EXISTS); + } + } + @Override - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReq.bizId}", - success = CRM_LEADS_UPDATE_SUCCESS) - public void updateClueFollowUp(CrmUpdateFollowUpReqBO updateReq) { + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}", + success = CRM_CLUE_FOLLOW_UP_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + public void updateClueFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { // 校验线索是否存在 - CrmClueDO oldClue = validateClueExists(updateReq.getBizId()); + CrmClueDO oldClue = validateClueExists(id); // 更新 - clueMapper.updateById(BeanUtils.toBean(updateReq, CrmClueDO.class).setId(updateReq.getBizId())); + clueMapper.updateById(new CrmClueDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime) + .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent)); // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); @@ -131,9 +140,9 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_DELETE_SUB_TYPE, bizNo = "{{#id}}", - success = CRM_LEADS_DELETE_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_DELETE_SUB_TYPE, bizNo = "{{#id}}", + success = CRM_CLUE_DELETE_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteClue(Long id) { // 1. 校验存在 CrmClueDO clue = validateClueExists(id); @@ -142,28 +151,29 @@ public class CrmClueServiceImpl implements CrmClueService { clueMapper.deleteById(id); // 3. 删除数据权限 - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_LEADS.getType(), id); + crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CLUE.getType(), id); // 4. 删除跟进 - followUpRecordService.deleteFollowUpRecordByBiz(CrmBizTypeEnum.CRM_LEADS.getType(), id); + followUpRecordService.deleteFollowUpRecordByBiz(CrmBizTypeEnum.CRM_CLUE.getType(), id); - // 记录操作日志上下文 + // 5. 记录操作日志上下文 LogRecordContext.putVariable("clueName", clue.getName()); } @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", - success = CRM_LEADS_TRANSFER_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", + success = CRM_CLUE_TRANSFER_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { // 1 校验线索是否存在 CrmClueDO clue = validateClueExists(reqVO.getId()); // 2.1 数据权限转移 - crmPermissionService.transferPermission(CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); + crmPermissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CLUE.getType(), + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 设置新的负责人 - clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); + clueMapper.updateById(new CrmClueDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId())); // 3. 记录转移日志 LogRecordContext.putVariable("clue", clue); @@ -171,69 +181,32 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#ids", level = CrmPermissionLevelEnum.OWNER) - public void transformClue(List ids, Long userId) { + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_TRANSLATE_SUB_TYPE, bizNo = "{{#id}}", + success = CRM_CLUE_TRANSLATE_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) + public void transformClue(Long id, Long userId) { // 1.1 校验线索都存在 - List clues = getClueList(ids, userId); - if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), ids.size())) { - ids.removeAll(convertSet(clues, CrmClueDO::getId)); - throw exception(CLUE_NOT_EXISTS_ANY, ids); - } - // 1.2 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 - List translatedClues = filterList(clues, - clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus())); - if (CollUtil.isNotEmpty(translatedClues)) { - throw exception(CLUE_TRANSFORM_FAIL_ALREADY, convertSet(translatedClues, CrmClueDO::getId)); + CrmClueDO clue = validateClueExists(id); + // 1.2 存在已经转化的 + if (clue.getTransformStatus()) { + throw exception(CLUE_TRANSFORM_FAIL_ALREADY); } // 2.1 遍历线索(未转化的线索),创建对应的客户 - clues.forEach(clue -> { - Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId); - clue.setCustomerId(customerId); - }); + Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId); // 2.2 更新线索 - clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId()) - .setTransformStatus(Boolean.TRUE).setCustomerId(clue.getCustomerId()))); + clueMapper.updateById(new CrmClueDO().setId(id).setTransformStatus(Boolean.TRUE).setCustomerId(customerId)); // 2.3 复制跟进记录 - copyFollowUpRecords(clues); - - // 3. 记录操作日志 - for (CrmClueDO clue : clues) { - getSelf().translateCustomerLog(clue); - } - } - - /** - * 线索被转换客户后,需要将线索的跟进记录,复制到客户上 - * - * @param clues 被转化的线索 - */ - private void copyFollowUpRecords(List clues) { List followUpRecords = followUpRecordService.getFollowUpRecordByBiz( - CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId)); - if (CollUtil.isEmpty(followUpRecords)) { - return; + CrmBizTypeEnum.CRM_CLUE.getType(), singleton(clue.getId())); + if (CollUtil.isNotEmpty(followUpRecords)) { + followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, record -> + BeanUtils.toBean(record, CrmFollowUpCreateReqBO.class) + .setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()).setBizId(customerId))); } - // 创建跟进 - Map clueMap = convertMap(clues, CrmClueDO::getId); - followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> - BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) - .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId()))); - } - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSLATE_SUB_TYPE, bizNo = "{{#clue.id}}", - success = CRM_LEADS_TRANSLATE_SUCCESS) - public void translateCustomerLog(CrmClueDO clue) { - // 记录操作日志上下文 - LogRecordContext.putVariable("clue", clue); - } - - private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { - // 校验负责人 - if (Objects.nonNull(reqVO.getOwnerUserId()) && - Objects.isNull(adminUserApi.getUser(reqVO.getOwnerUserId()))) { - throw exception(USER_NOT_EXISTS); - } + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("clueName", clue.getName()); } private CrmClueDO validateClueExists(Long id) { @@ -245,7 +218,7 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.READ) public CrmClueDO getClue(Long id) { return clueMapper.selectById(id); } @@ -263,18 +236,9 @@ public class CrmClueServiceImpl implements CrmClueService { return clueMapper.selectPage(pageReqVO, userId); } - /** - * 获得自身的代理对象,解决 AOP 生效问题 - * - * @return 自己 - */ - private CrmClueServiceImpl getSelf() { - return SpringUtil.getBean(getClass()); - } - @Override - public Long getFollowLeadsCount(Long userId) { - return clueMapper.selectFollowLeadsCount(userId); + public Long getFollowClueCount(Long userId) { + return clueMapper.selectCountByFollow(userId); } } 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 88f0b887c..5cfdbb1dc 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 @@ -79,8 +79,8 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); } - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_LEADS.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 - clueService.updateClueFollowUp(updateFollowUpReqBO); + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 + clueService.updateClueFollowUp(followUpRecord.getId(), followUpRecord.getNextTime(), followUpRecord.getContent()); } if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java index 0e5933c0c..52f8a977a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java @@ -3,9 +3,11 @@ package cn.iocoder.yudao.module.crm.service.permission.bo; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import lombok.AllArgsConstructor; import lombok.Data; import jakarta.validation.constraints.NotNull; +import lombok.NoArgsConstructor; /** * 数据权限转移 Request BO @@ -13,6 +15,8 @@ import jakarta.validation.constraints.NotNull; * @author HUIHUI */ @Data +@NoArgsConstructor +@AllArgsConstructor public class CrmPermissionTransferReqBO { /** From 3e6524932b06cea91cff375ea31cb9a88e34c680 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 20 Feb 2024 12:55:44 +0800 Subject: [PATCH 12/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=AE=A2=E6=88=B7=E7=9A=84=E8=AF=A6=E6=83=85=E3=80=81?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=88=90=E4=BA=A4=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 1 + .../module/crm/enums/LogRecordConstants.java | 2 + .../admin/customer/CrmCustomerController.http | 16 --- .../admin/customer/CrmCustomerController.java | 107 ++++++++++++------ .../CrmCustomerDistributeReqVO.java | 2 +- .../CrmCustomerImportExcelVO.java | 37 +++--- .../CrmCustomerImportReqVO.java | 2 +- .../CrmCustomerImportRespVO.java | 2 +- .../{ => customer}/CrmCustomerLockReqVO.java | 2 +- .../{ => customer}/CrmCustomerPageReqVO.java | 2 +- .../vo/{ => customer}/CrmCustomerRespVO.java | 106 ++++++++--------- .../{ => customer}/CrmCustomerSaveReqVO.java | 53 ++++----- .../CrmCustomerTransferReqVO.java | 2 +- .../convert/customer/CrmCustomerConvert.java | 66 ----------- .../dataobject/customer/CrmCustomerDO.java | 4 - .../dal/mysql/customer/CrmCustomerMapper.java | 2 +- .../crm/service/clue/CrmClueServiceImpl.java | 2 +- .../service/customer/CrmCustomerService.java | 10 +- .../customer/CrmCustomerServiceImpl.java | 35 ++++-- 19 files changed, 214 insertions(+), 239 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerDistributeReqVO.java (98%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerImportExcelVO.java (96%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerImportReqVO.java (98%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerImportRespVO.java (98%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerLockReqVO.java (97%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerPageReqVO.java (99%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerRespVO.java (88%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerSaveReqVO.java (94%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/{ => customer}/CrmCustomerTransferReqVO.java (99%) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 29909cf4f..7a04208fb 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -51,6 +51,7 @@ public interface ErrorCodeConstants { ErrorCode CUSTOMER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_020_006_012, "导入客户数据不能为空!"); ErrorCode CUSTOMER_CREATE_NAME_NOT_NULL = new ErrorCode(1_020_006_013, "客户名称不能为空!"); ErrorCode CUSTOMER_NAME_EXISTS = new ErrorCode(1_020_006_014, "已存在名为【{}】的客户!"); + ErrorCode CUSTOMER_UPDATE_DEAL_STATUS_FAIL = new ErrorCode(1_020_006_015, "更新客户的成交状态失败,原因:已经是该状态,无需更新"); // ========== 权限管理 1_020_007_000 ========== ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); 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 6ed048f66..7301cf8b1 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 @@ -43,6 +43,8 @@ public interface LogRecordConstants { String CRM_CUSTOMER_RECEIVE_SUCCESS = "{{#ownerUserName != null ? '将客户【' + #customer.name + '】分配给【' + #ownerUserName + '】' : '领取客户【' + #customer.name + '】'}}"; String CRM_CUSTOMER_IMPORT_SUB_TYPE = "{{#isUpdate ? '导入并更新客户' : '导入客户'}}"; String CRM_CUSTOMER_IMPORT_SUCCESS = "{{#isUpdate ? '导入并更新了客户【'+ #customer.name +'】' : '导入了客户【'+ #customer.name +'】'}}"; + String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUB_TYPE = "更新客户成交状态"; + String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUCCESS = "更新了客户【{{#customerName}}】的成交状态为【{{#dealStatus ? '已成交' : '未成交'}}】"; // ======================= CRM_CUSTOMER_LIMIT_CONFIG 客户限制配置 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http deleted file mode 100644 index 9a6cb93a8..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http +++ /dev/null @@ -1,16 +0,0 @@ -### 请求 /transfer -PUT {{baseUrl}}/crm/customer/transfer -Content-Type: application/-id: {{adminTenentId}}json -Authorization: Bearer {{token}} -tenant - -{ - "id": 10, - "newOwnerUserId": 127 -} - -### 自定义日志记录结果 -### 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=客户转移, bizId=10, content=把客户【张三】的负责人从【芋道源码(15612345678)】变更为了【tttt】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/transfer, userIp=127.0.0.1, userAgent=Apache-HttpClient/4.5.14 (Java/17.0.9)) - -### diff 日志 -### | 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=更新客户, bizId=11, content=更新了客户【所属行业】从【H 住宿和餐饮业】修改为【D 电力、热力、燃气及水生产和供应业】;【客户等级】从【C (非优先客户)】修改为【A (重点客户)】;【客户来源】从【线上咨询】修改为【预约上门】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/update, userIp=0:0:0:0:0:0:0:1, userAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 4c5d948c8..bf25238a2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -5,12 +5,14 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; 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.date.LocalDateTimeUtils; +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.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; -import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; @@ -22,11 +24,11 @@ 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.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; -import org.mapstruct.ap.internal.util.Collections; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -45,6 +47,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED; +import static java.util.Collections.singletonList; @Tag(name = "管理后台 - CRM 客户") @RestController @@ -77,6 +80,18 @@ public class CrmCustomerController { return success(true); } + @PutMapping("/update-deal-status") + @Operation(summary = "更新客户的成交状态") + @Parameters({ + @Parameter(name = "id", description = "客户编号", required = true), + @Parameter(name = "dealStatus", description = "成交状态", required = true) + }) + public CommonResult updateCustomerDealStatus(@RequestParam("id") Long id, + @RequestParam("dealStatus") Boolean dealStatus) { + customerService.updateCustomerDealStatus(id, dealStatus); + return success(true); + } + @DeleteMapping("/delete") @Operation(summary = "删除客户") @Parameter(name = "id", description = "客户编号", required = true) @@ -93,14 +108,15 @@ public class CrmCustomerController { public CommonResult getCustomer(@RequestParam("id") Long id) { // 1. 获取客户 CrmCustomerDO customer = customerService.getCustomer(id); - if (customer == null) { - return success(null); - } // 2. 拼接数据 - Map userMap = adminUserApi.getUserMap( - Collections.asSet(Long.valueOf(customer.getCreator()), customer.getOwnerUserId())); - Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); - return success(CrmCustomerConvert.INSTANCE.convert(customer, userMap, deptMap)); + return success(buildCustomerDetail(customer)); + } + + public CrmCustomerRespVO buildCustomerDetail(CrmCustomerDO customer) { + if (customer == null) { + return null; + } + return buildCustomerDetailList(singletonList(customer)).get(0); } @GetMapping("/page") @@ -112,16 +128,38 @@ public class CrmCustomerController { if (CollUtil.isEmpty(pageResult.getList())) { return success(PageResult.empty(pageResult.getTotal())); } - // 2. 拼接数据 - Map poolDayMap = Boolean.TRUE.equals(pageVO.getPool()) ? null : - getPoolDayMap(pageResult.getList()); // 客户界面,需要查看距离进入公海的时间 - Map userMap = adminUserApi.getUserMap( - convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId()))); - Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); - return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); + return success(new PageResult<>(buildCustomerDetailList(pageResult.getList()), pageResult.getTotal())); } + public List buildCustomerDetailList(List list) { + if (CollUtil.isEmpty(list)) { + return java.util.Collections.emptyList(); + } + // 1.1 获取创建人、负责人列表 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(list, + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + // 1.2 获取距离进入公海的时间 + Map poolDayMap = getPoolDayMap(list); + // 2. 转换成 VO + return BeanUtils.toBean(list, CrmCustomerRespVO.class, customerVO -> { + customerVO.setAreaName(AreaUtils.format(customerVO.getAreaId())); + // 2.1 设置创建人、负责人名称 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(customerVO.getCreator()), + user -> customerVO.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, customerVO.getOwnerUserId(), user -> { + customerVO.setOwnerUserName(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> customerVO.setOwnerUserDeptName(dept.getName())); + }); + // 2.2 设置距离进入公海的时间 + if (customerVO.getOwnerUserId() != null) { + customerVO.setPoolDay(poolDayMap.get(customerVO.getId())); + } + }); + } + + // TODO @芋艿:需要 review 下 @GetMapping("/put-in-pool-remind-page") @Operation(summary = "获得待进入公海客户分页") @PreAuthorize("@ss.hasPermission('crm:customer:query')") @@ -141,12 +179,7 @@ public class CrmCustomerController { } // 2. 拼接数据 - // TODO @芋艿:合并 getCustomerPage 和 getPutInPoolRemindCustomerPage 的后置处理; - Map poolDayMap = getPoolDayMap(pageResult.getList()); // 客户界面,需要查看距离进入公海的时间 - Map userMap = adminUserApi.getUserMap( - convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId()))); - Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); - return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); + return success(new PageResult<>(buildCustomerDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/put-in-pool-remind-count") @@ -182,22 +215,26 @@ public class CrmCustomerController { } /** - * 获取距离进入公海的时间 + * 获取距离进入公海的时间 Map * - * @param customerList 客户列表 - * @return Map + * @param list 客户列表 + * @return key 客户编号, value 距离进入公海的时间 */ - private Map getPoolDayMap(List customerList) { + private Map getPoolDayMap(List list) { CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig(); if (poolConfig == null || !poolConfig.getEnabled()) { return MapUtil.empty(); } - return convertMap(customerList, CrmCustomerDO::getId, customer -> { + return convertMap(list, CrmCustomerDO::getId, customer -> { + // TODO 芋艿:这样计算,貌似有点问题 // 1.1 未成交放入公海天数 long dealExpireDay = 0; if (!customer.getDealStatus()) { dealExpireDay = poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime()); } + if (dealExpireDay < 0) { + dealExpireDay = 0; + } // 1.2 未跟进放入公海天数 LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); long contactExpireDay = poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime); @@ -230,7 +267,7 @@ public class CrmCustomerController { List list = customerService.getCustomerPage(pageVO, getLoginUserId()).getList(); // 导出 Excel ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerRespVO.class, - BeanUtils.toBean(list, CrmCustomerRespVO.class)); + buildCustomerDetailList(list)); } @GetMapping("/get-import-template") @@ -238,12 +275,12 @@ public class CrmCustomerController { public void importTemplate(HttpServletResponse response) throws IOException { // 手动创建导出 demo List list = Arrays.asList( - CrmCustomerImportExcelVO.builder().name("芋道").industryId(1).level(1).source(1).mobile("15601691300").telephone("") - .qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") - .areaId(null).detailAddress("").build(), - CrmCustomerImportExcelVO.builder().name("源码").industryId(1).level(1).source(1).mobile("15601691300").telephone("") - .qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") - .areaId(null).detailAddress("").build() + CrmCustomerImportExcelVO.builder().name("芋道").industryId(1).level(1).source(1) + .mobile("15601691300").telephone("").qq("").wechat("").email("yunai@iocoder.cn") + .areaId(null).detailAddress("").remark("").build(), + CrmCustomerImportExcelVO.builder().name("源码").industryId(1).level(1).source(1) + .mobile("15601691300").telephone("").qq("").wechat("").email("yunai@iocoder.cn") + .areaId(null).detailAddress("").remark("").build() ); // 输出 ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerDistributeReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerDistributeReqVO.java similarity index 98% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerDistributeReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerDistributeReqVO.java index 24113ed12..16190baee 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerDistributeReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerDistributeReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java similarity index 96% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java index dda607147..4b21fff1c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -24,19 +24,6 @@ public class CrmCustomerImportExcelVO { @ExcelProperty("客户名称") private String name; - // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框 - @ExcelProperty(value = "所属行业", converter = DictConvert.class) - @DictFormat(CRM_CUSTOMER_INDUSTRY) - private Integer industryId; - - @ExcelProperty(value = "客户等级", converter = DictConvert.class) - @DictFormat(CRM_CUSTOMER_LEVEL) - private Integer level; - - @ExcelProperty(value = "客户来源", converter = DictConvert.class) - @DictFormat(CRM_CUSTOMER_SOURCE) - private Integer source; - @ExcelProperty("手机") private String mobile; @@ -52,12 +39,6 @@ public class CrmCustomerImportExcelVO { @ExcelProperty("邮箱") private String email; - @ExcelProperty("客户描述") - private String description; - - @ExcelProperty("备注") - private String remark; - // TODO @puhui999:需要选择省市区,需要研究下,怎么搞合理点; @ExcelProperty("地区编号") private Integer areaId; @@ -65,4 +46,20 @@ public class CrmCustomerImportExcelVO { @ExcelProperty("详细地址") private String detailAddress; + // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框 + @ExcelProperty(value = "所属行业", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @ExcelProperty(value = "客户等级", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_LEVEL) + private Integer level; + + @ExcelProperty(value = "客户来源", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_SOURCE) + private Integer source; + + @ExcelProperty("备注") + private String remark; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportReqVO.java similarity index 98% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportReqVO.java index a396dc50b..3f31b9732 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportRespVO.java similarity index 98% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportRespVO.java index de35b7b92..dda5bc5d1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerLockReqVO.java similarity index 97% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerLockReqVO.java index 1cf9ff382..10bf2e10a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerLockReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java similarity index 99% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java index 15b0529e6..73af5d6b1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; 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/customer/vo/CrmCustomerRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java similarity index 88% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java index 031bc66c1..236129918 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -7,12 +7,9 @@ import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - @Schema(description = "管理后台 - CRM 客户 Response VO") @Data @ExcelIgnoreUnannotated @@ -31,6 +28,28 @@ public class CrmCustomerRespVO { @DictFormat(DictTypeConstants.BOOLEAN_STRING) private Boolean followUpStatus; + @Schema(description = "最后跟进时间") + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; + + @Schema(description = "最后跟进内容", example = "吃饭、睡觉、打逗逗") + @ExcelProperty("最后跟进内容") + private String contactLastContent; + + @Schema(description = "下次联系时间") + @ExcelProperty("下次联系时间") + private LocalDateTime contactNextTime; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("负责人的用户编号") + private Long ownerUserId; + @Schema(description = "负责人名字", example = "25682") + @ExcelProperty("负责人名字") + private String ownerUserName; + @Schema(description = "负责人部门") + @ExcelProperty("负责人部门") + private String ownerUserDeptName; + @Schema(description = "锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") @ExcelProperty(value = "锁定状态", converter = DictConvert.class) @DictFormat(DictTypeConstants.BOOLEAN_STRING) @@ -41,6 +60,36 @@ public class CrmCustomerRespVO { @DictFormat(DictTypeConstants.BOOLEAN_STRING) private Boolean dealStatus; + @Schema(description = "手机", example = "25682") + @ExcelProperty("手机") + private String mobile; + + @Schema(description = "电话", example = "25682") + @ExcelProperty("电话") + private String telephone; + + @Schema(description = "QQ", example = "25682") + @ExcelProperty("QQ") + private String qq; + + @Schema(description = "wechat", example = "25682") + @ExcelProperty("wechat") + private String wechat; + + @Schema(description = "email", example = "25682") + @ExcelProperty("email") + private String email; + + @Schema(description = "地区编号", example = "1024") + @ExcelProperty("地区编号") + private Integer areaId; + @Schema(description = "地区名称", example = "北京市") + @ExcelProperty("地区名称") + private String areaName; + @Schema(description = "详细地址", example = "北京市成华大道") + @ExcelProperty("详细地址") + private String detailAddress; + @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") @ExcelProperty(value = "所属行业", converter = DictConvert.class) @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY) @@ -56,59 +105,10 @@ public class CrmCustomerRespVO { @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) private Integer source; - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("手机") - private String mobile; - - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("电话") - private String telephone; - - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("QQ") - private String qq; - - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("wechat") - private String wechat; - - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("email") - private String email; - @Schema(description = "负责人的用户编号", example = "25682") @ExcelProperty("备注") private String remark; - @Schema(description = "负责人的用户编号", example = "25682") - @ExcelProperty("负责人的用户编号") - private Long ownerUserId; - @Schema(description = "负责人名字", example = "25682") - @ExcelProperty("负责人名字") - private String ownerUserName; - @Schema(description = "负责人部门") - @ExcelProperty("负责人部门") - private String ownerUserDeptName; - - @Schema(description = "地区编号", example = "1024") - @ExcelProperty("地区编号") - private Integer areaId; - @Schema(description = "地区名称", example = "北京市") - @ExcelProperty("地区名称") - private String areaName; - @Schema(description = "详细地址", example = "北京市成华大道") - @ExcelProperty("详细地址") - private String detailAddress; - - @Schema(description = "最后跟进时间") - @ExcelProperty("最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @ExcelProperty("下次联系时间") - private LocalDateTime contactNextTime; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") private LocalDateTime createTime; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerSaveReqVO.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerSaveReqVO.java index b8e3d244a..bf4a4f00f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.framework.common.validation.Mobile; @@ -13,6 +13,7 @@ import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; @@ -34,19 +35,14 @@ public class CrmCustomerSaveReqVO { @NotEmpty(message = "客户名称不能为空") private String name; - @Schema(description = "所属行业", example = "1") - @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME) - @DictFormat(CRM_CUSTOMER_INDUSTRY) - private Integer industryId; + @Schema(description = "下次联系时间") + @DiffLogField(name = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime contactNextTime; - @Schema(description = "客户等级", example = "2") - @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME) - @InEnum(CrmCustomerLevelEnum.class) - private Integer level; - - @Schema(description = "客户来源", example = "3") - @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME) - private Integer source; + @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @NotNull(message = "负责人的用户编号不能为空") + private Long ownerUserId; @Schema(description = "手机", example = "18000000000") @DiffLogField(name = "手机") @@ -74,15 +70,6 @@ public class CrmCustomerSaveReqVO { @Size(max = 255, message = "邮箱长度不能超过 255 个字符") private String email; - @Schema(description = "客户描述", example = "任意文字") - @DiffLogField(name = "客户描述") - @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") - private String description; - - @Schema(description = "备注", example = "随便") - @DiffLogField(name = "备注") - private String remark; - @Schema(description = "地区编号", example = "20158") @DiffLogField(name = "地区编号", function = SysAreaParseFunction.NAME) private Integer areaId; @@ -91,12 +78,22 @@ public class CrmCustomerSaveReqVO { @DiffLogField(name = "详细地址") private String detailAddress; - @Schema(description = "下次联系时间") - @DiffLogField(name = "下次联系时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime contactNextTime; + @Schema(description = "所属行业", example = "1") + @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME) + @DictFormat(CRM_CUSTOMER_INDUSTRY) + private Integer industryId; - @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - private Long ownerUserId; + @Schema(description = "客户等级", example = "2") + @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME) + @InEnum(CrmCustomerLevelEnum.class) + private Integer level; + + @Schema(description = "客户来源", example = "3") + @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME) + private Integer source; + + @Schema(description = "备注", example = "随便") + @DiffLogField(name = "备注") + private String remark; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerTransferReqVO.java similarity index 99% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerTransferReqVO.java index 9bdc43532..e62a84fd7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerTransferReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java deleted file mode 100644 index 6a6642968..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.customer; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; - -/** - * 客户 Convert - * - * @author Wanwan - */ -@Mapper -public interface CrmCustomerConvert { - - CrmCustomerConvert INSTANCE = Mappers.getMapper(CrmCustomerConvert.class); - - default CrmCustomerRespVO convert(CrmCustomerDO customer, Map userMap, - Map deptMap) { - CrmCustomerRespVO customerResp = BeanUtils.toBean(customer, CrmCustomerRespVO.class); - setUserInfo(customerResp, userMap, deptMap); - return customerResp; - } - - default PageResult convertPage(PageResult pageResult, Map userMap, - Map deptMap, Map poolDayMap) { - PageResult result = BeanUtils.toBean(pageResult, CrmCustomerRespVO.class); - result.getList().forEach(item -> { - setUserInfo(item, userMap, deptMap); - findAndThen(poolDayMap, item.getId(), item::setPoolDay); - }); - return result; - } - - /** - * 设置用户信息 - * - * @param customer CRM 客户 Response VO - * @param userMap 用户信息 map - * @param deptMap 用户部门信息 map - */ - static void setUserInfo(CrmCustomerRespVO customer, Map userMap, Map deptMap) { - customer.setAreaName(AreaUtils.format(customer.getAreaId())); - findAndThen(userMap, customer.getOwnerUserId(), user -> { - customer.setOwnerUserName(user.getNickname()); - findAndThen(deptMap, user.getDeptId(), dept -> customer.setOwnerUserDeptName(dept.getName())); - }); - findAndThen(userMap, Long.parseLong(customer.getCreator()), user -> customer.setCreatorName(user.getNickname())); - } - - @Mapping(target = "bizId", source = "reqVO.id") - CrmPermissionTransferReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId); - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index a39e92bdb..e59311d0a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -57,10 +57,6 @@ public class CrmCustomerDO extends BaseDO { * 关联 AdminUserDO 的 id 字段 */ private Long ownerUserId; - /** - * 最后接收时间 - */ - private LocalDateTime receiveTime; /** * 锁定状态 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 7f649bc6c..95478df9d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -6,7 +6,7 @@ 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.customer.vo.CrmCustomerPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 935524948..fe10a133d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 5e675e0ed..8d7f47859 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; @@ -37,6 +37,14 @@ public interface CrmCustomerService { */ void updateCustomer(@Valid CrmCustomerSaveReqVO updateReqVO); + /** + * 更新客户的跟进状态 + * + * @param id 编号 + * @param dealStatus 跟进状态 + */ + void updateCustomerDealStatus(Long id, Boolean dealStatus); + /** * 删除客户 * 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 8cb25d9ae..ce88a89bc 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 @@ -10,8 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; -import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; @@ -27,6 +26,7 @@ import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 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.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.mzt.logapi.context.LogRecordContext; @@ -137,6 +137,26 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { LogRecordContext.putVariable("customerName", oldCustomer.getName()); } + @Override + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUB_TYPE, bizNo = "{{#id}}", + success = CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + public void updateCustomerDealStatus(Long id, Boolean dealStatus) { + // 1.1 校验存在 + CrmCustomerDO customer = validateCustomerExists(id); + // 1.2 校验是否重复操作 + if (Objects.equals(customer.getDealStatus(), dealStatus)) { + throw exception(CUSTOMER_UPDATE_DEAL_STATUS_FAIL); + } + + // 2. 更新客户的成交状态 + customerMapper.updateById(new CrmCustomerDO().setId(id).setDealStatus(dealStatus)); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("customerName", customer.getName()); + LogRecordContext.putVariable("dealStatus", dealStatus); + } + @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_DELETE_SUB_TYPE, bizNo = "{{#id}}", @@ -146,7 +166,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 1.1 校验存在 CrmCustomerDO customer = validateCustomerExists(id); // 1.2 检查引用 - checkCustomerReference(id); + validateCustomerReference(id); // 2. 删除 customerMapper.deleteById(id); @@ -162,7 +182,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { * * @param id 客户编号 */ - private void checkCustomerReference(Long id) { + private void validateCustomerReference(Long id) { if (contactService.getContactCountByCustomerId(id) > 0) { throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTACT.getName()); } @@ -186,8 +206,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { validateCustomerExceedOwnerLimit(reqVO.getNewOwnerUserId(), 1); // 2.1 数据权限转移 - permissionService.transferPermission( - CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); + permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 转移后重新设置负责人 customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); @@ -230,8 +250,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { success = CRM_CUSTOMER_CREATE_SUCCESS) public Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId) { // 1. 插入客户 - CrmCustomerDO customer = BeanUtils.toBean(customerCreateReq, CrmCustomerDO.class).setOwnerUserId(userId) - .setLockStatus(false).setDealStatus(false).setReceiveTime(LocalDateTime.now()); + CrmCustomerDO customer = BeanUtils.toBean(customerCreateReq, CrmCustomerDO.class).setOwnerUserId(userId); customerMapper.insert(customer); // 2. 创建数据权限 From b444312ea888baa950a829c1105445ab463a9eaf Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 20 Feb 2024 19:07:48 +0800 Subject: [PATCH 13/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=AE=A2=E6=88=B7=E7=9A=84=E8=BF=87=E6=9C=9F=E5=88=B0?= =?UTF-8?q?=E5=85=AC=E6=B5=B7=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 2 + .../admin/clue/CrmClueController.java | 5 +- .../admin/customer/CrmCustomerController.java | 70 ++++------- .../dataobject/customer/CrmCustomerDO.java | 4 + .../dal/mysql/customer/CrmCustomerMapper.java | 112 ++++++++++-------- .../crm/service/clue/CrmClueServiceImpl.java | 5 +- .../service/customer/CrmCustomerService.java | 60 +++++----- .../customer/CrmCustomerServiceImpl.java | 94 ++++++++------- .../CrmFollowUpRecordServiceImpl.java | 18 +-- 9 files changed, 187 insertions(+), 183 deletions(-) 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 7301cf8b1..0299a8d31 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 @@ -45,6 +45,8 @@ public interface LogRecordConstants { String CRM_CUSTOMER_IMPORT_SUCCESS = "{{#isUpdate ? '导入并更新了客户【'+ #customer.name +'】' : '导入了客户【'+ #customer.name +'】'}}"; String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUB_TYPE = "更新客户成交状态"; String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUCCESS = "更新了客户【{{#customerName}}】的成交状态为【{{#dealStatus ? '已成交' : '未成交'}}】"; + String CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE = "客户跟进"; + String CRM_CUSTOMER_FOLLOW_UP_SUCCESS = "客户跟进【{{#customerName}}】"; // ======================= CRM_CUSTOMER_LIMIT_CONFIG 客户限制配置 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index 044b39d34..ecfef7d01 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -43,6 +43,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static java.util.Collections.singletonList; @Tag(name = "管理后台 - 线索") @RestController @@ -93,11 +94,11 @@ public class CrmClueController { return success(buildClueDetail(clue)); } - public CrmClueRespVO buildClueDetail(CrmClueDO clue) { + private CrmClueRespVO buildClueDetail(CrmClueDO clue) { if (clue == null) { return null; } - return buildClueDetailList(Collections.singletonList(clue)).get(0); + return buildClueDetailList(singletonList(clue)).get(0); } @GetMapping("/page") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index bf25238a2..034cb5ffc 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; @@ -15,7 +15,6 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -40,13 +39,11 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED; import static java.util.Collections.singletonList; @Tag(name = "管理后台 - CRM 客户") @@ -123,6 +120,7 @@ public class CrmCustomerController { @Operation(summary = "获得客户分页") @PreAuthorize("@ss.hasPermission('crm:customer:query')") public CommonResult> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { + customerService.autoPutCustomerPool(); // 1. 查询客户分页 PageResult pageResult = customerService.getCustomerPage(pageVO, getLoginUserId()); if (CollUtil.isEmpty(pageResult.getList())) { @@ -159,45 +157,21 @@ public class CrmCustomerController { }); } - // TODO @芋艿:需要 review 下 - @GetMapping("/put-in-pool-remind-page") + @GetMapping("/put-pool-remind-page") @Operation(summary = "获得待进入公海客户分页") @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getPutInPoolRemindCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { - // 获取公海配置 TODO @dbh52:合并到 getPutInPoolRemindCustomerPage 会更合适哈; - CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); - if (ObjUtil.isNull(poolConfigDO) - || Boolean.FALSE.equals(poolConfigDO.getEnabled()) - || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { - throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); - } - + public CommonResult> getPutPoolRemindCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { // 1. 查询客户分页 - PageResult pageResult = customerService.getPutInPoolRemindCustomerPage(pageVO, poolConfigDO, getLoginUserId()); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty(pageResult.getTotal())); - } - + PageResult pageResult = customerService.getPutPoolRemindCustomerPage(pageVO, getLoginUserId()); // 2. 拼接数据 return success(new PageResult<>(buildCustomerDetailList(pageResult.getList()), pageResult.getTotal())); } - @GetMapping("/put-in-pool-remind-count") + @GetMapping("/put-pool-remind-count") @Operation(summary = "获得待进入公海客户数量") @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult getPutInPoolRemindCustomerCount() { - // 获取公海配置 - CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); - if (ObjUtil.isNull(poolConfigDO) - || Boolean.FALSE.equals(poolConfigDO.getEnabled()) - || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { - throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); - } - CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO() - .setPool(null) - .setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY) - .setSceneType(CrmSceneTypeEnum.OWNER.getType()); - return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId())); + public CommonResult getPutPoolRemindCustomerCount() { + return success(customerService.getPutPoolRemindCustomerCount(getLoginUserId())); } @GetMapping("/today-customer-count") @@ -225,24 +199,26 @@ public class CrmCustomerController { if (poolConfig == null || !poolConfig.getEnabled()) { return MapUtil.empty(); } + list = CollectionUtils.filterList(list, customer -> { + // 特殊:如果没负责人,则说明已经在公海,不用计算 + if (customer.getOwnerUserId() == null) { + return false; + } + // 已成交 or 已锁定,不进入公海 + return !customer.getDealStatus() && !customer.getLockStatus(); + }); return convertMap(list, CrmCustomerDO::getId, customer -> { - // TODO 芋艿:这样计算,貌似有点问题 // 1.1 未成交放入公海天数 - long dealExpireDay = 0; - if (!customer.getDealStatus()) { - dealExpireDay = poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime()); - } - if (dealExpireDay < 0) { - dealExpireDay = 0; - } + long dealExpireDay = poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getOwnerTime()); // 1.2 未跟进放入公海天数 - LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); - long contactExpireDay = poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime); - if (contactExpireDay < 0) { - contactExpireDay = 0; + LocalDateTime lastTime = customer.getOwnerTime(); + if (customer.getContactLastTime() != null && customer.getContactLastTime().isAfter(lastTime)) { + lastTime = customer.getContactLastTime(); } + long contactExpireDay = poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime); // 2. 返回最小的天数 - return Math.min(dealExpireDay, contactExpireDay); + long poolDay = Math.min(dealExpireDay, contactExpireDay); + return poolDay > 0 ? poolDay : 0; }); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index e59311d0a..76d511115 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -57,6 +57,10 @@ public class CrmCustomerDO extends BaseDO { * 关联 AdminUserDO 的 id 字段 */ private Long ownerUserId; + /** + * 成为负责人的时间 + */ + private LocalDateTime ownerTime; /** * 锁定状态 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 95478df9d..c70d14900 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -31,40 +31,6 @@ import java.util.List; @Mapper public interface CrmCustomerMapper extends BaseMapperX { - private static MPJLambdaWrapperX buildPutInPoolRemindCustomerWrapper(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfigDO, Long userId) { - MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); - - // 锁定状态不需要提醒 - query.ne(CrmCustomerDO::getLockStatus, true); - - // 情况一:未成交提醒日期区间 - Integer dealExpireDays = poolConfigDO.getDealExpireDays(); - LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) - .minusDays(dealExpireDays); - LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) - .minusDays(Math.max(dealExpireDays - poolConfigDO.getNotifyDays(), 0)); - // 情况二:未跟进提醒日期区间 - Integer contactExpireDays = poolConfigDO.getContactExpireDays(); - LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) - .minusDays(contactExpireDays); - LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) - .minusDays(Math.max(contactExpireDays - poolConfigDO.getNotifyDays(), 0)); - query - // 情况一:1. 未成交放入公海提醒 - .eq(CrmCustomerDO::getDealStatus, false) - .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate) - // 情况二:未跟进放入公海提醒 - .or() // 2.1 contactLastTime 为空 TODO 芋艿:这个要不要搞个默认值; - .isNull(CrmCustomerDO::getContactLastTime) - .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate) - .or() // 2.2 ContactLastTime 不为空 - .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate); - return query; - } - default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { return selectCount(new LambdaUpdateWrapper() .eq(CrmCustomerDO::getLockStatus, lockStatus) @@ -124,30 +90,80 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectJoinList(CrmCustomerDO.class, query); } - default List selectListByLockAndNotPool(Boolean lockStatus) { - return selectList(new LambdaQueryWrapper() - .eq(CrmCustomerDO::getLockStatus, lockStatus) - .gt(CrmCustomerDO::getOwnerUserId, 0)); - } - default CrmCustomerDO selectByCustomerName(String name) { return selectOne(CrmCustomerDO::getName, name); } - default PageResult selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, - CrmCustomerPoolConfigDO poolConfigDO, - Long userId) { - final MPJLambdaWrapperX query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId); + default PageResult selectPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, + CrmCustomerPoolConfigDO poolConfig, + Long userId) { + final MPJLambdaWrapperX query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, userId); return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class)); } - default Long selectPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, - CrmCustomerPoolConfigDO poolConfigDO, - Long userId) { - final MPJLambdaWrapperX query = buildPutInPoolRemindCustomerWrapper(pageReqVO, poolConfigDO, userId); + default Long selectPutPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, + CrmCustomerPoolConfigDO poolConfigDO, + Long userId) { + final MPJLambdaWrapperX query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfigDO, userId); return selectCount(query); } + private static MPJLambdaWrapperX buildPutPoolRemindCustomerQuery(CrmCustomerPageReqVO pageReqVO, + CrmCustomerPoolConfigDO poolConfig, + Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); + + // 未锁定 + 未成交 + query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); + + // 情况一:未成交提醒日期区间 + Integer dealExpireDays = poolConfig.getDealExpireDays(); + LocalDateTime startDealRemindTime = LocalDateTime.now().minusDays(dealExpireDays); + LocalDateTime endDealRemindTime = LocalDateTime.now() + .minusDays(Math.max(dealExpireDays - poolConfig.getNotifyDays(), 0)); + // 情况二:未跟进提醒日期区间 + Integer contactExpireDays = poolConfig.getContactExpireDays(); + LocalDateTime startContactRemindTime = LocalDateTime.now().minusDays(contactExpireDays); + LocalDateTime endContactRemindTime = LocalDateTime.now() + .minusDays(Math.max(contactExpireDays - poolConfig.getNotifyDays(), 0)); + query.and(q -> { + // 情况一:成交超时提醒 + q.between(CrmCustomerDO::getOwnerTime, startDealRemindTime, endDealRemindTime) + // 情况二:跟进超时提醒 + .or(w -> w.between(CrmCustomerDO::getOwnerTime, startContactRemindTime, endContactRemindTime) + .and(p -> p.between(CrmCustomerDO::getContactLastTime, startContactRemindTime, endContactRemindTime) + .or().isNull(CrmCustomerDO::getContactLastTime))); + }); + return query; + } + + /** + * 获得需要过期到公海的客户列表 + * + * @return 客户列表 + */ + default List selectListByAutoPool(CrmCustomerPoolConfigDO poolConfig) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.gt(CrmCustomerDO::getOwnerUserId, 0); + // 未锁定 + 未成交 + query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); + // 已经超时 + LocalDateTime dealExpireTime = LocalDateTime.now().minusDays(poolConfig.getDealExpireDays()); + LocalDateTime contactExpireTime = LocalDateTime.now().minusDays(poolConfig.getContactExpireDays()); + query.and(q -> { + // 情况一:成交超时 + q.lt(CrmCustomerDO::getOwnerTime, dealExpireTime) + // 情况二:跟进超时 + .or(w -> w.lt(CrmCustomerDO::getOwnerTime, contactExpireTime) + .and(p -> p.lt(CrmCustomerDO::getContactLastTime, contactExpireTime) + .or().isNull(CrmCustomerDO::getContactLastTime))); + }); + return selectList(query); + } + default Long selectTodayCustomerCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index fe10a133d..7251eee26 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -78,8 +78,7 @@ public class CrmClueServiceImpl implements CrmClueService { adminUserApi.validateUser(createReqVO.getOwnerUserId()); // 2. 插入线索 - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class) - .setContactLastTime(LocalDateTime.now()); + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); clueMapper.insert(clue); // 3. 创建数据权限 @@ -129,7 +128,7 @@ public class CrmClueServiceImpl implements CrmClueService { // 校验线索是否存在 CrmClueDO oldClue = validateClueExists(id); - // 更新 + // 更新线索 clueMapper.updateById(new CrmClueDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime) .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 8d7f47859..f4858ce53 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -3,11 +3,10 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; @@ -45,6 +44,15 @@ public interface CrmCustomerService { */ void updateCustomerDealStatus(Long id, Boolean dealStatus); + /** + * 更新客户相关的跟进信息 + * + * @param id 编号 + * @param contactNextTime 下次联系时间 + * @param contactLastContent 最后联系内容 + */ + void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); + /** * 删除客户 * @@ -88,6 +96,23 @@ public interface CrmCustomerService { */ PageResult getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId); + /** + * 获得放入公海提醒的客户分页 + * + * @param pageVO 分页查询 + * @param userId 用户编号 + * @return 客户分页 + */ + PageResult getPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, Long userId); + + /** + * 获得待进入公海的客户数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getPutPoolRemindCustomerCount(Long userId); + /** * 校验客户是否存在 * @@ -111,13 +136,6 @@ public interface CrmCustomerService { */ void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId); - /** - * 更新客户相关更进信息 - * - * @param customerUpdateFollowUpReqBO 请求 - */ - void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO); - /** * 创建客户 * @@ -161,18 +179,6 @@ public interface CrmCustomerService { */ int autoPutCustomerPool(); - /** - * 获得放入公海提醒的客户分页数据 - * - * @param pageVO 分页查询 - * @param poolConfigDO 公海配置 - * @param userId 用户编号 - * @return 客户分页 - */ - PageResult getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, - CrmCustomerPoolConfigDO poolConfigDO, - Long userId); - /** * 获得今日需联系客户数量 * @@ -181,18 +187,6 @@ public interface CrmCustomerService { */ Long getTodayCustomerCount(Long userId); - /** - * 获得待进入公海的客户数量 - * - * @param pageVO 分页查询 - * @param poolConfigDO 公海配置 - * @param userId 用户编号 - * @return 提醒数量 - */ - Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageVO, - CrmCustomerPoolConfigDO poolConfigDO, - Long userId); - /** * 获得分配给我的客户数量 * 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 ce88a89bc..37d94abe8 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 @@ -8,7 +8,6 @@ import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -16,6 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfi import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; @@ -23,7 +23,6 @@ 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.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; @@ -43,7 +42,6 @@ import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; @@ -114,7 +112,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { */ private static CrmCustomerDO initCustomer(Object customer, Long ownerUserId) { return BeanUtils.toBean(customer, CrmCustomerDO.class).setOwnerUserId(ownerUserId) - .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); + .setOwnerTime(LocalDateTime.now()); } @Override @@ -157,6 +155,22 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { LogRecordContext.putVariable("dealStatus", dealStatus); } + @Override + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}", + success = CRM_CUSTOMER_FOLLOW_UP_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + public void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { + // 1.1 校验存在 + CrmCustomerDO customer = validateCustomerExists(id); + + // 2. 更新客户的跟进信息 + customerMapper.updateById(new CrmCustomerDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime) + .setContactLastTime(LocalDateTime.now())); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("customerName", customer.getName()); + } + @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_DELETE_SUB_TYPE, bizNo = "{{#id}}", @@ -168,7 +182,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 1.2 检查引用 validateCustomerReference(id); - // 2. 删除 + // 2. 删除客户 customerMapper.deleteById(id); // 3. 删除数据权限 permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); @@ -209,7 +223,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CUSTOMER.getType(), reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 转移后重新设置负责人 - customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); + customerMapper.updateById(new CrmCustomerDO().setId(reqVO.getId()) + .setOwnerUserId(reqVO.getNewOwnerUserId()).setOwnerTime(LocalDateTime.now())); // 3. 记录转移日志 LogRecordContext.putVariable("customer", customer); @@ -226,7 +241,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { if (customer.getLockStatus().equals(lockReqVO.getLockStatus())) { throw exception(customer.getLockStatus() ? CUSTOMER_LOCK_FAIL_IS_LOCK : CUSTOMER_UNLOCK_FAIL_IS_UNLOCK); } - // 1.3 校验锁定上限。 + // 1.3 校验锁定上限 if (lockReqVO.getLockStatus()) { validateCustomerExceedLockLimit(userId); } @@ -239,11 +254,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { LogRecordContext.putVariable("customer", customer); } - @Override - public void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO) { - customerMapper.updateById(BeanUtils.toBean(customerUpdateFollowUpReqBO, CrmCustomerDO.class).setId(customerUpdateFollowUpReqBO.getBizId())); - } - @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#customer.id}}", @@ -263,7 +273,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public CrmCustomerImportRespVO importCustomerList(List importCustomers, CrmCustomerImportReqVO importReqVO) { + public CrmCustomerImportRespVO importCustomerList(List importCustomers, + CrmCustomerImportReqVO importReqVO) { if (CollUtil.isEmpty(importCustomers)) { throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); } @@ -383,12 +394,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 1.4 校验负责人是否到达上限 validateCustomerExceedOwnerLimit(ownerUserId, customers.size()); - // 2.1 领取公海数据 + // 2. 领取公海数据 List updateCustomers = new ArrayList<>(); List createPermissions = new ArrayList<>(); customers.forEach(customer -> { // 2.1. 设置负责人 - updateCustomers.add(new CrmCustomerDO().setId(customer.getId()).setOwnerUserId(ownerUserId)); + updateCustomers.add(new CrmCustomerDO().setId(customer.getId()) + .setOwnerUserId(ownerUserId).setOwnerTime(LocalDateTime.now())); // 2.2. 创建负责人数据权限 createPermissions.add(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(ownerUserId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); @@ -415,34 +427,23 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { if (poolConfig == null || !poolConfig.getEnabled()) { return 0; } - // 1.1 获取没有锁定的不在公海的客户 - List customerList = customerMapper.selectListByLockAndNotPool(Boolean.FALSE); - // TODO @puhui999:下面也搞到 sql 里去哈;写 or 查询,问题不大的;低 393 到 402;原因是,避免无用的太多数据查询到 java 进程里; - List poolCustomerList = new ArrayList<>(); - poolCustomerList.addAll(filterList(customerList, customer -> - !customer.getDealStatus() && (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0)); - poolCustomerList.addAll(filterList(customerList, customer -> { - if (!customer.getDealStatus()) { // 这里只处理成交的 - return false; - } - LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); - return (poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime)) <= 0; - })); - + // 1. 获得需要放到的客户列表 + List customerList = customerMapper.selectListByAutoPool(poolConfig); // 2. 逐个放入公海 int count = 0; - for (CrmCustomerDO customer : poolCustomerList) { + for (CrmCustomerDO customer : customerList) { try { getSelf().putCustomerPool(customer); count++; } catch (Throwable e) { - log.error("[autoPutCustomerPool][Customer 客户({}) 放入公海异常]", customer.getId(), e); + log.error("[autoPutCustomerPool][客户({}) 放入公海异常]", customer.getId(), e); } } return count; } - private void putCustomerPool(CrmCustomerDO customer) { + @Transactional // 需要 protected 修饰,因为需要在事务中调用 + protected void putCustomerPool(CrmCustomerDO customer) { // 1. 设置负责人为 NULL int updateOwnerUserIncr = customerMapper.updateOwnerUserIdById(customer.getId(), null); if (updateOwnerUserIncr == 0) { @@ -486,17 +487,29 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public PageResult getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, - CrmCustomerPoolConfigDO poolConfigDO, - Long userId) { - return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId); + public PageResult getPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, Long userId) { + CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig(); + if (ObjUtil.isNull(poolConfig) + || Boolean.FALSE.equals(poolConfig.getEnabled()) + || Boolean.FALSE.equals(poolConfig.getNotifyEnabled())) { + return PageResult.empty(); + } + return customerMapper.selectPutPoolRemindCustomerPage(pageVO, poolConfig, userId); } @Override - public Long getPutInPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, - CrmCustomerPoolConfigDO poolConfigDO, - Long userId) { - return customerMapper.selectPutInPoolRemindCustomerCount(pageReqVO, poolConfigDO, userId); + public Long getPutPoolRemindCustomerCount(Long userId) { + CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig(); + if (ObjUtil.isNull(poolConfig) + || Boolean.FALSE.equals(poolConfig.getEnabled()) + || Boolean.FALSE.equals(poolConfig.getNotifyEnabled())) { + return 0L; + } + CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO() + .setPool(null) + .setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY) + .setSceneType(CrmSceneTypeEnum.OWNER.getType()); + return customerMapper.selectPutPoolRemindCustomerCount(pageVO, poolConfig, userId); } @Override @@ -596,7 +609,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } } - /** * 获得自身的代理对象,解决 AOP 生效问题 * 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 5cfdbb1dc..00242b19c 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 @@ -72,24 +72,24 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { CrmFollowUpRecordDO followUpRecord = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class); crmFollowUpRecordMapper.insert(followUpRecord); - LocalDateTime now = LocalDateTime.now(); - CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()) - .setContactLastTime(now).setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent()); // 2. 更新 bizId 对应的记录; - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 + CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()) + .setContactLastTime(LocalDateTime.now()) + .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent()); + if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); } - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 clueService.updateClueFollowUp(followUpRecord.getId(), followUpRecord.getNextTime(), followUpRecord.getContent()); } - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); } - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息 + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息 contractService.updateContractFollowUp(updateFollowUpReqBO); } - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息 - customerService.updateCustomerFollowUp(updateFollowUpReqBO); + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息 + customerService.updateCustomerFollowUp(followUpRecord.getBizId(), followUpRecord.getNextTime(), followUpRecord.getContent()); } // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent From 4b41c3c69230cc49913c7612f29bc5abfab69dc0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 20 Feb 2024 20:19:59 +0800 Subject: [PATCH 14/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=AE=A2=E6=88=B7=E7=9A=84=20backlog=20=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/customer/CrmCustomerController.java | 15 +++-- .../dal/mysql/customer/CrmCustomerMapper.java | 24 +++---- .../service/customer/CrmCustomerService.java | 34 +++++----- .../customer/CrmCustomerServiceImpl.java | 63 +++++++++---------- 4 files changed, 65 insertions(+), 71 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 034cb5ffc..e567aeecd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -174,15 +174,15 @@ public class CrmCustomerController { return success(customerService.getPutPoolRemindCustomerCount(getLoginUserId())); } - @GetMapping("/today-customer-count") + @GetMapping("/today-contact-count") @Operation(summary = "获得今日需联系客户数量") @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult getTodayCustomerCount() { - return success(customerService.getTodayCustomerCount(getLoginUserId())); + public CommonResult getTodayContactCustomerCount() { + return success(customerService.getTodayContactCustomerCount(getLoginUserId())); } - @GetMapping("/follow-customer-count") - @Operation(summary = "获得分配给我的客户数量") + @GetMapping("/follow-count") + @Operation(summary = "获得分配给我、待跟进的线索数量的客户数量") @PreAuthorize("@ss.hasPermission('crm:customer:query')") public CommonResult getFollowCustomerCount() { return success(customerService.getFollowCustomerCount(getLoginUserId())); @@ -222,9 +222,9 @@ public class CrmCustomerController { }); } - @GetMapping(value = "/list-all-simple") + @GetMapping(value = "/simple-list") @Operation(summary = "获取客户精简信息列表", description = "只包含有读权限的客户,主要用于前端的下拉选项") - public CommonResult> getSimpleDeptList() { + public CommonResult> getCustomerSimpleList() { CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO(); reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 List list = customerService.getCustomerPage(reqVO, getLoginUserId()).getList(); @@ -232,7 +232,6 @@ public class CrmCustomerController { new CrmCustomerRespVO().setId(customer.getId()).setName(customer.getName()))); } - // TODO @puhui999:公海的导出,前端可以接下 @GetMapping("/export-excel") @Operation(summary = "导出客户 Excel") @PreAuthorize("@ss.hasPermission('crm:customer:export')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index c70d14900..f9495323a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -49,11 +49,11 @@ public interface CrmCustomerMapper extends BaseMapperX { .set(CrmCustomerDO::getOwnerUserId, ownerUserId)); } - default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { + default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType(), pageReqVO.getPool()); // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class) .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) @@ -81,10 +81,10 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } - default List selectBatchIds(Collection ids, Long userId) { + default List selectBatchIds(Collection ids, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, ownerUserId); // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class).in(CrmCustomerDO::getId, ids).orderByDesc(CrmCustomerDO::getId); return selectJoinList(CrmCustomerDO.class, query); @@ -96,8 +96,8 @@ public interface CrmCustomerMapper extends BaseMapperX { default PageResult selectPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfig, - Long userId) { - final MPJLambdaWrapperX query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, userId); + Long ownerUserId) { + final MPJLambdaWrapperX query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, ownerUserId); return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class)); } @@ -110,11 +110,11 @@ public interface CrmCustomerMapper extends BaseMapperX { private static MPJLambdaWrapperX buildPutPoolRemindCustomerQuery(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfig, - Long userId) { + Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); + CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType(), null); // 未锁定 + 未成交 query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); @@ -164,11 +164,11 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectList(query); } - default Long selectTodayCustomerCount(Long userId) { + default Long selectCountByTodayContact(Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 今天需联系 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); @@ -176,11 +176,11 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectCount(query); } - default Long selectFollowCustomerCount(Long userId) { + default Long selectCountByFollow(Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); + CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 未跟进 query.eq(CrmClueDO::getFollowUpStatus, false); return selectCount(query); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index f4858ce53..969889143 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -113,6 +113,22 @@ public interface CrmCustomerService { */ Long getPutPoolRemindCustomerCount(Long userId); + /** + * 获得今日需联系客户数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getTodayContactCustomerCount(Long userId); + + /** + * 获得分配给我的客户数量 + * + * @param userId 用户编号 + * @return 提醒数量 + */ + Long getFollowCustomerCount(Long userId); + /** * 校验客户是否存在 * @@ -168,7 +184,7 @@ public interface CrmCustomerService { * * @param ids 要领取的客户编号数组 * @param ownerUserId 负责人 - * @param isReceive 是/否领取 + * @param isReceive 是/否领取;true - 领取;false - 分配 */ void receiveCustomer(List ids, Long ownerUserId, Boolean isReceive); @@ -179,20 +195,4 @@ public interface CrmCustomerService { */ int autoPutCustomerPool(); - /** - * 获得今日需联系客户数量 - * - * @param userId 用户编号 - * @return 提醒数量 - */ - Long getTodayCustomerCount(Long userId); - - /** - * 获得分配给我的客户数量 - * - * @param userId 用户编号 - * @return 提醒数量 - */ - Long getFollowCustomerCount(Long userId); - } 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 37d94abe8..d98edce24 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 @@ -18,7 +18,6 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; 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.contract.CrmContractService; @@ -191,23 +190,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { LogRecordContext.putVariable("customerName", customer.getName()); } - /** - * 校验客户是否被引用 - * - * @param id 客户编号 - */ - private void validateCustomerReference(Long id) { - if (contactService.getContactCountByCustomerId(id) > 0) { - throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTACT.getName()); - } - if (businessService.getBusinessCountByCustomerId(id) > 0) { - throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_BUSINESS.getName()); - } - if (contractService.getContractCountByCustomerId(id) > 0) { - throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTRACT.getName()); - } - } - @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", @@ -336,13 +318,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { LogRecordContext.putVariable("isUpdate", isUpdate); } - private void validateCustomerForCreate(CrmCustomerImportExcelVO importCustomer) { - // 校验客户名称不能为空 - if (StrUtil.isEmptyIfStr(importCustomer.getName())) { - throw exception(CUSTOMER_CREATE_NAME_NOT_NULL); - } - } - // ==================== 公海相关操作 ==================== @Override @@ -371,18 +346,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) public void receiveCustomer(List ids, Long ownerUserId, Boolean isReceive) { - if (!isReceive && !CrmPermissionUtils.isCrmAdmin()) { // 只有管理员可以分配 - throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.CRM_CUSTOMER.getName()); - } - // 1.1 校验存在 List customers = customerMapper.selectBatchIds(ids); if (customers.size() != ids.size()) { throw exception(CUSTOMER_NOT_EXISTS); } - // 1.2. 校验负责人是否存在 + // 1.2 校验负责人是否存在 adminUserApi.validateUserList(singletonList(ownerUserId)); - // 1.3. 校验状态 + // 1.3 校验状态 customers.forEach(customer -> { // 校验是否已有负责人 validateCustomerOwnerExists(customer, false); @@ -513,17 +484,41 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public Long getTodayCustomerCount(Long userId) { - return customerMapper.selectTodayCustomerCount(userId); + public Long getTodayContactCustomerCount(Long userId) { + return customerMapper.selectCountByTodayContact(userId); } @Override public Long getFollowCustomerCount(Long userId) { - return customerMapper.selectFollowCustomerCount(userId); + return customerMapper.selectCountByFollow(userId); } // ======================= 校验相关 ======================= + private void validateCustomerForCreate(CrmCustomerImportExcelVO importCustomer) { + // 校验客户名称不能为空 + if (StrUtil.isEmptyIfStr(importCustomer.getName())) { + throw exception(CUSTOMER_CREATE_NAME_NOT_NULL); + } + } + + /** + * 校验客户是否被引用 + * + * @param id 客户编号 + */ + private void validateCustomerReference(Long id) { + if (contactService.getContactCountByCustomerId(id) > 0) { + throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTACT.getName()); + } + if (businessService.getBusinessCountByCustomerId(id) > 0) { + throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_BUSINESS.getName()); + } + if (contractService.getContractCountByCustomerId(id) > 0) { + throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTRACT.getName()); + } + } + /** * 校验客户是否存在 * From 66a34a6d9022d12c820bbcdd8ca611213b85bb2f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 20 Feb 2024 21:18:45 +0800 Subject: [PATCH 15/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E8=81=94=E7=B3=BB=E4=BA=BA=E7=9A=84=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/CrmContactController.java | 84 +++++------ .../admin/contact/vo/CrmContactRespVO.java | 108 ++++++++------- .../admin/contact/vo/CrmContactSaveReqVO.java | 54 ++++---- .../admin/contract/CrmContractController.java | 2 +- .../followup/CrmFollowUpRecordController.java | 2 +- .../convert/contact/CrmContactConvert.java | 42 ------ .../dal/dataobject/contact/CrmContactDO.java | 131 +++++++++--------- .../dal/mysql/contact/CrmContactMapper.java | 5 +- .../service/contact/CrmContactService.java | 15 +- .../contact/CrmContactServiceImpl.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 1 - 11 files changed, 213 insertions(+), 233 deletions(-) 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 766adb02d..161f10299 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 @@ -2,24 +2,24 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.NumberUtil; 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.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.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; -import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +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; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import com.google.common.collect.Lists; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -37,12 +37,13 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static java.util.Collections.singletonList; @Tag(name = "管理后台 - CRM 联系人") @RestController @@ -60,6 +61,8 @@ public class CrmContactController { @Resource private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; @PostMapping("/create") @Operation(summary = "创建联系人") @@ -92,19 +95,14 @@ public class CrmContactController { @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult getContact(@RequestParam("id") Long id) { CrmContactDO contact = contactService.getContact(id); + return success(buildContactDetail(contact)); + } + + private CrmContactRespVO buildContactDetail(CrmContactDO contact) { if (contact == null) { - throw exception(ErrorCodeConstants.CONTACT_NOT_EXISTS); + return null; } - // 1. 获取用户名 - Map userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList( - NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId()))); - // 2. 获取客户信息 - List customerList = customerService.getCustomerList( - Collections.singletonList(contact.getCustomerId())); - // 3. 直属上级 - List parentContactList = contactService.getContactListByIds( - Collections.singletonList(contact.getParentId()), getLoginUserId()); - return success(CrmContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); + return buildContactDetailList(singletonList(contact)).get(0); } @GetMapping("/list-by-ids") @@ -112,7 +110,8 @@ public class CrmContactController { @Parameter(name = "ids", description = "编号", required = true, example = "[1024]") @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getContactListByIds(@RequestParam("ids") List ids) { - return success(BeanUtils.toBean(contactService.getContactListByIds(ids, getLoginUserId()), CrmContactRespVO.class)); + List list = contactService.getContactListByIds(ids, getLoginUserId()); + return success(BeanUtils.toBean(list, CrmContactRespVO.class)); } @GetMapping("/simple-all-list") @@ -129,7 +128,7 @@ public class CrmContactController { @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getContactPage(@Valid CrmContactPageReqVO pageVO) { PageResult pageResult = contactService.getContactPage(pageVO, getLoginUserId()); - return success(buildContactDetailPage(pageResult)); + return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/page-by-customer") @@ -137,7 +136,7 @@ public class CrmContactController { public CommonResult> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); PageResult pageResult = contactService.getContactPageByCustomerId(pageVO); - return success(buildContactDetailPage(pageResult)); + return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/export-excel") @@ -147,32 +146,39 @@ public class CrmContactController { public void exportContactExcel(@Valid CrmContactPageReqVO exportReqVO, HttpServletResponse response) throws IOException { exportReqVO.setPageNo(PAGE_SIZE_NONE); - PageResult pageResult = contactService.getContactPage(exportReqVO, getLoginUserId()); - ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class, - buildContactDetailPage(pageResult).getList()); + List list = contactService.getContactPage(exportReqVO, getLoginUserId()).getList(); + ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class, buildContactDetailList(list)); } - /** - * 构建详细的联系人分页结果 - * - * @param pageResult 简单的联系人分页结果 - * @return 详细的联系人分页结果 - */ - private PageResult buildContactDetailPage(PageResult pageResult) { - List contactList = pageResult.getList(); + private List buildContactDetailList(List contactList) { if (CollUtil.isEmpty(contactList)) { - return PageResult.empty(pageResult.getTotal()); + return Collections.emptyList(); } - // 1. 获取客户列表 - List crmCustomerDOList = customerService.getCustomerList( + // 1.1 获取客户列表 + Map customerMap = customerService.getCustomerMap( convertSet(contactList, CrmContactDO::getCustomerId)); - // 2. 获取创建人、负责人列表 + // 1.2 获取创建人、负责人列表 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); - // 3. 直属上级 - List parentContactList = contactService.getContactListByIds( - convertSet(contactList, CrmContactDO::getParentId), getLoginUserId()); - return CrmContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + // 1.3 直属上级 Map + Map parentContactMap = contactService.getContactMap( + convertSet(contactList, CrmContactDO::getParentId)); + // 2. 转换成 VO + return BeanUtils.toBean(contactList, CrmContactRespVO.class, contactVO -> { + contactVO.setAreaName(AreaUtils.format(contactVO.getAreaId())); + // 2.1 设置客户名称 + MapUtils.findAndThen(customerMap, contactVO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName())); + // 2.2 设置创建人、负责人名称 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(contactVO.getCreator()), + user -> contactVO.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, contactVO.getOwnerUserId(), user -> { + contactVO.setOwnerUserName(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> contactVO.setOwnerUserDeptName(dept.getName())); + }); + // 2.3 设置直属上级名称 + findAndThen(parentContactMap, contactVO.getParentId(), contact -> contactVO.setParentName(contact.getName())); + }); } @PutMapping("/transfer") @@ -183,7 +189,7 @@ public class CrmContactController { return success(true); } - // ================== 关联/取关联系人 =================== + // ================== 关联/取关商机 =================== @PostMapping("/create-business-list") @Operation(summary = "创建联系人与商机的关联") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java index d99ea703c..b2b1e8384 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java @@ -20,29 +20,36 @@ public class CrmContactRespVO { @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167") private Long id; - @Schema(description = "姓名", example = "芋艿") - @ExcelProperty(value = "姓名", order = 1) + @Schema(description = "联系人姓名", example = "芋艿") + @ExcelProperty(value = "联系人姓名", order = 1) private String name; @Schema(description = "客户编号", example = "10795") private Long customerId; + @ExcelProperty(value = "客户名称", order = 2) + @Schema(description = "客户名字", example = "test") + private String customerName; - @Schema(description = "性别") - @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3) - @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX) - private Integer sex; + @Schema(description = "最后跟进时间") + @ExcelProperty(value = "最后跟进时间", order = 6) + private LocalDateTime contactLastTime; - @Schema(description = "职位") - @ExcelProperty(value = "职位", order = 3) - private String post; + @Schema(description = "最后跟进内容") + @ExcelProperty(value = "最后跟进内容", order = 6) + private String contactLastContent; - @Schema(description = "是否关键决策人") - @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3) - @DictFormat(DictTypeConstants.BOOLEAN_STRING) - private Boolean master; + @Schema(description = "下次联系时间") + @ExcelProperty(value = "下次联系时间", order = 6) + private LocalDateTime contactNextTime; - @Schema(description = "直属上级", example = "23457") - private Long parentId; + @Schema(description = "负责人编号") + private Long ownerUserId; + @Schema(description = "负责人名字", example = "25682") + @ExcelProperty("负责人名字") + private String ownerUserName; + @Schema(description = "负责人部门") + @ExcelProperty("负责人部门") + private String ownerUserDeptName; @Schema(description = "手机号", example = "1387171766") @ExcelProperty(value = "手机号", order = 4) @@ -52,6 +59,10 @@ public class CrmContactRespVO { @ExcelProperty(value = "电话", order = 4) private String telephone; + @Schema(description = "电子邮箱", example = "1111@22.com") + @ExcelProperty(value = "邮箱", order = 4) + private String email; + @Schema(description = "QQ", example = "197272662") @ExcelProperty(value = "QQ", order = 4) private Long qq; @@ -60,53 +71,52 @@ public class CrmContactRespVO { @ExcelProperty(value = "微信", order = 4) private String wechat; - @Schema(description = "电子邮箱", example = "1111@22.com") - @ExcelProperty(value = "邮箱", order = 4) - private String email; - @Schema(description = "地区编号", example = "20158") private Integer areaId; + @Schema(description = "地区名", example = "上海上海市浦东新区") + @ExcelProperty(value = "地区", order = 5) + private String areaName; @Schema(description = "地址") @ExcelProperty(value = "地址", order = 5) private String detailAddress; - @Schema(description = "备注", example = "你说的对") - @ExcelProperty(value = "备注", order = 6) - private String remark; + @Schema(description = "性别") + @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3) + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX) + private Integer sex; - @Schema(description = "负责人用户编号", example = "14334") - private Long ownerUserId; + @Schema(description = "是否关键决策人") + @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean master; - @Schema(description = "最后跟进时间") - @ExcelProperty(value = "最后跟进时间", order = 6) - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @ExcelProperty(value = "下次联系时间", order = 6) - private LocalDateTime contactNextTime; - - @Schema(description = "创建人", example = "25682") - private String creator; - - @Schema(description = "创建人名字", example = "test") - @ExcelProperty(value = "创建人", order = 8) - private String creatorName; - - @ExcelProperty(value = "客户名称", order = 2) - @Schema(description = "客户名字", example = "test") - private String customerName; - - @Schema(description = "负责人", example = "test") - @ExcelProperty(value = "负责人", order = 7) - private String ownerUserName; + @Schema(description = "职位") + @ExcelProperty(value = "职位", order = 3) + private String post; + @Schema(description = "直属上级", example = "23457") + private Long parentId; @Schema(description = "直属上级名", example = "芋头") @ExcelProperty(value = "直属上级", order = 4) private String parentName; - @Schema(description = "地区名", example = "上海上海市浦东新区") - @ExcelProperty(value = "地区", order = 5) - private String areaName; + @Schema(description = "备注", example = "你说的对") + @ExcelProperty(value = "备注", order = 6) + private String remark; + + @Schema(description = "创建人", example = "25682") + private String creator; + @Schema(description = "创建人名字", example = "test") + @ExcelProperty(value = "创建人", order = 8) + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("更新时间") + private LocalDateTime updateTime; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java index 299b1fbbb..68dcd1be5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java @@ -13,7 +13,6 @@ import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @Schema(description = "管理后台 - CRM 联系人创建/更新 Request VO") @Data @@ -31,21 +30,15 @@ public class CrmContactSaveReqVO { @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME) private Long customerId; - @Schema(description = "性别") - @DiffLogField(name = "性别", function = SysSexParseFunction.NAME) - private Integer sex; + @Schema(description = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + @DiffLogField(name = "下次联系时间") + private LocalDateTime contactNextTime; - @Schema(description = "职位") - @DiffLogField(name = "职位") - private String post; - - @Schema(description = "是否关键决策人") - @DiffLogField(name = "关键决策人", function = SysBooleanParseFunction.NAME) - private Boolean master; - - @Schema(description = "直属上级", example = "23457") - @DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME) - private Long parentId; + @Schema(description = "负责人用户编号", example = "14334") + @NotNull(message = "负责人不能为空") + @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME) + private Long ownerUserId; @Schema(description = "手机号", example = "1387171766") @Mobile @@ -78,25 +71,26 @@ public class CrmContactSaveReqVO { @DiffLogField(name = "地址") private String detailAddress; + @Schema(description = "性别") + @DiffLogField(name = "性别", function = SysSexParseFunction.NAME) + private Integer sex; + + @Schema(description = "是否关键决策人") + @DiffLogField(name = "关键决策人", function = SysBooleanParseFunction.NAME) + private Boolean master; + + @Schema(description = "职位") + @DiffLogField(name = "职位") + private String post; + + @Schema(description = "直属上级", example = "23457") + @DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME) + private Long parentId; + @Schema(description = "备注", example = "你说的对") @DiffLogField(name = "备注") private String remark; - @Schema(description = "负责人用户编号", example = "14334") - @NotNull(message = "负责人不能为空") - @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME) - private Long ownerUserId; - - @Schema(description = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @DiffLogField(name = "最后跟进时间") - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) - @DiffLogField(name = "下次联系时间") - private LocalDateTime contactNextTime; - @Schema(description = "关联商机 ID", example = "122233") private Long businessId; // 注意:该字段用于在【商机】详情界面「新建联系人」时,自动进行关联 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 3951d1ebd..ef0aa849a 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 @@ -168,7 +168,7 @@ public class CrmContractController { Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contractList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); // 3. 获取联系人 - Map contactMap = convertMap(contactService.getContactListByIds(convertSet(contractList, + Map contactMap = convertMap(contactService.getContactList(convertSet(contractList, CrmContractDO::getContactId)), CrmContactDO::getId); // 4. 获取商机 Map businessMap = convertMap(businessService.getBusinessList(convertSet(contractList, 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 f0b726353..735f2e887 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 @@ -75,7 +75,7 @@ public class CrmFollowUpRecordController { public CommonResult> getFollowUpRecordPage(@Valid CrmFollowUpRecordPageReqVO pageReqVO) { PageResult pageResult = followUpRecordService.getFollowUpRecordPage(pageReqVO); /// 拼接数据 - Map contactMap = convertMap(contactService.getContactListByIds( + 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); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java index 5fd2afa67..77f4dec93 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java @@ -1,25 +1,16 @@ package cn.iocoder.yudao.module.crm.convert.contact; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactRespVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; /** * CRM 联系人 Convert @@ -31,42 +22,9 @@ public interface CrmContactConvert { CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class); - CrmContactRespVO convert(CrmContactDO bean); - @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId); - default PageResult convertPage(PageResult pageResult, Map userMap, - List customerList, List parentContactList) { - PageResult voPageResult = BeanUtils.toBean(pageResult, CrmContactRespVO.class); - // 拼接关联字段 - Map parentContactMap = convertMap(parentContactList, CrmContactDO::getId); - Map customerMap = convertMap(customerList, CrmCustomerDO::getId); - voPageResult.getList().forEach(item -> { - setUserInfo(item, userMap); - findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName())); - findAndThen(parentContactMap, item.getParentId(), contactDO -> item.setParentName(contactDO.getName())); - }); - return voPageResult; - } - - default CrmContactRespVO convert(CrmContactDO contactDO, Map userMap, - List customerList, List parentContactList) { - CrmContactRespVO contactVO = convert(contactDO); - setUserInfo(contactVO, userMap); - Map customerMap = CollectionUtils.convertMap(customerList, CrmCustomerDO::getId); - Map contactMap = CollectionUtils.convertMap(parentContactList, CrmContactDO::getId); - findAndThen(customerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName())); - findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName())); - return contactVO; - } - - static void setUserInfo(CrmContactRespVO contactRespVO, Map userMap) { - contactRespVO.setAreaName(AreaUtils.format(contactRespVO.getAreaId())); - findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> contactRespVO.setOwnerUserName(user.getNickname())); - findAndThen(userMap, Long.parseLong(contactRespVO.getCreator()), user -> contactRespVO.setCreatorName(user.getNickname())); - } - @Mapping(target = "id", source = "reqBO.bizId") CrmContactDO convert(CrmUpdateFollowUpReqBO reqBO); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java index c2dec247d..5a891eb9c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java @@ -29,77 +29,16 @@ public class CrmContactDO extends BaseDO { */ @TableId private Long id; + /** + * 联系人姓名 + */ + private String name; /** * 客户编号 * * 关联 {@link CrmCustomerDO#getId()} */ private Long customerId; - /** - * 手机号 - */ - private String mobile; - /** - * 电话 - */ - private String telephone; - /** - * 电子邮箱 - */ - private String email; - /** - * 所在地 - * - * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 - */ - private Integer areaId; - /** - * 详细地址 - */ - private String detailAddress; - /** - * 备注 - */ - private String remark; - - /** - * 直属上级 - * - * 关联 {@link CrmContactDO#id} - */ - private Long parentId; - /** - * 姓名 - */ - private String name; - /** - * 职位 - */ - private String post; - /** - * QQ - */ - private Long qq; - /** - * 微信 - */ - private String wechat; - /** - * 性别 - * - * 枚举 {@link cn.iocoder.yudao.module.system.enums.common.SexEnum} - */ - private Integer sex; - /** - * 是否关键决策人 - */ - private Boolean master; - /** - * 负责人用户编号 - * - * 关联 AdminUserDO 的 id 字段 - */ - private Long ownerUserId; /** * 最后跟进时间 @@ -114,4 +53,66 @@ public class CrmContactDO extends BaseDO { */ private LocalDateTime contactNextTime; + /** + * 负责人用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + + /** + * 手机号 + */ + private String mobile; + /** + * 电话 + */ + private String telephone; + /** + * 电子邮箱 + */ + private String email; + /** + * QQ + */ + private Long qq; + /** + * 微信 + */ + private String wechat; + /** + * 所在地 + * + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 + */ + private Integer areaId; + /** + * 详细地址 + */ + private String detailAddress; + /** + * 性别 + * + * 枚举 {@link cn.iocoder.yudao.module.system.enums.common.SexEnum} + */ + private Integer sex; + /** + * 是否关键决策人 + */ + private Boolean master; + /** + * 职位 + */ + private String post; + /** + * 直属上级 + * + * 关联 {@link CrmContactDO#id} + */ + private Long parentId; + /** + * 备注 + */ + private String remark; + } 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 c35df47d3..c254601d0 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 @@ -63,11 +63,10 @@ public interface CrmContactMapper extends BaseMapperX { return selectJoinPage(pageReqVO, CrmContactDO.class, query); } - default List selectBatchIds(Collection ids, Long userId) { + default List selectBatchIds(Collection ids, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); - // 拼接自身的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, ownerUserId); query.selectAll(CrmContactDO.class).in(CrmContactDO::getId, ids).orderByDesc(CrmContactDO::getId); return selectJoinList(CrmContactDO.class, query); } 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 d7688b8fb..978986180 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 @@ -11,6 +11,9 @@ import jakarta.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * CRM 联系人 Service 接口 @@ -88,7 +91,17 @@ public interface CrmContactService { * @param ids 编号 * @return 联系人列表 */ - List getContactListByIds(Collection ids); + List getContactList(Collection ids); + + /** + * 获得联系人 Map + * + * @param ids 编号 + * @return 联系人 Map + */ + default Map getContactMap(Collection ids) { + return convertMap(getContactList(ids), CrmContactDO::getId); + } /** * 获得联系人列表 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 08ce78b81..db7fe90bf 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 @@ -218,7 +218,7 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - public List getContactListByIds(Collection ids) { + public List getContactList(Collection ids) { if (CollUtil.isEmpty(ids)) { return ListUtil.empty(); } 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 d98edce24..06c58386b 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 @@ -264,7 +264,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { .updateCustomerNames(new ArrayList<>()).failureCustomerNames(new LinkedHashMap<>()).build(); importCustomers.forEach(importCustomer -> { // 校验,判断是否有不符合的原因 - // TODO @puhui999:可以用 ValidationUtils 做参数校验;可能要封装一个方法,返回 message;这样的话,就可以在 CrmCustomerImportExcelVO 写需要校验的参数啦; try { validateCustomerForCreate(importCustomer); } catch (ServiceException ex) { From 7dd35f3295c0226d6eba8cfaf8d461adb5506db1 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 20 Feb 2024 23:32:26 +0800 Subject: [PATCH 16/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E8=81=94=E7=B3=BB=E4=BA=BA=E7=9A=84=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E3=80=81=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 2 + .../admin/contact/CrmContactController.java | 2 +- .../admin/contact/vo/CrmContactSaveReqVO.java | 1 + .../convert/contact/CrmContactConvert.java | 35 ----------- .../dal/mysql/contact/CrmContactMapper.java | 6 -- .../service/contact/CrmContactService.java | 28 +++++---- .../contact/CrmContactServiceImpl.java | 63 ++++++++++++------- .../service/customer/CrmCustomerService.java | 4 +- .../customer/CrmCustomerServiceImpl.java | 8 +-- .../CrmFollowUpRecordServiceImpl.java | 33 +++++----- 10 files changed, 81 insertions(+), 101 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java 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 0299a8d31..f90862d11 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 @@ -75,6 +75,8 @@ public interface LogRecordConstants { String CRM_CONTACT_DELETE_SUCCESS = "删除了联系人【{{#contactName}}】"; String CRM_CONTACT_TRANSFER_SUB_TYPE = "转移联系人"; String CRM_CONTACT_TRANSFER_SUCCESS = "将联系人【{{#contact.name}}】的负责人从【{getAdminUserById{#contact.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String CRM_CONTACT_FOLLOW_UP_SUB_TYPE = "联系人跟进"; + String CRM_CONTACT_FOLLOW_UP_SUCCESS = "联系人跟进【{{#contactName}}】"; // ======================= CRM_BUSINESS 商机 ======================= 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 161f10299..aedcb905e 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 @@ -118,7 +118,7 @@ public class CrmContactController { @Operation(summary = "获得联系人的精简列表") @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getSimpleContactList() { - List list = contactService.getSimpleContactList(getLoginUserId()); + List list = contactService.getContactList(getLoginUserId()); return success(convertList(list, contact -> // 只返回 id、name 字段 new CrmContactRespVO().setId(contact.getId()).setName(contact.getName()))); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java index 68dcd1be5..874716f4e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java @@ -27,6 +27,7 @@ public class CrmContactSaveReqVO { private String name; @Schema(description = "客户编号", example = "10795") + @NotNull(message = "客户编号不能为空") @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME) private Long customerId; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java deleted file mode 100644 index 77f4dec93..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.contact; - -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * CRM 联系人 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface CrmContactConvert { - - CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class); - - @Mapping(target = "bizId", source = "reqVO.id") - CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId); - - @Mapping(target = "id", source = "reqBO.bizId") - CrmContactDO convert(CrmUpdateFollowUpReqBO reqBO); - - default List convertList(List list) { - return CollectionUtils.convertList(list, INSTANCE::convert); - } - -} 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 c254601d0..2542da0b0 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 @@ -22,12 +22,6 @@ import java.util.List; @Mapper public interface CrmContactMapper extends BaseMapperX { - default int updateOwnerUserIdById(Long id, Long ownerUserId) { - return update(new LambdaUpdateWrapper() - .eq(CrmContactDO::getId, id) - .set(CrmContactDO::getOwnerUserId, ownerUserId)); - } - default int updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) { return update(new LambdaUpdateWrapper() .eq(CrmContactDO::getCustomerId, customerId) 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 978986180..a096ed232 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 @@ -6,9 +6,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReq import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; @@ -54,7 +54,7 @@ public interface CrmContactService { void transferContact(CrmContactTransferReqVO reqVO, Long userId); /** - * 更新客户联系人负责人 + * 更新指定客户的联系人的负责人 * * @param customerId 客户编号 * @param ownerUserId 用户编号 @@ -64,9 +64,20 @@ public interface CrmContactService { /** * 更新联系人相关跟进信息 * - * @param updateFollowUpReqBOList 跟进信息 + * @param id 编号 + * @param contactNextTime 下次联系时间 + * @param contactLastContent 最后联系内容 */ - void updateContactFollowUpBatch(List updateFollowUpReqBOList); + void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); + + /** + * 更新联系人相关跟进信息 + * + * @param ids 编号数组 + * @param contactNextTime 下次联系时间 + * @param contactLastContent 最后联系内容 + */ + void updateContactFollowUpBatch(Collection ids, LocalDateTime contactNextTime, String contactLastContent); /** * 获得联系人 @@ -103,20 +114,13 @@ public interface CrmContactService { return convertMap(getContactList(ids), CrmContactDO::getId); } - /** - * 获得联系人列表 - * - * @return 联系人列表 - */ - List getContactList(); - /** * 获取联系人列表(校验权限) * * @param userId 用户编号 * @return 联系人列表 */ - List getSimpleContactList(Long userId); + List getContactList(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 db7fe90bf..7b89167e0 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 @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusines import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; -import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; @@ -17,9 +16,9 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 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.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; @@ -30,14 +29,15 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; import static java.util.Collections.singletonList; /** @@ -73,7 +73,7 @@ public class CrmContactServiceImpl implements CrmContactService { success = CRM_CONTACT_CREATE_SUCCESS) public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) { createReqVO.setId(null); - // 1. 校验 + // 1. 校验关联数据 validateRelationDataExists(createReqVO); // 2. 插入联系人 @@ -102,8 +102,9 @@ public class CrmContactServiceImpl implements CrmContactService { success = CRM_CONTACT_UPDATE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContact(CrmContactSaveReqVO updateReqVO) { - // 1. 校验存在 + // 1.1 校验存在 CrmContactDO oldContact = validateContactExists(updateReqVO.getId()); + // 1.2 校验关联数据 validateRelationDataExists(updateReqVO); // 2. 更新联系人 @@ -123,15 +124,15 @@ public class CrmContactServiceImpl implements CrmContactService { private void validateRelationDataExists(CrmContactSaveReqVO saveReqVO) { // 1. 校验客户 if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) { - throw exception(CUSTOMER_NOT_EXISTS); + customerService.validateCustomer(saveReqVO.getCustomerId()); } // 2. 校验负责人 - if (saveReqVO.getOwnerUserId() != null && adminUserApi.getUser(saveReqVO.getOwnerUserId()) == null) { - throw exception(USER_NOT_EXISTS); + if (saveReqVO.getOwnerUserId() != null) { + adminUserApi.validateUser(saveReqVO.getOwnerUserId()); } // 3. 直属上级 - if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) { - throw exception(CONTACT_NOT_EXISTS); + if (saveReqVO.getParentId() != null) { + validateContactExists(saveReqVO.getParentId()); } // 4. 如果有关联商机,则需要校验存在 if (saveReqVO.getBusinessId() != null && businessService.getBusiness(saveReqVO.getBusinessId()) == null) { @@ -165,11 +166,11 @@ public class CrmContactServiceImpl implements CrmContactService { } private CrmContactDO validateContactExists(Long id) { - CrmContactDO contactDO = contactMapper.selectById(id); - if (contactDO == null) { + CrmContactDO contact = contactMapper.selectById(id); + if (contact == null) { throw exception(CONTACT_NOT_EXISTS); } - return contactDO; + return contact; } @Override @@ -182,10 +183,10 @@ public class CrmContactServiceImpl implements CrmContactService { CrmContactDO contact = validateContactExists(reqVO.getId()); // 2.1 数据权限转移 - permissionService.transferPermission( - CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType())); + permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTACT.getType(), + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 设置新的负责人 - contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); + contactMapper.updateById(new CrmContactDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId())); // 3. 记录转移日志 LogRecordContext.putVariable("contact", contact); @@ -194,11 +195,30 @@ public class CrmContactServiceImpl implements CrmContactService { @Override public void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) { contactMapper.updateOwnerUserIdByCustomerId(customerId, ownerUserId); + // TODO @puhui999:操作日志、数据权限; } @Override - public void updateContactFollowUpBatch(List updateFollowUpReqBOList) { - contactMapper.updateBatch(CrmContactConvert.INSTANCE.convertList(updateFollowUpReqBOList)); + @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}", + success = CRM_CONTACT_FOLLOW_UP_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + public void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { + // 1.1 校验存在 + CrmContactDO contact = validateContactExists(id); + + // 2. 更新联系人的跟进信息 + contactMapper.updateById(new CrmContactDO().setId(id).setContactNextTime(contactNextTime) + .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent)); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("contactName", contact.getName()); + } + + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE) + public void updateContactFollowUpBatch(Collection ids, LocalDateTime contactNextTime, String contactLastContent) { + contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactLastTime(LocalDateTime.now()) + .setContactNextTime(contactNextTime).setContactLastContent(contactLastContent))); } //======================= 查询相关 ======================= @@ -226,12 +246,7 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - public List getContactList() { - return contactMapper.selectList(); - } - - @Override - public List getSimpleContactList(Long userId) { + public List getContactList(Long userId) { CrmContactPageReqVO reqVO = new CrmContactPageReqVO(); reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 return contactMapper.selectPage(reqVO, userId).getList(); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 969889143..a99269e08 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -132,9 +132,9 @@ public interface CrmCustomerService { /** * 校验客户是否存在 * - * @param customerId 客户 id + * @param id 编号 */ - void validateCustomer(Long customerId); + void validateCustomer(Long id); /** * 客户转移 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 06c58386b..a0ea3922c 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 @@ -164,7 +164,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 2. 更新客户的跟进信息 customerMapper.updateById(new CrmCustomerDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime) - .setContactLastTime(LocalDateTime.now())); + .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent)); // 3. 记录操作日志上下文 LogRecordContext.putVariable("customerName", customer.getName()); @@ -521,11 +521,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { /** * 校验客户是否存在 * - * @param customerId 客户 id + * @param id 客户 id */ @Override - public void validateCustomer(Long customerId) { - validateCustomerExists(customerId); + public void validateCustomer(Long id) { + validateCustomerExists(id); } private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) { 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 00242b19c..848d4749a 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 @@ -68,41 +68,40 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @Override @CrmPermission(bizTypeValue = "#createReqVO.bizType", bizId = "#createReqVO.bizId", level = CrmPermissionLevelEnum.WRITE) public Long createFollowUpRecord(CrmFollowUpRecordSaveReqVO createReqVO) { - // 创建更进记录 - CrmFollowUpRecordDO followUpRecord = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class); - crmFollowUpRecordMapper.insert(followUpRecord); + // 1. 创建更进记录 + CrmFollowUpRecordDO record = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class); + crmFollowUpRecordMapper.insert(record); - // 2. 更新 bizId 对应的记录; - CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()) + // 2. 更新 bizId 对应的记录 + CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(record.getBizId()) .setContactLastTime(LocalDateTime.now()) - .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent()); - if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 + .setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent()); + if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息 businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); } - if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 - clueService.updateClueFollowUp(followUpRecord.getId(), followUpRecord.getNextTime(), followUpRecord.getContent()); + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), record.getBizType())) { // 更新线索跟进信息 + clueService.updateClueFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } - if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 - contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), record.getBizType())) { // 更新联系人跟进信息 + contactService.updateContactFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } - if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息 + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), record.getBizType())) { // 更新合同跟进信息 contractService.updateContractFollowUp(updateFollowUpReqBO); } - if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息 - customerService.updateCustomerFollowUp(followUpRecord.getBizId(), followUpRecord.getNextTime(), followUpRecord.getContent()); + if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), record.getBizType())) { // 更新客户跟进信息 + customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { - contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), - contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null))); + contactService.updateContactFollowUpBatch(createReqVO.getContactIds(), null, null); } // 3.2 需要更新 businessIds 对应的记录,不更新 lastTime 和 lastContent if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); } - return followUpRecord.getId(); + return record.getId(); } @Override From 02b63de8089012a14f898a9e23ea63409d135902 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 21 Feb 2024 14:27:25 +0800 Subject: [PATCH 17/54] =?UTF-8?q?CRM=EF=BC=9A=E5=AE=8C=E5=96=84=20review?= =?UTF-8?q?=20=E6=8F=90=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 1 + .../module/crm/enums/LogRecordConstants.java | 2 ++ .../vo/business/CrmBusinessSaveReqVO.java | 5 ++-- .../admin/contract/vo/CrmContractRespVO.java | 5 ++-- .../convert/contract/CrmContractConvert.java | 4 +-- .../contract/CrmContractProductDO.java | 5 ++-- .../business/CrmBusinessProductMapper.java | 13 +-------- .../CrmContactBusinessMapper.java | 6 ++-- .../dal/mysql/contact/CrmContactMapper.java | 4 +++ .../contract/CrmContractProductMapper.java | 9 ------ .../business/CrmBusinessServiceImpl.java | 26 ++++++----------- .../bo/CrmBusinessUpdateProductReqBO.java | 4 +-- .../contact/CrmContactBusinessService.java | 16 ++++++----- .../CrmContactBusinessServiceImpl.java | 23 +++++++++++---- .../service/contact/CrmContactService.java | 9 +++--- .../contact/CrmContactServiceImpl.java | 28 +++++++++++++++++-- .../contract/CrmContractServiceImpl.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 2 +- 18 files changed, 88 insertions(+), 76 deletions(-) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/{contactbusinesslink => contact}/CrmContactBusinessMapper.java (91%) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 7a04208fb..8f8c8ed1a 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -28,6 +28,7 @@ public interface ErrorCodeConstants { ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除"); + ErrorCode CONTACT_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_003_003, "更新联系人负责人失败"); // ========== 回款 1-020-004-000 ========== ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); 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 f90862d11..a64ca9af8 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 @@ -77,6 +77,8 @@ public interface LogRecordConstants { String CRM_CONTACT_TRANSFER_SUCCESS = "将联系人【{{#contact.name}}】的负责人从【{getAdminUserById{#contact.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; String CRM_CONTACT_FOLLOW_UP_SUB_TYPE = "联系人跟进"; String CRM_CONTACT_FOLLOW_UP_SUCCESS = "联系人跟进【{{#contactName}}】"; + String CRM_CONTACT_UPDATE_OWNER_USER_SUB_TYPE = "更新联系人负责人"; + String CRM_CONTACT_UPDATE_OWNER_USER_SUCCESS = "将联系人【{{#contact.name}}】的负责人从【{getAdminUserById{#contact.ownerUserId}}】变更为了【{getAdminUserById{#ownerUserId}}】"; // ======================= CRM_BUSINESS 商机 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java index 0be6264eb..ee1149cf3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java @@ -77,15 +77,14 @@ public class CrmBusinessSaveReqVO { @Schema(description = "联系人编号", example = "110") private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段 - // TODO @puhui999:传递 items 就行啦; @Schema(description = "产品列表") - private List productItems; + private List items; @Schema(description = "产品列表") @Data @NoArgsConstructor @AllArgsConstructor - public static class CrmBusinessProductItem { + public static class Item { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") @NotNull(message = "产品编号不能为空") 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/CrmContractRespVO.java index da6239414..554e285dd 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/CrmContractRespVO.java @@ -130,14 +130,13 @@ public class CrmContractRespVO { private Integer auditStatus; @Schema(description = "产品列表") - private List productItems; + private List items; - // TODO @puhui999:可以直接叫 Item @Schema(description = "产品列表") @Data @NoArgsConstructor @AllArgsConstructor - public static class CrmContractProductItemRespVO { + public static class Item { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") private Long id; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java index 0d2e49934..0b816f37a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java @@ -59,8 +59,8 @@ public interface CrmContractConvert { default void setContractRespVOProductItems(CrmContractRespVO respVO, Map contractProductMap, List productList) { - respVO.setProductItems(CollectionUtils.convertList(productList, product -> { - CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class); + respVO.setItems(CollectionUtils.convertList(productList, product -> { + CrmContractRespVO.Item productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.Item.class); findAndThen(contractProductMap, product.getId(), contractProduct -> productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent())); return productItemRespVO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java index bc977c78f..d0489e490 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java @@ -57,8 +57,9 @@ public class CrmContractProductDO extends BaseDO { private Integer discountPercent; /** * 总计价格(折扣后价格) - * - * TODO @puhui999:可以写下计算公式哈; + * = {@link #price} + * * {@link #count} + * * ({@link #discountPercent / 100}) */ private Integer totalPrice; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java index 2d1471c73..a91a0fd14 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import org.apache.ibatis.annotations.Mapper; @@ -16,18 +15,8 @@ import java.util.List; @Mapper public interface CrmBusinessProductMapper extends BaseMapperX { - // TODO @puhui999:用不到的方法,看看是不是删除哈 - default void deleteByBusinessId(Long getBusinessId) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; - delete(CrmBusinessProductDO::getBusinessId, getBusinessId); - } - - default CrmBusinessProductDO selectByBusinessId(Long getBusinessId) { - return selectOne(CrmBusinessProductDO::getBusinessId, getBusinessId); - } - default List selectListByBusinessId(Long businessId) { - // TODO @puhui999:可以简化,selectList(CrmBusinessProductDO::getBusinessId, businessId) - return selectList(new LambdaQueryWrapperX().eq(CrmBusinessProductDO::getBusinessId, businessId)); + return selectList(CrmBusinessProductDO::getBusinessId, businessId); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java similarity index 91% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessMapper.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java index 3eae483bc..01f8bc888 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink; +package cn.iocoder.yudao.module.crm.dal.mysql.contact; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; @@ -9,7 +9,7 @@ import java.util.Collection; import java.util.List; /** - * CRM 联系人与商机的关联 Mapper + * CRM 联系人商机关联 Mapper * * @author 芋道源码 */ @@ -31,4 +31,4 @@ public interface CrmContactBusinessMapper extends BaseMapperX { 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/CrmContractProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java index 814024125..feafbc444 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java @@ -16,15 +16,6 @@ import java.util.List; @Mapper public interface CrmContractProductMapper extends BaseMapperX { - // TODO @puhui999:用不到的方法,看看是不是删除哈 - default void deleteByContractId(Long contractId) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; - delete(CrmContractProductDO::getContractId, contractId); - } - - default CrmContractProductDO selectByContractId(Long contractId) { - return selectOne(CrmContractProductDO::getContractId, contractId); - } - default List selectListByContractId(Long contractId) { return selectList(new LambdaQueryWrapperX().eq(CrmContractProductDO::getContractId, contractId)); } 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 535578fd2..2a5ce511b 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 @@ -80,16 +80,15 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId); businessMapper.insert(business); // 1.2 插入商机关联商品 - if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 - List productList = buildBusinessProductList(createReqVO.getProductItems(), business.getId()); + if (CollUtil.isNotEmpty(createReqVO.getItems())) { // 如果有的话 + List productList = buildBusinessProductList(createReqVO.getItems(), business.getId()); businessProductMapper.insertBatch(productList); // 更新合同商品总金额 businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice( getSumValue(productList, CrmBusinessProductDO::getTotalPrice, Integer::sum))); } - // TODO @puhui999:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 - createContactBusiness(business.getId(), createReqVO.getContactId()); - + // 在联系人的详情页,如果直接【新建商机】,则需要关联下。 + contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId()); // 2. 创建数据权限 // 设置当前操作的人为负责人 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) @@ -100,14 +99,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { return business.getId(); } - // TODO @lzxhqs:CrmContactBusinessService 调用这个;这样逻辑才能收敛哈; - private void createContactBusiness(Long businessId, Long contactId) { - CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO(); - contactBusiness.setBusinessId(businessId); - contactBusiness.setContactId(contactId); - contactBusinessService.insert(contactBusiness); - } - @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", @@ -121,7 +112,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); businessMapper.updateById(updateObj); // 2.2 更新商机关联商品 - List productList = buildBusinessProductList(updateReqVO.getProductItems(), updateObj.getId()); + List productList = buildBusinessProductList(updateReqVO.getItems(), updateObj.getId()); updateBusinessProduct(productList, updateObj.getId()); // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 @@ -175,10 +166,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } } - private List buildBusinessProductList(List productItems, - Long businessId) { + private List buildBusinessProductList(List productItems, Long businessId) { // 校验商品存在 - Set productIds = convertSet(productItems, CrmBusinessSaveReqVO.CrmBusinessProductItem::getId); + Set productIds = convertSet(productItems, CrmBusinessSaveReqVO.Item::getId); List productList = productService.getProductList(productIds); if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { throw exception(PRODUCT_NOT_EXISTS); @@ -237,7 +227,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) { // 更新商机关联商品 List productList = buildBusinessProductList( - BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.CrmBusinessProductItem.class), updateProductReqBO.getId()); + BeanUtils.toBean(updateProductReqBO.getItems(), CrmBusinessSaveReqVO.Item.class), updateProductReqBO.getId()); updateBusinessProduct(productList, updateProductReqBO.getId()); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java index 34b2fa381..0c8d7efbf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java @@ -25,13 +25,13 @@ public class CrmBusinessUpdateProductReqBO { // TODO @芋艿:再想想 @NotEmpty(message = "产品列表不能为空") - private List productItems; + private List items; @Schema(description = "产品列表") @Data @NoArgsConstructor @AllArgsConstructor - public static class CrmBusinessProductItem { + public static class Item { @Schema(description = "产品编号", example = "20529") @NotNull(message = "产品编号不能为空") 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 8a9c4192f..882958b64 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 @@ -13,6 +13,15 @@ import java.util.List; */ public interface CrmContactBusinessService { + /** + * 创建联系人人商机关联 + * + * @param contactId 联系人编号 + * @param businessId 商机编号 + */ + void createContactBusiness(Long contactId, Long businessId); + + /** * 创建联系人与商机的关联 * @@ -42,11 +51,4 @@ public interface CrmContactBusinessService { */ List getContactBusinessListByContactId(Long contactId); - /** - * 新增联系人与商机的关联 - * - * @param contactBusiness 新增联系人与商机的对象 - */ - void insert(CrmContactBusinessDO contactBusiness); - } \ No newline at end of file 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 7b0711334..58821e07b 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 @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusines import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; -import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; +import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactBusinessMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; @@ -41,6 +41,22 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService @Lazy // 延迟加载,为了解决延迟加载 private CrmContactService contactService; + @Override + public void createContactBusiness(Long contactId, Long businessId) { + // 校验存在 + CrmContactDO contact = contactService.getContact(contactId); + if (contact == null) { + throw exception(CONTACT_NOT_EXISTS); + } + CrmBusinessDO business = businessService.getBusiness(businessId); + if (business == null) { + throw exception(BUSINESS_NOT_EXISTS); + } + + // 插入 + contactBusinessMapper.insert(new CrmContactBusinessDO(null, contactId, businessId)); + } + @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) { @@ -91,9 +107,4 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService return contactBusinessMapper.selectListByContactId(contactId); } - @Override - public void insert(CrmContactBusinessDO contactBusiness) { - contactBusinessMapper.insert(contactBusiness); - } - } \ No newline at end of file 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 a096ed232..5a743c580 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 @@ -55,6 +55,7 @@ public interface CrmContactService { /** * 更新指定客户的联系人的负责人 + * 数据权限基于 【客户】 * * @param customerId 客户编号 * @param ownerUserId 用户编号 @@ -64,8 +65,8 @@ public interface CrmContactService { /** * 更新联系人相关跟进信息 * - * @param id 编号 - * @param contactNextTime 下次联系时间 + * @param id 编号 + * @param contactNextTime 下次联系时间 * @param contactLastContent 最后联系内容 */ void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); @@ -73,8 +74,8 @@ public interface CrmContactService { /** * 更新联系人相关跟进信息 * - * @param ids 编号数组 - * @param contactNextTime 下次联系时间 + * @param ids 编号数组 + * @param contactNextTime 下次联系时间 * @param contactLastContent 最后联系内容 */ void updateContactFollowUpBatch(Collection ids, LocalDateTime contactNextTime, String contactLastContent); 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 7b89167e0..c142ef4eb 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 @@ -184,7 +184,7 @@ public class CrmContactServiceImpl implements CrmContactService { // 2.1 数据权限转移 permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTACT.getType(), - reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 设置新的负责人 contactMapper.updateById(new CrmContactDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId())); @@ -193,9 +193,31 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#customerId", level = CrmPermissionLevelEnum.OWNER) public void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) { - contactMapper.updateOwnerUserIdByCustomerId(customerId, ownerUserId); - // TODO @puhui999:操作日志、数据权限; + // 1. 校验存在 + List contacts = contactMapper.selectListByCustomerId(customerId); + if (CollUtil.isEmpty(contacts)) { + return; + } + int count = contactMapper.updateOwnerUserIdByCustomerId(customerId, ownerUserId); + if (count == 0) { + throw exception(CONTACT_UPDATE_OWNER_USER_FAIL); + } + + // 2. 记录操作日志 + for (CrmContactDO contact : contacts) { + receiveContactLog(contact, ownerUserId); + } + } + + @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_UPDATE_OWNER_USER_SUB_TYPE, bizNo = "{{#contact.id}", + success = CRM_CONTACT_UPDATE_OWNER_USER_SUCCESS) + public void receiveContactLog(CrmContactDO contact, Long ownerUserId) { + // 记录操作日志上下文 + LogRecordContext.putVariable("contact", contact); + LogRecordContext.putVariable("ownerUserId", ownerUserId); } @Override 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 71b9446e4..a57ac7e93 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 @@ -104,7 +104,7 @@ public class CrmContractServiceImpl implements CrmContractService { // 如果存在合同关联了商机则更新商机商品关联 if (contract.getBusinessId() != null) { businessService.updateBusinessProduct(new CrmBusinessUpdateProductReqBO().setId(contract.getBusinessId()) - .setProductItems(BeanUtils.toBean(createReqVO.getProductItems(), CrmBusinessUpdateProductReqBO.CrmBusinessProductItem.class))); + .setItems(BeanUtils.toBean(createReqVO.getProductItems(), CrmBusinessUpdateProductReqBO.Item.class))); } } 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 a0ea3922c..ffc328eae 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 @@ -412,7 +412,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return count; } - @Transactional // 需要 protected 修饰,因为需要在事务中调用 + @Transactional(rollbackFor = Exception.class) // 需要 protected 修饰,因为需要在事务中调用 protected void putCustomerPool(CrmCustomerDO customer) { // 1. 设置负责人为 NULL int updateOwnerUserIncr = customerMapper.updateOwnerUserIdById(customer.getId(), null); From e01dda9bafb906123fb4fdc9c951e5da5c40a53b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 21 Feb 2024 18:45:10 +0800 Subject: [PATCH 18/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=95=86=E6=9C=BA=E7=9A=84=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 1 + .../admin/business/CrmBusinessController.java | 98 ++++++++--- .../vo/business/CrmBusinessExcelVO.java | 75 --------- .../vo/business/CrmBusinessRespVO.java | 157 +++++++++++++----- .../vo/business/CrmBusinessSaveReqVO.java | 62 +++---- .../admin/contract/CrmContractController.java | 2 +- .../admin/product/CrmProductController.java | 53 ++++-- .../product/vo/product/CrmProductRespVO.java | 3 +- .../vo/product/CrmProductSaveReqVO.java | 6 +- .../convert/business/CrmBusinessConvert.java | 23 --- .../convert/product/CrmProductConvert.java | 46 ----- .../dataobject/business/CrmBusinessDO.java | 97 +++++------ .../business/CrmBusinessProductDO.java | 26 +-- .../crm/dal/dataobject/clue/CrmClueDO.java | 2 +- .../dal/dataobject/product/CrmProductDO.java | 6 +- .../crm/dal/mysql/business/package-info.java | 4 - .../crm/dal/mysql/contact/package-info.java | 4 - .../dal/mysql/product/CrmProductMapper.java | 24 +-- .../service/business/CrmBusinessService.java | 9 + .../business/CrmBusinessServiceImpl.java | 124 +++++++------- .../business/CrmBusinessStatusService.java | 14 +- .../CrmBusinessStatusServiceImpl.java | 5 + .../CrmBusinessStatusTypeService.java | 13 ++ .../CrmBusinessStatusTypeServiceImpl.java | 11 +- .../contract/CrmContractServiceImpl.java | 3 +- .../product/CrmProductCategoryService.java | 15 +- .../service/product/CrmProductService.java | 33 +++- .../product/CrmProductServiceImpl.java | 49 ++++-- 28 files changed, 527 insertions(+), 438 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessExcelVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/product/CrmProductConvert.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 7a04208fb..a484c778f 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -67,6 +67,7 @@ public interface ErrorCodeConstants { // ========== 产品 1_020_008_000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_020_008_000, "产品不存在"); ErrorCode PRODUCT_NO_EXISTS = new ErrorCode(1_020_008_001, "产品编号已存在"); + ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_020_008_002, "产品【{}】已禁用"); // ========== 产品分类 1_020_009_000 ========== ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_020_009_000, "产品分类不存在"); 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 c85c151f5..91b8e95dd 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 @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.business; import cn.hutool.core.collection.CollUtil; 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.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; @@ -10,15 +12,21 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.product.CrmProductService; +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; +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; @@ -30,13 +38,15 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; @@ -55,6 +65,13 @@ public class CrmBusinessController { private CrmBusinessStatusTypeService businessStatusTypeService; @Resource private CrmBusinessStatusService businessStatusService; + @Resource + private CrmProductService productService; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; @PostMapping("/create") @Operation(summary = "创建商机") @@ -86,9 +103,25 @@ public class CrmBusinessController { @PreAuthorize("@ss.hasPermission('crm:business:query')") public CommonResult getBusiness(@RequestParam("id") Long id) { CrmBusinessDO business = businessService.getBusiness(id); - return success(BeanUtils.toBean(business, CrmBusinessRespVO.class)); + return success(buildBusinessDetail(business)); } + private CrmBusinessRespVO buildBusinessDetail(CrmBusinessDO business) { + if (business == null) { + return null; + } + CrmBusinessRespVO businessVO = buildBusinessDetailList(Collections.singletonList(business)).get(0); + // 拼接产品项 + List businessProducts = businessService.getBusinessProductListByBusinessId(businessVO.getId()); + Map productMap = productService.getProductMap( + convertSet(businessProducts, CrmBusinessProductDO::getProductId)); + businessVO.setProducts(BeanUtils.toBean(businessProducts, CrmBusinessRespVO.Product.class, businessProductVO -> + MapUtils.findAndThen(productMap, businessProductVO.getProductId(), + product -> businessProductVO.setProductNo(product.getNo()).setProductUnit(product.getUnit())))); + return businessVO; + } + + // TODO 芋艿:处理下 @GetMapping("/list-by-ids") @Operation(summary = "获得商机列表") @Parameter(name = "ids", description = "编号", required = true, example = "[1024]") @@ -97,6 +130,7 @@ public class CrmBusinessController { return success(BeanUtils.toBean(businessService.getBusinessList(ids, getLoginUserId()), CrmBusinessRespVO.class)); } + // TODO 芋艿:处理下 @GetMapping("/simple-all-list") @Operation(summary = "获得联系人的精简列表") @PreAuthorize("@ss.hasPermission('crm:contact:query')") @@ -113,7 +147,7 @@ public class CrmBusinessController { @PreAuthorize("@ss.hasPermission('crm:business:query')") public CommonResult> getBusinessPage(@Valid CrmBusinessPageReqVO pageVO) { PageResult pageResult = businessService.getBusinessPage(pageVO, getLoginUserId()); - return success(buildBusinessDetailPageResult(pageResult)); + return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/page-by-customer") @@ -123,7 +157,7 @@ public class CrmBusinessController { throw exception(CUSTOMER_NOT_EXISTS); } PageResult pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); - return success(buildBusinessDetailPageResult(pageResult)); + return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/page-by-contact") @@ -131,7 +165,7 @@ public class CrmBusinessController { @PreAuthorize("@ss.hasPermission('crm:business:query')") public CommonResult> getBusinessContactPage(@Valid CrmBusinessPageReqVO pageReqVO) { PageResult pageResult = businessService.getBusinessPageByContact(pageReqVO); - return success(buildBusinessDetailPageResult(pageResult)); + return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/export-excel") @@ -141,29 +175,43 @@ public class CrmBusinessController { public void exportBusinessExcel(@Valid CrmBusinessPageReqVO exportReqVO, HttpServletResponse response) throws IOException { exportReqVO.setPageSize(PAGE_SIZE_NONE); - PageResult pageResult = businessService.getBusinessPage(exportReqVO, getLoginUserId()); + List list = businessService.getBusinessPage(exportReqVO, getLoginUserId()).getList(); // 导出 Excel ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessRespVO.class, - buildBusinessDetailPageResult(pageResult).getList()); + buildBusinessDetailList(list)); } - /** - * 构建详细的商机分页结果 - * - * @param pageResult 简单的商机分页结果 - * @return 详细的商机分页结果 - */ - private PageResult buildBusinessDetailPageResult(PageResult pageResult) { - if (CollUtil.isEmpty(pageResult.getList())) { - return PageResult.empty(pageResult.getTotal()); + private List buildBusinessDetailList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); } - List statusTypeList = businessStatusTypeService.getBusinessStatusTypeList( - convertSet(pageResult.getList(), CrmBusinessDO::getStatusTypeId)); - List statusList = businessStatusService.getBusinessStatusList( - convertSet(pageResult.getList(), CrmBusinessDO::getStatusId)); - List customerList = customerService.getCustomerList( - convertSet(pageResult.getList(), CrmBusinessDO::getCustomerId)); - return CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList); + // 1.1 获取客户列表 + Map customerMap = customerService.getCustomerMap( + convertSet(list, CrmBusinessDO::getCustomerId)); + // 1.2 获取创建人、负责人列表 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(list, + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + // 1.3 获得商机状态组 + Map statusTypeMap = businessStatusTypeService.getBusinessStatusTypeMap( + convertSet(list, CrmBusinessDO::getStatusTypeId)); + Map statusMap = businessStatusService.getBusinessStatusMap( + convertSet(list, CrmBusinessDO::getStatusId)); + // 2. 拼接数据 + return BeanUtils.toBean(list, CrmBusinessRespVO.class, businessVO -> { + // 2.1 设置客户名称 + MapUtils.findAndThen(customerMap, businessVO.getCustomerId(), customer -> businessVO.setCustomerName(customer.getName())); + // 2.2 设置创建人、负责人名称 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(businessVO.getCreator()), + user -> businessVO.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, businessVO.getOwnerUserId(), user -> { + businessVO.setOwnerUserName(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> businessVO.setOwnerUserDeptName(dept.getName())); + }); + // 2.3 设置商机状态 + MapUtils.findAndThen(statusTypeMap, businessVO.getStatusTypeId(), statusType -> businessVO.setStatusTypeName(statusType.getName())); + MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(status.getName())); + }); } @PutMapping("/transfer") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessExcelVO.java deleted file mode 100644 index a11949ecd..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessExcelVO.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; - -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.util.Set; - -/** - * 商机 Excel VO - * - * @author ljlleo - */ -@Data -public class CrmBusinessExcelVO { - - @ExcelProperty("主键") - private Long id; - - @ExcelProperty("商机名称") - private String name; - - @ExcelProperty("商机状态类型编号") - private Long statusTypeId; - - @ExcelProperty("商机状态编号") - private Long statusId; - - @ExcelProperty("下次联系时间") - private LocalDateTime contactNextTime; - - @ExcelProperty("客户编号") - private Long customerId; - - @ExcelProperty("预计成交日期") - private LocalDateTime dealTime; - - @ExcelProperty("商机金额") - private BigDecimal price; - - @ExcelProperty("整单折扣") - private BigDecimal discountPercent; - - @ExcelProperty("产品总金额") - private BigDecimal productPrice; - - @ExcelProperty("备注") - private String remark; - - @ExcelProperty("负责人的用户编号") - private Long ownerUserId; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - - @ExcelProperty("只读权限的用户编号数组") - private Set roUserIds; - - @ExcelProperty("读写权限的用户编号数组") - private Set rwUserIds; - - @ExcelProperty("1赢单2输单3无效") - private Integer endStatus; - - @ExcelProperty("结束时的备注") - private String endRemark; - - @ExcelProperty("最后跟进时间") - private LocalDateTime contactLastTime; - - @ExcelProperty("跟进状态") - private Integer followUpStatus; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index d3b6ab2fb..41829360a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -1,69 +1,144 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; +import lombok.NoArgsConstructor; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 商机 Response VO") +@Schema(description = "管理后台 - CRM 商机 Response VO") @Data +@ExcelIgnoreUnannotated public class CrmBusinessRespVO { - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") + @ExcelProperty("编号") private Long id; @Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @NotNull(message = "商机名称不能为空") + @ExcelProperty("商机名称") private String name; - @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") - @NotNull(message = "商机状态类型不能为空") - private Long statusTypeId; - - @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "商机状态不能为空") - private Long statusId; - - @Schema(description = "下次联系时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime contactNextTime; - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299") - @NotNull(message = "客户不能为空") private Long customerId; - - @Schema(description = "预计成交日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime dealTime; - - @Schema(description = "商机金额", example = "12371") - private Integer price; - - // TODO @ljileo:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题 - @Schema(description = "整单折扣") - private Integer discountPercent; - - @Schema(description = "产品总金额", example = "12025") - private BigDecimal productPrice; - - @Schema(description = "备注", example = "随便") - private String remark; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("客户名称") private String customerName; + @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example ="true") + @ExcelProperty("跟进状态") + private Boolean followUpStatus; + + @Schema(description = "最后跟进时间") + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; + + @Schema(description = "下次联系时间") + @ExcelProperty("下次联系时间") + private LocalDateTime contactNextTime; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("负责人的用户编号") + private Long ownerUserId; + @Schema(description = "负责人名字", example = "25682") + @ExcelProperty("负责人名字") + private String ownerUserName; + @Schema(description = "负责人部门") + @ExcelProperty("负责人部门") + private String ownerUserDeptName; + + @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") + private Long statusTypeId; @Schema(description = "状态类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中") + @ExcelProperty("商机状态类型") private String statusTypeName; + @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") + private Long statusId; @Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "跟进中") + @ExcelProperty("商机状态") private String statusName; + @Schema + @ExcelProperty("1赢单2输单3无效") + private Integer endStatus; + + @ExcelProperty("结束时的备注") + private String endRemark; + + @Schema(description = "预计成交日期") + @ExcelProperty("预计成交日期") + private LocalDateTime dealTime; + + @Schema(description = "产品总金额", example = "12025") + @ExcelProperty("产品总金额") + private BigDecimal totalProductPrice; + + @Schema(description = "整单折扣") + @ExcelProperty("整单折扣") + private BigDecimal discountPercent; + + @Schema(description = "商机总金额", example = "12371") + @ExcelProperty("商机总金额") + private BigDecimal totalPrice; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "1024") + @ExcelProperty("创建人") + private String creator; + @Schema(description = "创建人名字", example = "芋道源码") + @ExcelProperty("创建人名字") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("更新时间") + private LocalDateTime updateTime; + + @Schema(description = "产品列表") + private List products; + + @Schema(description = "产品列表") + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class Product { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") + private Long productId; + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") + private String productNo; + @Schema(description = "产品单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + private Integer productUnit; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + private BigDecimal productPrice; + + @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + private BigDecimal businessPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + private Integer count; + + @Schema(description = "总计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + private BigDecimal totalPrice; + + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java index 0be6264eb..b9816a8fc 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction; +import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFunction; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; @@ -29,75 +28,68 @@ public class CrmBusinessSaveReqVO { @NotNull(message = "商机名称不能为空") private String name; - @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") - @DiffLogField(name = "商机状态") - @NotNull(message = "商机状态类型不能为空") - private Long statusTypeId; - - @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @DiffLogField(name = "商机状态") - @NotNull(message = "商机状态不能为空") - private Long statusId; + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299") + @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME) + @NotNull(message = "客户不能为空") + private Long customerId; @Schema(description = "下次联系时间") @DiffLogField(name = "下次联系时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime contactNextTime; - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299") - @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME) - @NotNull(message = "客户不能为空") - private Long customerId; + @Schema(description = "负责人用户编号", example = "14334") + @NotNull(message = "负责人不能为空") + @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME) + private Long ownerUserId; + + @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") + @DiffLogField(name = "商机状态") + @NotNull(message = "商机状态类型不能为空") + private Long statusTypeId; @Schema(description = "预计成交日期") @DiffLogField(name = "预计成交日期") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime dealTime; - @Schema(description = "商机金额", example = "12371") - @DiffLogField(name = "商机金额") - private Integer price; - @Schema(description = "整单折扣") @DiffLogField(name = "整单折扣") - private Integer discountPercent; - - @Schema(description = "产品总金额", example = "12025") - @DiffLogField(name = "产品总金额") - private BigDecimal productPrice; + @NotNull(message = "整单折扣不能为空") + private BigDecimal discountPercent; @Schema(description = "备注", example = "随便") @DiffLogField(name = "备注") private String remark; - @Schema(description = "结束状态", example = "1") - @InEnum(CrmBizEndStatus.class) - private Integer endStatus; - @Schema(description = "联系人编号", example = "110") private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段 - // TODO @puhui999:传递 items 就行啦; @Schema(description = "产品列表") - private List productItems; + private List products; @Schema(description = "产品列表") @Data @NoArgsConstructor @AllArgsConstructor - public static class CrmBusinessProductItem { + public static class Product { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") @NotNull(message = "产品编号不能为空") - private Long id; + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + @NotNull(message = "产品单价不能为空") + private BigDecimal productPrice; + + @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + @NotNull(message = "合同价格不能为空") + private BigDecimal businessPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") @NotNull(message = "产品数量不能为空") private Integer count; - @Schema(description = "产品折扣") - private Integer discountPercent; - } } 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 ef0aa849a..d691a1701 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 @@ -179,7 +179,7 @@ public class CrmContractController { if (contractList.size() == 1) { List contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId()); contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId); - productList = productService.getProductListByIds(convertSet(contractProductList, CrmContractProductDO::getProductId)); + productList = productService.getProductList(convertSet(contractProductList, CrmContractProductDO::getProductId)); } return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java index 94774373d..91d31de7a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java @@ -1,16 +1,17 @@ package cn.iocoder.yudao.module.crm.controller.admin.product; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.SetUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +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.product.vo.product.CrmProductPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO; -import cn.iocoder.yudao.module.crm.convert.product.CrmProductConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService; @@ -34,10 +35,9 @@ 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.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static java.util.Collections.singletonList; @Tag(name = "管理后台 - CRM 产品") @RestController @@ -49,6 +49,7 @@ public class CrmProductController { private CrmProductService productService; @Resource private CrmProductCategoryService productCategoryService; + @Resource private AdminUserApi adminUserApi; @@ -82,21 +83,30 @@ public class CrmProductController { @PreAuthorize("@ss.hasPermission('crm:product:query')") public CommonResult getProduct(@RequestParam("id") Long id) { CrmProductDO product = productService.getProduct(id); + return success(buildProductDetail(product)); + } + + private CrmProductRespVO buildProductDetail(CrmProductDO product) { if (product == null) { - return success(null); + return null; } - Map userMap = adminUserApi.getUserMap( - SetUtils.asSet(Long.valueOf(product.getCreator()), product.getOwnerUserId())); - CrmProductCategoryDO category = productCategoryService.getProductCategory(product.getCategoryId()); - return success(CrmProductConvert.INSTANCE.convert(product, userMap, category)); + return buildProductDetailList(singletonList(product)).get(0); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得产品精简列表", description = "只包含被开启的产品,主要用于前端的下拉选项") + public CommonResult> getProductSimpleList() { + List list = productService.getProductListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, product -> new CrmProductRespVO().setId(product.getId()).setName(product.getName()) + .setUnit(product.getUnit()).setNo(product.getNo()).setPrice(product.getPrice()))); } @GetMapping("/page") @Operation(summary = "获得产品分页") @PreAuthorize("@ss.hasPermission('crm:product:query')") public CommonResult> getProductPage(@Valid CrmProductPageReqVO pageVO) { - PageResult pageResult = productService.getProductPage(pageVO, getLoginUserId()); - return success(new PageResult<>(getProductDetailList(pageResult.getList()), pageResult.getTotal())); + PageResult pageResult = productService.getProductPage(pageVO); + return success(new PageResult<>(buildProductDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/export-excel") @@ -106,21 +116,30 @@ public class CrmProductController { public void exportProductExcel(@Valid CrmProductPageReqVO exportReqVO, HttpServletResponse response) throws IOException { exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = productService.getProductPage(exportReqVO, getLoginUserId()).getList(); + List list = productService.getProductPage(exportReqVO).getList(); // 导出 Excel ExcelUtils.write(response, "产品.xls", "数据", CrmProductRespVO.class, - getProductDetailList(list)); + buildProductDetailList(list)); } - private List getProductDetailList(List list) { + private List buildProductDetailList(List list) { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } + // 1.1 获得用户信息 Map userMap = adminUserApi.getUserMap( convertSetByFlatMap(list, user -> Stream.of(Long.valueOf(user.getCreator()), user.getOwnerUserId()))); - List productCategoryList = productCategoryService.getProductCategoryList( + // 1.2 获得分类信息 + Map categoryMap = productCategoryService.getProductCategoryMap( convertSet(list, CrmProductDO::getCategoryId)); - return CrmProductConvert.INSTANCE.convertList(list, userMap, productCategoryList); + // 2. 拼接数据 + return BeanUtils.toBean(list, CrmProductRespVO.class, productVO -> { + // 2.1 设置用户信息 + MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname())); + MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname())); + // 2.2 设置分类名称 + MapUtils.findAndThen(categoryMap, productVO.getCategoryId(), category -> productVO.setCategoryName(category.getName())); + }); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java index ceca3e5a0..1f659aa77 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java @@ -8,6 +8,7 @@ import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.math.BigDecimal; import java.time.LocalDateTime; @Schema(description = "管理后台 - CRM 产品 Response VO") @@ -34,7 +35,7 @@ public class CrmProductRespVO { @Schema(description = "价格, 单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") @ExcelProperty("价格,单位:分") - private Long price; + private BigDecimal price; @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架") @ExcelProperty(value = "单位", converter = DictConvert.class) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductSaveReqVO.java index 01b2ae443..ef6d5824d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductSaveReqVO.java @@ -7,6 +7,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.math.BigDecimal; + @Schema(description = "管理后台 - CRM 产品创建/修改 Request VO") @Data public class CrmProductSaveReqVO { @@ -28,10 +30,10 @@ public class CrmProductSaveReqVO { @DiffLogField(name = "单位", function = CrmProductUnitParseFunction.NAME) private Integer unit; - @Schema(description = "价格, 单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @Schema(description = "价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") @NotNull(message = "价格不能为空") @DiffLogField(name = "价格") - private Long price; + private BigDecimal price; @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架") @NotNull(message = "状态不能为空") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java index d7f990043..c86726412 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java @@ -1,14 +1,8 @@ package cn.iocoder.yudao.module.crm.convert.business; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import org.mapstruct.Mapper; @@ -16,9 +10,6 @@ import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 商机 Convert @@ -33,20 +24,6 @@ public interface CrmBusinessConvert { @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId); - default PageResult convertPage(PageResult pageResult, List customerList, - List statusTypeList, List statusList) { - PageResult voPageResult = BeanUtils.toBean(pageResult, CrmBusinessRespVO.class); - // 拼接关联字段 - Map customerMap = convertMap(customerList, CrmCustomerDO::getId, CrmCustomerDO::getName); - Map statusTypeMap = convertMap(statusTypeList, CrmBusinessStatusTypeDO::getId, CrmBusinessStatusTypeDO::getName); - Map statusMap = convertMap(statusList, CrmBusinessStatusDO::getId, CrmBusinessStatusDO::getName); - voPageResult.getList().forEach(type -> type - .setCustomerName(customerMap.get(type.getCustomerId())) - .setStatusTypeName(statusTypeMap.get(type.getStatusTypeId())) - .setStatusName(statusMap.get(type.getStatusId()))); - return voPageResult; - } - @Mapping(target = "id", source = "reqBO.bizId") CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/product/CrmProductConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/product/CrmProductConvert.java deleted file mode 100644 index 2165a208f..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/product/CrmProductConvert.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.product; - -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.product.vo.product.CrmProductRespVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; - -/** - * 产品 Convert - * - * @author ZanGe丶 - */ -@Mapper -public interface CrmProductConvert { - - CrmProductConvert INSTANCE = Mappers.getMapper(CrmProductConvert.class); - - default List convertList(List list, - Map userMap, - List categoryList) { - Map categoryMap = convertMap(categoryList, CrmProductCategoryDO::getId); - return CollectionUtils.convertList(list, - product -> convert(product, userMap, categoryMap.get(product.getCategoryId()))); - } - - default CrmProductRespVO convert(CrmProductDO product, - Map userMap, CrmProductCategoryDO category) { - CrmProductRespVO productVO = BeanUtils.toBean(product, CrmProductRespVO.class); - Optional.ofNullable(category).ifPresent(c -> productVO.setCategoryName(c.getName())); - MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname())); - MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname())); - return productVO; - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java index 3a543712b..803f37a38 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java @@ -8,10 +8,11 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.math.BigDecimal; import java.time.LocalDateTime; /** - * 商机 DO + * CRM 商机 DO * * @author ljlleo */ @@ -26,7 +27,7 @@ import java.time.LocalDateTime; public class CrmBusinessDO extends BaseDO { /** - * 主键 + * 编号 */ @TableId private Long id; @@ -34,6 +35,33 @@ public class CrmBusinessDO extends BaseDO { * 商机名称 */ private String name; + /** + * 客户编号 + * + * 关联 {@link CrmCustomerDO#getId()} + */ + private Long customerId; + + /** + * 跟进状态 + */ + private Boolean followUpStatus; + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + /** * 商机状态类型编号 * @@ -46,39 +74,6 @@ public class CrmBusinessDO extends BaseDO { * 关联 {@link CrmBusinessStatusDO#getId()} */ private Long statusId; - /** - * 下次联系时间 - */ - private LocalDateTime contactNextTime; - /** - * 客户编号 - * - * TODO @ljileo:这个字段,后续要写下关联的实体哈 - * 关联 {@link CrmCustomerDO#getId()} - */ - private Long customerId; - /** - * 预计成交日期 - */ - private LocalDateTime dealTime; - /** - * 商机金额 - * - */ - private Integer price; - /** - * 整单折扣 - * - */ - private Integer discountPercent; - /** - * 产品总金额,单位:分 - */ - private Integer productPrice; - /** - * 备注 - */ - private String remark; /** * 结束状态 * @@ -89,20 +84,28 @@ public class CrmBusinessDO extends BaseDO { * 结束时的备注 */ private String endRemark; - /** - * 最后跟进时间 - */ - private LocalDateTime contactLastTime; - /** - * 跟进状态 - */ - private Boolean followUpStatus; /** - * 负责人的用户编号 - * - * 关联 AdminUserDO 的 id 字段 + * 预计成交日期 */ - private Long ownerUserId; + private LocalDateTime dealTime; + /** + * 产品总金额,单位:元 + * + * productPrice = ∑({@link CrmBusinessProductDO#getTotalPrice()}) + */ + private BigDecimal totalProductPrice; + /** + * 整单折扣,百分比 + */ + private BigDecimal discountPercent; + /** + * 商机总金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 79d6a2a7b..6adc7e42e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -7,9 +7,13 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.math.BigDecimal; + /** * 商机产品关联表 DO * + * CrmBusinessDO : CrmBusinessProductDO = 1 : N + * * @author lzxhqs */ @TableName("crm_business_product") @@ -40,24 +44,24 @@ public class CrmBusinessProductDO extends BaseDO { */ private Long productId; /** - * 产品单价 + * 产品单价,单位:元 + * + * 冗余 {@link CrmProductDO#getPrice()} */ - private Integer price; + private BigDecimal productPrice; /** - * 销售价格, 单位:分 + * 合同价格, 单位:元 */ - private Integer salesPrice; + private BigDecimal businessPrice; /** * 数量 */ - private Integer count; + private BigDecimal count; /** - * 折扣 + * 总计价格,单位:元 + * + * totalPrice = businessPrice * count */ - private Integer discountPercent; - /** - * 总计价格(折扣后价格) - */ - private Integer totalPrice; + private BigDecimal totalPrice; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java index 48e600be6..3af6feec4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -11,7 +11,7 @@ import lombok.*; import java.time.LocalDateTime; /** - * 线索 DO + * CRM 线索 DO * * @author Wanwan */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java index a3c56ccc9..caeeb53d2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.math.BigDecimal; + /** * CRM 产品 DO * @@ -43,9 +45,9 @@ public class CrmProductDO extends BaseDO { */ private Integer unit; /** - * 价格,单位:分 + * 价格,单位:元 */ - private Integer price; + private BigDecimal price; /** * 状态 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java deleted file mode 100644 index 72863e1f4..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 商机(销售机会) - */ -package cn.iocoder.yudao.module.crm.dal.mysql.business; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java deleted file mode 100644 index 6cb7d4be2..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 联系人 - */ -package cn.iocoder.yudao.module.crm.dal.mysql.contact; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java index 30a07eec2..4d1d61809 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java @@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * CRM 产品 Mapper * @@ -17,21 +17,23 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface CrmProductMapper extends BaseMapperX { - default PageResult selectPage(CrmProductPageReqVO reqVO, Long userId) { - MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); - // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_PRODUCT.getType(), - CrmProductDO::getId, userId, null, Boolean.FALSE); - // 拼接自身的查询条件 - query.selectAll(CrmProductDO.class) + default PageResult selectPage(CrmProductPageReqVO reqVO) { + return selectPage(reqVO, new MPJLambdaWrapperX() .likeIfPresent(CrmProductDO::getName, reqVO.getName()) .eqIfPresent(CrmProductDO::getStatus, reqVO.getStatus()) - .orderByDesc(CrmProductDO::getId); - return selectJoinPage(reqVO, CrmProductDO.class, query); + .orderByDesc(CrmProductDO::getId)); } default CrmProductDO selectByNo(String no) { return selectOne(CrmProductDO::getNo, no); } + default Long selectCountByCategoryId(Long categoryId) { + return selectCount(CrmProductDO::getCategoryId, categoryId); + } + + default List selectListByStatus(Integer status) { + return selectList(CrmProductDO::getStatus, status); + } + } 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 683070d02..c7dba0101 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 @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; @@ -90,6 +91,14 @@ public interface CrmBusinessService { */ List getBusinessList(Collection ids); + /** + * 获得指定商机编号的产品列表 + * + * @param businessId 商机编号 + * @return 商机产品列表 + */ + List getBusinessProductListByBusinessId(Long businessId); + /** * 获得商机分页 * 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 535578fd2..15dd00ee2 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 @@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.crm.service.business; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; @@ -14,7 +12,6 @@ import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; @@ -36,14 +33,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; /** @@ -75,27 +72,29 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}", success = CRM_BUSINESS_CREATE_SUCCESS) public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) { - createReqVO.setId(null); - // 1. 插入商机 + // 1.1 校验产品项的有效性 + List businessProducts = validateBusinessProducts(createReqVO.getProducts()); + // 1.2 TODO 芋艿:校验关联字 + + // 2.1 插入商机 CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId); + calculateTotalPrice(business, businessProducts); businessMapper.insert(business); - // 1.2 插入商机关联商品 - if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 - List productList = buildBusinessProductList(createReqVO.getProductItems(), business.getId()); - businessProductMapper.insertBatch(productList); - // 更新合同商品总金额 - businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice( - getSumValue(productList, CrmBusinessProductDO::getTotalPrice, Integer::sum))); + // 2.2 插入商机关联商品 + if (CollUtil.isNotEmpty(businessProducts)) { + businessProducts.forEach(item -> item.setBusinessId(business.getId())); + businessProductMapper.insertBatch(businessProducts); } + // TODO @puhui999:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 createContactBusiness(business.getId(), createReqVO.getContactId()); - // 2. 创建数据权限 + // 3. 创建数据权限 // 设置当前操作的人为负责人 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 3. 记录操作日志上下文 + // 4. 记录操作日志上下文 LogRecordContext.putVariable("business", business); return business.getId(); } @@ -114,15 +113,18 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { success = CRM_BUSINESS_UPDATE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateBusiness(CrmBusinessSaveReqVO updateReqVO) { - // 1. 校验存在 + // 1.1 校验存在 CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId()); + // 1.2 校验产品项的有效性 + List businessProducts = validateBusinessProducts(updateReqVO.getProducts()); + // 1.3 TODO 芋艿:校验关联字 // 2.1 更新商机 CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); + calculateTotalPrice(updateObj, businessProducts); businessMapper.updateById(updateObj); // 2.2 更新商机关联商品 - List productList = buildBusinessProductList(updateReqVO.getProductItems(), updateObj.getId()); - updateBusinessProduct(productList, updateObj.getId()); + updateBusinessProduct(updateObj.getId(), businessProducts); // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 // 3. 记录操作日志上下文 @@ -130,6 +132,37 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { LogRecordContext.putVariable("businessName", oldBusiness.getName()); } + private void updateBusinessProduct(Long id, List newList) { + List oldList = businessProductMapper.selectListByBusinessId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setBusinessId(id)); + businessProductMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + businessProductMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId)); + } + } + + private List validateBusinessProducts(List list) { + // 1. 校验产品存在 + productService.validProductList(convertSet(list, CrmBusinessSaveReqVO.Product::getProductId)); + // 2. 转化为 CrmBusinessProductDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, CrmBusinessProductDO.class, item -> { + item.setTotalPrice(MoneyUtils.priceMultiply(item.getBusinessPrice(), item.getCount())); + })); + } + + private void calculateTotalPrice(CrmBusinessDO business, List businessProducts) { + business.setTotalProductPrice(getSumValue(businessProducts, CrmBusinessProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(business.getTotalProductPrice(), business.getDiscountPercent()); + business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice)); + } + @Override public void updateBusinessFollowUpBatch(List updateFollowUpReqBOList) { businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList)); @@ -155,44 +188,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { LogRecordContext.putVariable("businessName", business.getName()); } - private void updateBusinessProduct(List newProductList, Long businessId) { - List oldProducts = businessProductMapper.selectListByBusinessId(businessId); - List> diffList = CollectionUtils.diffList(oldProducts, newProductList, (oldValue, newValue) -> { - boolean condition = ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId()); - if (condition) { - newValue.setId(oldValue.getId()); // 更新需要原始编号 - } - return condition; - }); - if (CollUtil.isNotEmpty(diffList.get(0))) { - businessProductMapper.insertBatch(diffList.get(0)); - } - if (CollUtil.isNotEmpty(diffList.get(1))) { - businessProductMapper.updateBatch(diffList.get(1)); - } - if (CollUtil.isNotEmpty(diffList.get(2))) { - businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId)); - } - } - - private List buildBusinessProductList(List productItems, - Long businessId) { - // 校验商品存在 - Set productIds = convertSet(productItems, CrmBusinessSaveReqVO.CrmBusinessProductItem::getId); - List productList = productService.getProductList(productIds); - if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { - throw exception(PRODUCT_NOT_EXISTS); - } - Map productMap = convertMap(productList, CrmProductDO::getId); - return convertList(productItems, productItem -> { - CrmProductDO product = productMap.get(productItem.getId()); - return BeanUtils.toBean(product, CrmBusinessProductDO.class) - .setId(null).setProductId(productItem.getId()).setBusinessId(businessId) - .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) - .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent())); - }); - } - /** * 删除校验合同是关联合同 * @@ -235,10 +230,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Override public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) { - // 更新商机关联商品 - List productList = buildBusinessProductList( - BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.CrmBusinessProductItem.class), updateProductReqBO.getId()); - updateBusinessProduct(productList, updateProductReqBO.getId()); + // 更新商机关联商品 TODO yunai +// List productList = buildBusinessProductList( +// BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.Product.class), updateProductReqBO.getId()); +// updateBusinessProduct(productList, updateProductReqBO.getId()); } //======================= 查询相关 ======================= @@ -265,6 +260,11 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { return businessMapper.selectBatchIds(ids); } + @Override + public List getBusinessProductListByBusinessId(Long businessId) { + return businessProductMapper.selectListByBusinessId(businessId); + } + @Override public PageResult getBusinessPage(CrmBusinessPageReqVO pageReqVO, Long userId) { return businessMapper.selectPage(pageReqVO, userId); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java index a2fc2d18d..d9128b429 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java @@ -5,11 +5,13 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusine import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; - import jakarta.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 商机状态 Service 接口 @@ -74,4 +76,14 @@ public interface CrmBusinessStatusService { */ List getBusinessStatusList(Collection ids); + /** + * 获得商机状态 Map + * + * @param ids 编号数组 + * @return 商机状态 Map + */ + default Map getBusinessStatusMap(Collection ids) { + return convertMap(getBusinessStatusList(ids), CrmBusinessStatusDO::getId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java index 2e49e99d7..b838fdc6f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.service.business; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO; @@ -13,6 +14,7 @@ import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import java.util.Collection; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -80,6 +82,9 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { @Override public List getBusinessStatusList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } return businessStatusMapper.selectBatchIds(ids); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java index 20509994e..a48ff0503 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java @@ -9,6 +9,9 @@ import jakarta.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 商机状态类型 Service 接口 @@ -72,4 +75,14 @@ public interface CrmBusinessStatusTypeService { */ List getBusinessStatusTypeList(Collection ids); + /** + * 获得商机状态类型 Map + * + * @param ids 编号数组 + * @return 商机状态类型 Map + */ + default Map getBusinessStatusTypeMap(Collection ids) { + return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java index d9845976b..85d30e8ce 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.service.business; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO; @@ -11,19 +10,18 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; - import java.util.Collection; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NAME_EXISTS; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS; /** * 商机状态类型 Service 实现类 @@ -126,6 +124,9 @@ public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeSe @Override public List getBusinessStatusTypeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } return businessStatusTypeMapper.selectBatchIds(ids); } 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 71b9446e4..cdd888544 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 @@ -184,7 +184,8 @@ public class CrmContractServiceImpl implements CrmContractService { return BeanUtils.toBean(product, CrmContractProductDO.class) .setId(null).setProductId(productItem.getId()).setContractId(contractId) .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) - .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent())); + // TODO 芋艿:这里临时注释掉 + .setTotalPrice(MoneyUtils.calculator(null, productItem.getCount(), productItem.getDiscountPercent())); }); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java index 56974da11..c68c0cf77 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java @@ -3,10 +3,13 @@ package cn.iocoder.yudao.module.crm.service.product; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * CRM 产品分类 Service 接口 @@ -61,4 +64,14 @@ public interface CrmProductCategoryService { */ List getProductCategoryList(Collection ids); + /** + * 获得产品分类 Map + * + * @param ids 编号数组 + * @return 产品分类 Map + */ + default Map getProductCategoryMap(Collection ids) { + return convertMap(getProductCategoryList(ids), CrmProductCategoryDO::getId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java index 6d2dd4943..9379734ef 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java @@ -8,6 +8,9 @@ import jakarta.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * CRM 产品 Service 接口 @@ -54,28 +57,46 @@ public interface CrmProductService { */ List getProductList(Collection ids); + /** + * 获得产品 Map + * + * @param ids 编号 + * @return 产品 Map + */ + default Map getProductMap(Collection ids) { + return convertMap(getProductList(ids), CrmProductDO::getId); + } + /** * 获得产品分页 * * @param pageReqVO 分页查询 * @return 产品分页 */ - PageResult getProductPage(CrmProductPageReqVO pageReqVO, Long userId); + PageResult getProductPage(CrmProductPageReqVO pageReqVO); /** - * 获得产品 + * 获得产品数量 * * @param categoryId 分类编号 * @return 产品 */ - CrmProductDO getProductByCategoryId(Long categoryId); + Long getProductByCategoryId(Long categoryId); /** - * 获得产品列表 + * 获得指定状态的产品列表 * - * @param ids 产品编号 + * @param status 状态 * @return 产品列表 */ - List getProductListByIds(Collection ids); + List getProductListByStatus(Integer status); + + /** + * 校验产品们的有效性 + * + * @param ids 编号数组 + * @return 产品列表 + */ + List validProductList(Collection ids); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java index 95205524e..c44bc6b9e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.crm.service.product; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; @@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; @@ -27,8 +26,10 @@ import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; @@ -138,25 +139,41 @@ public class CrmProductServiceImpl implements CrmProductService { } @Override - public List getProductList(Collection ids) { + public PageResult getProductPage(CrmProductPageReqVO pageReqVO) { + return productMapper.selectPage(pageReqVO); + } + + @Override + public Long getProductByCategoryId(Long categoryId) { + return productMapper.selectCountByCategoryId(categoryId); + } + + @Override + public List getProductListByStatus(Integer status) { + return productMapper.selectListByStatus(status); + } + + @Override + public List validProductList(Collection ids) { if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); + return Collections.emptyList(); } - return productMapper.selectBatchIds(ids); + List list = productMapper.selectBatchIds(ids); + Map productMap = convertMap(list, CrmProductDO::getId); + for (Long id : ids) { + CrmProductDO product = productMap.get(id); + if (productMap.get(id) == null) { + throw exception(PRODUCT_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(product.getStatus())) { + throw exception(PRODUCT_NOT_ENABLE, product.getName()); + } + } + return list; } @Override - public PageResult getProductPage(CrmProductPageReqVO pageReqVO, Long userId) { - return productMapper.selectPage(pageReqVO, userId); - } - - @Override - public CrmProductDO getProductByCategoryId(Long categoryId) { - return productMapper.selectOne(new LambdaQueryWrapper().eq(CrmProductDO::getCategoryId, categoryId)); - } - - @Override - public List getProductListByIds(Collection ids) { + public List getProductList(Collection ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } From f76a7cd94125022cf422e3e150f349e5cd4eb8e9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 21 Feb 2024 20:10:13 +0800 Subject: [PATCH 19/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=95=86=E6=9C=BA=E7=8A=B6=E6=80=81=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=AE=9E=E7=8E=B0=EF=BC=8C=E4=B8=8D=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E8=A1=A8=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 15 +- .../admin/business/CrmBusinessController.http | 32 ---- .../admin/business/CrmBusinessController.java | 3 +- .../business/CrmBusinessStatusController.java | 118 +++++++++++++ .../CrmBusinessStatusTypeController.java | 141 ---------------- .../vo/business/CrmBusinessRespVO.java | 6 +- .../vo/business/CrmBusinessSaveReqVO.java | 6 +- .../vo/status/CrmBusinessStatusPageReqVO.java | 15 -- .../vo/status/CrmBusinessStatusQueryVO.java | 19 --- .../vo/status/CrmBusinessStatusRespVO.java | 52 ++++-- .../vo/status/CrmBusinessStatusSaveReqVO.java | 48 ++++-- .../type/CrmBusinessStatusTypePageReqVO.java | 15 -- .../vo/type/CrmBusinessStatusTypeQueryVO.java | 19 --- .../vo/type/CrmBusinessStatusTypeRespVO.java | 44 ----- .../type/CrmBusinessStatusTypeSaveReqVO.java | 29 ---- .../business/CrmBusinessStatusConvert.java | 25 --- .../CrmBusinessStatusTypeConvert.java | 44 ----- .../dataobject/business/CrmBusinessDO.java | 2 +- .../business/CrmBusinessStatusTypeDO.java | 11 +- .../dal/mysql/business/CrmBusinessMapper.java | 4 + .../business/CrmBusinessStatusMapper.java | 22 +-- .../business/CrmBusinessStatusTypeMapper.java | 27 +-- .../service/business/CrmBusinessService.java | 8 + .../business/CrmBusinessServiceImpl.java | 5 + .../business/CrmBusinessStatusService.java | 53 ++++-- .../CrmBusinessStatusServiceImpl.java | 155 ++++++++++++++---- .../CrmBusinessStatusTypeService.java | 88 ---------- .../CrmBusinessStatusTypeServiceImpl.java | 133 --------------- 28 files changed, 385 insertions(+), 754 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusPageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusQueryVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypePageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeQueryVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeRespVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index a484c778f..61ea1ede9 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -22,8 +22,6 @@ public interface ErrorCodeConstants { ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除"); - // TODO @lilleo:商机状态、商机类型,都单独错误码段 - // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); @@ -77,12 +75,11 @@ public interface ErrorCodeConstants { ErrorCode PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_020_009_004, "父分类不能是二级分类"); ErrorCode product_CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_020_009_005, "存在子分类,无法删除"); - // ========== 商机状态类型 1_020_010_000 ========== - ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_010_000, "商机状态类型不存在"); - ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态类型名称已存在"); - - // ========== 商机状态 1_020_011_000 ========== - ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_011_000, "商机状态不存在"); + // ========== 商机状态 1_020_010_000 ========== + ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_010_000, "商机状态组不存在"); + ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态组的名称已存在"); + ErrorCode BUSINESS_STATUS_UPDATE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行更新"); + ErrorCode BUSINESS_STATUS_DELETE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行删除"); // ========== 客户公海规则设置 1_020_012_000 ========== ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用"); @@ -92,6 +89,4 @@ public interface ErrorCodeConstants { ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在"); ErrorCode FOLLOW_UP_RECORD_DELETE_DENIED = new ErrorCode(1_020_013_001, "删除跟进记录失败,原因:没有权限"); - // ========== 待办消息 1_020_014_000 ========== - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http deleted file mode 100644 index 55adb4bd5..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http +++ /dev/null @@ -1,32 +0,0 @@ -### 请求 /transfer -PUT {{baseUrl}}/crm/business/transfer -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -{ - "id": 1, - "ownerUserId": 2, - "transferType": 2, - "permissionType": 2 -} - -### 请求 /update -PUT {{baseUrl}}/crm/business/update -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -{ - "id": 1, - "name": "2", - "statusTypeId": 2, - "statusId": 2, - "customerId": 1 -} - -### 请求 /get -GET {{baseUrl}}/crm/business/get?id=1024 -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} 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 91b8e95dd..dd3c0eb4e 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 @@ -20,7 +20,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -62,7 +61,7 @@ public class CrmBusinessController { @Resource private CrmCustomerService customerService; @Resource - private CrmBusinessStatusTypeService businessStatusTypeService; + private CrmBusinessStatusService businessStatusTypeService; @Resource private CrmBusinessStatusService businessStatusService; @Resource diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java new file mode 100644 index 000000000..bdc44679d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService; +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; +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; +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 java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; + +@Tag(name = "管理后台 - CRM 商机状态") +@RestController +@RequestMapping("/crm/business-status") +@Validated +public class CrmBusinessStatusController { + + @Resource + private CrmBusinessStatusService businessStatusTypeService; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; + + @PostMapping("/create") + @Operation(summary = "创建商机状态") + @PreAuthorize("@ss.hasPermission('crm:business-status:create')") + public CommonResult createBusinessStatus(@Valid @RequestBody CrmBusinessStatusSaveReqVO createReqVO) { + return success(businessStatusTypeService.createBusinessStatus(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新商机状态") + @PreAuthorize("@ss.hasPermission('crm:business-status:update')") + public CommonResult updateBusinessStatus(@Valid @RequestBody CrmBusinessStatusSaveReqVO updateReqVO) { + businessStatusTypeService.updateBusinessStatus(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除商机状态") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:business-status-type:delete')") + public CommonResult deleteBusinessStatusType(@RequestParam("id") Long id) { + businessStatusTypeService.deleteBusinessStatusType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得商机状态") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") + public CommonResult getBusinessStatusType(@RequestParam("id") Long id) { + CrmBusinessStatusTypeDO statusType = businessStatusTypeService.getBusinessStatusType(id); + if (statusType == null) { + return success(null); + } + List statuses = businessStatusTypeService.getBusinessStatusListByTypeId(id); + return success(BeanUtils.toBean(statusType, CrmBusinessStatusRespVO.class, + statusTypeVO -> statusTypeVO.setStatuses(BeanUtils.toBean(statuses, CrmBusinessStatusRespVO.Status.class)))); + } + + @GetMapping("/page") + @Operation(summary = "获得商机状态分页") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") + public CommonResult> getBusinessStatusTypePage(@Valid PageParam pageReqVO) { + // 1. 查询数据 + PageResult pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO); + // 2. 拼接数据 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), statusType -> Long.parseLong(statusType.getCreator()))); + Map deptMap = deptApi.getDeptMap( + convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds, Collection::stream)); + return success(BeanUtils.toBean(pageResult, CrmBusinessStatusRespVO.class, statusTypeVO -> { + statusTypeVO.setCreator(userMap.get(NumberUtils.parseLong(statusTypeVO.getCreator())).getNickname()); + statusTypeVO.setDeptNames(convertList(statusTypeVO.getDeptIds(), + deptId -> deptMap.containsKey(deptId) ? deptMap.get(deptId).getName() : null)); + })); + } + + @GetMapping("/type-simple-list") + @Operation(summary = "获得商机状态列表") + public CommonResult> getBusinessStatusTypeSimpleList() { + List list = businessStatusTypeService.getBusinessStatusTypeList(); + return success(BeanUtils.toBean(list, CrmBusinessStatusRespVO.class)); + } + + @GetMapping("/status-simple-list") + @Operation(summary = "获得商机状态列表") + @Parameter(name = "typeId", description = "商机状态组", required = true, example = "1024") + public CommonResult> getBusinessStatusSimpleList(@RequestParam("typeId") Long typeId) { + List list = businessStatusTypeService.getBusinessStatusListByTypeId(typeId); + return success(BeanUtils.toBean(list, CrmBusinessStatusRespVO.Status.class)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java deleted file mode 100644 index 337590044..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java +++ /dev/null @@ -1,141 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO; -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusConvert; -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusTypeConvert; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService; -import cn.iocoder.yudao.module.system.api.dept.DeptApi; -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - -@Tag(name = "管理后台 - CRM 商机状态类型") -@RestController -@RequestMapping("/crm/business-status-type") -@Validated -public class CrmBusinessStatusTypeController { - - @Resource - private CrmBusinessStatusTypeService businessStatusTypeService; - - @Resource - private CrmBusinessStatusService businessStatusService; - - @Resource - private DeptApi deptApi; - - @PostMapping("/create") - @Operation(summary = "创建商机状态类型") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:create')") - public CommonResult createBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO createReqVO) { - return success(businessStatusTypeService.createBusinessStatusType(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新商机状态类型") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:update')") - public CommonResult updateBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO updateReqVO) { - businessStatusTypeService.updateBusinessStatusType(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除商机状态类型") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('crm:business-status-type:delete')") - public CommonResult deleteBusinessStatusType(@RequestParam("id") Long id) { - businessStatusTypeService.deleteBusinessStatusType(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得商机状态类型") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") - public CommonResult getBusinessStatusType(@RequestParam("id") Long id) { - CrmBusinessStatusTypeDO statusType = businessStatusTypeService.getBusinessStatusType(id); - // 处理状态回显 - // TODO @lzxhqs:可以在 businessStatusService 加个 getBusinessStatusListByTypeId 方法,直接返回 List 哈,常用的,尽量封装个简单易懂的方法,不用追求绝对通用哈; - CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO(); - queryVO.setTypeId(id); - List statusList = businessStatusService.selectList(queryVO); - return success(CrmBusinessStatusTypeConvert.INSTANCE.convert(statusType, statusList)); - } - - @GetMapping("/page") - @Operation(summary = "获得商机状态类型分页") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") - public CommonResult> getBusinessStatusTypePage(@Valid CrmBusinessStatusTypePageReqVO pageReqVO) { - PageResult pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO); - // 处理部门回显 - Set deptIds = CollectionUtils.convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds,Collection::stream); - List deptList = deptApi.getDeptList(deptIds); - return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult, deptList)); - } - - @GetMapping("/export-excel") - @Operation(summary = "导出商机状态类型 Excel") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:export')") - @OperateLog(type = EXPORT) - public void exportBusinessStatusTypeExcel(@Valid CrmBusinessStatusTypePageReqVO pageReqVO, - HttpServletResponse response) throws IOException { - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO).getList(); - // 导出 Excel - ExcelUtils.write(response, "商机状态类型.xls", "数据", CrmBusinessStatusTypeRespVO.class, - BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class)); - } - - @GetMapping("/get-simple-list") - @Operation(summary = "获得商机状态类型列表") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") - public CommonResult> getBusinessStatusTypeList() { - CrmBusinessStatusTypeQueryVO queryVO = new CrmBusinessStatusTypeQueryVO(); - queryVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - List list = businessStatusTypeService.selectList(queryVO); - return success(BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class)); - } - - // TODO @ljlleo 这个接口,是不是可以和 getBusinessStatusTypeList 合并成一个? - @GetMapping("/get-status-list") - @Operation(summary = "获得商机状态列表") - @PreAuthorize("@ss.hasPermission('crm:business-status:query')") - public CommonResult> getBusinessStatusListByTypeId(@RequestParam("typeId") Long typeId) { - CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO(); - queryVO.setTypeId(typeId); - List list = businessStatusService.selectList(queryVO); - return success(CrmBusinessStatusConvert.INSTANCE.convertList(list)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index 41829360a..6e8ea6741 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -52,10 +52,10 @@ public class CrmBusinessRespVO { @ExcelProperty("负责人部门") private String ownerUserDeptName; - @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") + @Schema(description = "商机状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") private Long statusTypeId; - @Schema(description = "状态类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中") - @ExcelProperty("商机状态类型") + @Schema(description = "商机状组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中") + @ExcelProperty("商机状态组") private String statusTypeName; @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java index b9816a8fc..8b0c53d21 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java @@ -43,9 +43,9 @@ public class CrmBusinessSaveReqVO { @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME) private Long ownerUserId; - @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") - @DiffLogField(name = "商机状态") - @NotNull(message = "商机状态类型不能为空") + @Schema(description = "商机状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") + @DiffLogField(name = "商机状态组") + @NotNull(message = "商机状态组不能为空") private Long statusTypeId; @Schema(description = "预计成交日期") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusPageReqVO.java deleted file mode 100644 index b91a954e0..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusPageReqVO.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 商机状态分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmBusinessStatusPageReqVO extends PageParam { - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusQueryVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusQueryVO.java deleted file mode 100644 index fbf4d06e1..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusQueryVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -import java.util.Collection; - -@Schema(description = "管理后台 - 商机状态 Query VO") -@Data -@ToString(callSuper = true) -public class CrmBusinessStatusQueryVO { - - @Schema(description = "主键集合") - private Collection idList; - - @Schema(description = "状态类型编号") - private Long typeId; -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusRespVO.java index 405a832a5..a2ee1dfe5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusRespVO.java @@ -1,33 +1,51 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + @Schema(description = "管理后台 - 商机状态 Response VO") @Data -@ExcelIgnoreUnannotated public class CrmBusinessStatusRespVO { - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899") - @ExcelProperty("主键") + @Schema(description = "状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934") private Long id; - @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139") - @ExcelProperty("状态类型编号") - private Long typeId; - - @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") - @ExcelProperty("状态名") + @Schema(description = "状态组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") private String name; - @Schema(description = "赢单率") - @ExcelProperty("赢单率") - private String percent; + @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED) + private List deptIds; + @Schema(description = "使用的部门名称", requiredMode = Schema.RequiredMode.REQUIRED) + private List deptNames; - @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("排序") - private Integer sort; + @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED) + private String creator; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "状态集合", requiredMode = Schema.RequiredMode.REQUIRED) + private List statuses; + + @Data + public static class Status { + + @Schema(description = "状态编号", example = "23899") + private Long id; + + @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + private String name; + + @Schema(description = "赢单率", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") + private BigDecimal percent; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; + + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java index 3327b09f7..05ea279af 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java @@ -1,32 +1,48 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import lombok.Data; -@Schema(description = "管理后台 - 商机状态新增/修改 Request VO") +import java.math.BigDecimal; +import java.util.List; + +@Schema(description = "管理后台 - 商机状态组新增/修改 Request VO") @Data public class CrmBusinessStatusSaveReqVO { - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899") + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934") private Long id; - @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139") - @NotNull(message = "状态类型编号不能为空") - private Long typeId; - - @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") - @NotEmpty(message = "状态名不能为空") + @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotEmpty(message = "状态类型名不能为空") private String name; - // TODO @lzxhqs::percent 应该是 Integer; - @Schema(description = "赢单率") - private String percent; + @Schema(description = "使用的部门编号") + private List deptIds; - // TODO @lzxhqs:这个是不是不用前端新增和修改的时候传递,交给顺序计算出来,存储起来就好了; - @Schema(description = "排序") - private Integer sort; + @Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "商机状态集合不能为空") + private List statuses; + + @Data + public static class Status { + + @Schema(description = "状态编号", example = "23899") + private Long id; + + @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + @NotEmpty(message = "状态名不能为空") + private String name; + + @Schema(description = "赢单率", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") + @NotNull(message = "赢单率不能为空") + private BigDecimal percent; + + @Schema(description = "排序", hidden = true, example = "1") + private Integer sort; + + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypePageReqVO.java deleted file mode 100644 index 03b113cc7..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypePageReqVO.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 商机状态类型分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmBusinessStatusTypePageReqVO extends PageParam { - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeQueryVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeQueryVO.java deleted file mode 100644 index 9c78f1afc..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeQueryVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.ToString; - -import java.util.Collection; - -@Schema(description = "管理后台 - 商机状态类型 Query VO") -@Data -@ToString(callSuper = true) -public class CrmBusinessStatusTypeQueryVO { - - @Schema(description = "主键集合") - private Collection idList; - - @Schema(description = "状态") - private Integer status; -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeRespVO.java deleted file mode 100644 index 9d13d5dc3..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeRespVO.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type; - -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - 商机状态类型 Response VO") -@Data -@ExcelIgnoreUnannotated -public class CrmBusinessStatusTypeRespVO { - - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934") - @ExcelProperty("主键") - private Long id; - - @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @ExcelProperty("状态类型名") - private String name; - - @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("使用的部门编号") - private List deptIds; - @Schema(description = "使用的部门名称", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("使用的部门名称") - private List deptNames; - - @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建人") - private String creator; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - - // TODO @ljlleo 字段后缀改成 statuses,保持和 deptIds 风格一致;CrmBusinessStatusDO 改成 VO 哈;一般不使用 do 直接返回 - @Schema(description = "状态集合", requiredMode = Schema.RequiredMode.REQUIRED) - private List statusList; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java deleted file mode 100644 index 23dc7742d..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type; - -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO; -import com.google.common.collect.Lists; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import java.util.List; - -@Schema(description = "管理后台 - 商机状态类型新增/修改 Request VO") -@Data -public class CrmBusinessStatusTypeSaveReqVO { - - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934") - private Long id; - - @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @NotEmpty(message = "状态类型名不能为空") - private String name; - - // TODO @lzxhqs: VO 里面,我们不使用默认值哈。这里 Lists.newArrayList() 看看怎么去掉。上面 deptIds 也是类似噢 - @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED) - private List deptIds = Lists.newArrayList(); - - @Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED) - private List statusList; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java deleted file mode 100644 index 52186e3d9..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.business; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 商机状态 Convert - * - * @author ljlleo - */ -@Mapper -public interface CrmBusinessStatusConvert { - - CrmBusinessStatusConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusConvert.class); - - List convertList(List list); - - PageResult convertPage(PageResult page); - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java deleted file mode 100644 index 4876fb537..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.business; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; - -// TODO @lzxhqs:看看是不是用 BeanUtils 替代了 -/** - * 商机状态类型 Convert - * - * @author ljlleo - */ -@Mapper -public interface CrmBusinessStatusTypeConvert { - - CrmBusinessStatusTypeConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusTypeConvert.class); - - CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean); - - PageResult convertPage(PageResult page); - - default PageResult convertPage(PageResult page, List deptList) { - PageResult pageResult = convertPage(page); - // 拼接关联字段 - Map deptMap = convertMap(deptList, DeptRespDTO::getId, DeptRespDTO::getName); - pageResult.getList().forEach(type -> type.setDeptNames(convertList(type.getDeptIds(), deptMap::get))); - return pageResult; - } - - default CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean, List statusList) { - return convert(bean).setStatusList(statusList); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java index 803f37a38..770c0110e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java @@ -63,7 +63,7 @@ public class CrmBusinessDO extends BaseDO { private Long ownerUserId; /** - * 商机状态类型编号 + * 商机状态组编号 * * 关联 {@link CrmBusinessStatusTypeDO#getId()} */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java index aa9f86251..791a8b700 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; import com.baomidou.mybatisplus.annotation.KeySequence; @@ -12,7 +11,7 @@ import lombok.*; import java.util.List; /** - * 商机状态类型 DO + * 商机状态组 DO * * @author ljlleo */ @@ -35,17 +34,11 @@ public class CrmBusinessStatusTypeDO extends BaseDO { * 状态类型名 */ private String name; + /** * 使用的部门编号 */ @TableField(typeHandler = LongListTypeHandler.class) private List deptIds; - /** - * 开启状态 - * - * TODO 改成 Integer,关联 CommonStatus - * 枚举 {@link CommonStatusEnum} - */ - private Boolean status; } 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 d7438484f..4e93c5eb3 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 @@ -63,4 +63,8 @@ public interface CrmBusinessMapper extends BaseMapperX { 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/business/CrmBusinessStatusMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java index be847ab9d..f157e7dc6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java @@ -1,10 +1,6 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import org.apache.ibatis.annotations.Mapper; @@ -18,20 +14,12 @@ import java.util.List; @Mapper public interface CrmBusinessStatusMapper extends BaseMapperX { - default PageResult selectPage(CrmBusinessStatusPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .orderByDesc(CrmBusinessStatusDO::getId)); - } - - default List selectList(CrmBusinessStatusQueryVO queryVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(CrmBusinessStatusDO::getTypeId, queryVO.getTypeId()) - .inIfPresent(CrmBusinessStatusDO::getId, queryVO.getIdList()) - .orderByDesc(CrmBusinessStatusDO::getId)); - } - - default int delete(Long typeId) { + default int deleteByTypeId(Long typeId) { return delete(CrmBusinessStatusDO::getTypeId, typeId); } + default List selectListByTypeId(Long typeId) { + return selectList(CrmBusinessStatusDO::getTypeId, typeId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java index 410ebf050..3444e58a7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java @@ -1,44 +1,27 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - /** - * 商机状态类型 Mapper + * 商机状态组 Mapper * * @author ljlleo */ @Mapper public interface CrmBusinessStatusTypeMapper extends BaseMapperX { - default PageResult selectPage(CrmBusinessStatusTypePageReqVO reqVO) { + default PageResult selectPage(PageParam reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .orderByDesc(CrmBusinessStatusTypeDO::getId)); } - default List selectList(CrmBusinessStatusTypeQueryVO queryVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(CrmBusinessStatusTypeDO::getStatus, queryVO.getStatus()) - .inIfPresent(CrmBusinessStatusTypeDO::getId, queryVO.getIdList())); - } - - // TODO @lzxhqs:这个可以改成 selectByName。业务上基于在判断 id 匹配;这样更通用一些;mapper 尽量通用,不关注或者特别关联业务; - /** - * 根据ID和name查询 - * - * @param id 商机状态类型id - * @param name 状态类型名 - * @return result - */ - default CrmBusinessStatusTypeDO selectByIdAndName(Long id, String name) { - return selectOne(CrmBusinessStatusTypeDO::getId, id, CrmBusinessStatusTypeDO::getName, name); + default CrmBusinessStatusTypeDO selectByName(String name) { + return selectOne(CrmBusinessStatusTypeDO::getName, name); } } 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 c7dba0101..696689e8a 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 @@ -138,4 +138,12 @@ public interface CrmBusinessService { */ Long getBusinessCountByCustomerId(Long customerId); + /** + * 获得使用指定商机状态组的商机数量 + * + * @param statusTypeId 商机状态组编号 + * @return 数量 + */ + Long getBusinessCountByStatusTypeId(Long statusTypeId); + } 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 15dd00ee2..2b4e09e2f 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 @@ -295,4 +295,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { return businessMapper.selectCount(CrmBusinessDO::getCustomerId, customerId); } + @Override + public Long getBusinessCountByStatusTypeId(Long statusTypeId) { + return businessMapper.selectCountByStatusTypeId(statusTypeId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java index d9128b429..c813f37cf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.crm.service.business; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; import jakarta.validation.Valid; import java.util.Collection; @@ -40,33 +40,56 @@ public interface CrmBusinessStatusService { * * @param id 编号 */ - void deleteBusinessStatus(Long id); + void deleteBusinessStatusType(Long id); /** - * 获得商机状态 + * 获得商机状态组 * * @param id 编号 - * @return 商机状态 + * @return 商机状态组 */ - CrmBusinessStatusDO getBusinessStatus(Long id); + CrmBusinessStatusTypeDO getBusinessStatusType(Long id); /** - * 获得商机状态分页 + * 获得商机状态组列表 + * + * @return 商机状态组列表 + */ + List getBusinessStatusTypeList(); + + /** + * 获得商机状态组分页 * * @param pageReqVO 分页查询 - * @return 商机状态分页 + * @return 商机状态组分页 */ - PageResult getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO); + PageResult getBusinessStatusTypePage(PageParam pageReqVO); - // TODO @ljlleo 常用的 ids 之类的查询,可以封装单独的方法,不用走类似 QueryVO,用起来更方便。 - // TODO @ljlleo 方法名用 getBusinessStatusList /** - * 获得商机状态分页 + * 获得商机状态组列表 * - * @param queryVO 查询参数 - * @return 商机状态分页 + * @param ids 编号数组 + * @return 商机状态组列表 */ - List selectList(CrmBusinessStatusQueryVO queryVO); + List getBusinessStatusTypeList(Collection ids); + + /** + * 获得商机状态组 Map + * + * @param ids 编号数组 + * @return 商机状态组 Map + */ + default Map getBusinessStatusTypeMap(Collection ids) { + return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId); + } + + /** + * 获得指定类型的商机状态列表 + * + * @param typeId 商机状态组编号 + * @return 商机状态列表 + */ + List getBusinessStatusListByTypeId(Long typeId); /** * 获得商机状态列表 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java index b838fdc6f..349b112c2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java @@ -1,24 +1,29 @@ package cn.iocoder.yudao.module.crm.service.business; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_NOT_EXISTS; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; /** * 商机状态 Service 实现类 @@ -29,55 +34,135 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STAT @Validated public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { + @Resource + private CrmBusinessStatusTypeMapper businessStatusTypeMapper; @Resource private CrmBusinessStatusMapper businessStatusMapper; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private CrmBusinessService businessService; + @Override + @Transactional(rollbackFor = Exception.class) public Long createBusinessStatus(CrmBusinessStatusSaveReqVO createReqVO) { - // 插入 - CrmBusinessStatusDO businessStatus = BeanUtils.toBean(createReqVO, CrmBusinessStatusDO.class); - businessStatusMapper.insert(businessStatus); - // 返回 - return businessStatus.getId(); + // 1.1 检验名称是否存在 + validateBusinessStatusTypeNameUnique(createReqVO.getName(), null); + // 1.2 设置状态的排序 + int sort = 0; + for (CrmBusinessStatusSaveReqVO.Status status : createReqVO.getStatuses()) { + status.setSort(sort++); + } + + // 2.1 插入类型 + CrmBusinessStatusTypeDO statusType = BeanUtils.toBean(createReqVO, CrmBusinessStatusTypeDO.class); + businessStatusTypeMapper.insert(statusType); + // 2.2 插入状态 + List statuses = BeanUtils.toBean(createReqVO.getStatuses(), CrmBusinessStatusDO.class, + status -> status.setTypeId(statusType.getId())); + businessStatusMapper.insertBatch(statuses); + return statusType.getId(); } @Override + @Transactional(rollbackFor = Exception.class) public void updateBusinessStatus(CrmBusinessStatusSaveReqVO updateReqVO) { - // 校验存在 - validateBusinessStatusExists(updateReqVO.getId()); - // 更新 - CrmBusinessStatusDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusDO.class); - businessStatusMapper.updateById(updateObj); + // 1.1 校验存在 + validateBusinessStatusTypeNameUnique(updateReqVO.getId()); + // 1.2 校验名称是否存在 + validateBusinessStatusTypeNameUnique(updateReqVO.getName(), updateReqVO.getId()); + // 1.3 设置状态的排序 + int sort = 0; + for (CrmBusinessStatusSaveReqVO.Status status : updateReqVO.getStatuses()) { + status.setSort(sort++); + } + // 1.4 已经使用,无法更新 + if (businessService.getBusinessCountByStatusTypeId(updateReqVO.getId()) > 0) { + throw exception(BUSINESS_STATUS_UPDATE_FAIL_USED); + } + + // 2.1 更新类型 + CrmBusinessStatusTypeDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusTypeDO.class); + businessStatusTypeMapper.updateById(updateObj); + // 2.2 更新状态 + updateBusinessStatus(updateReqVO.getId(), BeanUtils.toBean(updateReqVO.getStatuses(), CrmBusinessStatusDO.class)); } - @Override - public void deleteBusinessStatus(Long id) { - // 校验存在 - validateBusinessStatusExists(id); - // TODO @ljlleo 这里可以考虑,如果有商机在使用,不允许删除 - // 删除 - businessStatusMapper.deleteById(id); - } - - private void validateBusinessStatusExists(Long id) { - if (businessStatusMapper.selectById(id) == null) { - throw exception(BUSINESS_STATUS_NOT_EXISTS); + private void updateBusinessStatus(Long id, List newList) { + List oldList = businessStatusMapper.selectListByTypeId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setTypeId(id)); + businessStatusMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + businessStatusMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + businessStatusMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessStatusDO::getId)); } } - @Override - public CrmBusinessStatusDO getBusinessStatus(Long id) { - return businessStatusMapper.selectById(id); + private void validateBusinessStatusTypeNameUnique(Long id) { + if (businessStatusTypeMapper.selectById(id) == null) { + throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS); + } + } + + private void validateBusinessStatusTypeNameUnique(String name, Long id) { + CrmBusinessStatusTypeDO statusType = businessStatusTypeMapper.selectByName(name); + if (statusType == null + || statusType.getId().equals(id)) { + return; + } + throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS); } @Override - public PageResult getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO) { - return businessStatusMapper.selectPage(pageReqVO); + @Transactional(rollbackFor = Exception.class) + public void deleteBusinessStatusType(Long id) { + // 1.1 校验存在 + validateBusinessStatusTypeNameUnique(id); + // 1.2 已经使用,无法更新 + if (businessService.getBusinessCountByStatusTypeId(id) > 0) { + throw exception(BUSINESS_STATUS_DELETE_FAIL_USED); + } + + // 2.1 删除类型 + businessStatusTypeMapper.deleteById(id); + // 2.2 删除状态 + businessStatusMapper.deleteByTypeId(id); } @Override - public List selectList(CrmBusinessStatusQueryVO queryVO) { - return businessStatusMapper.selectList(queryVO); + public CrmBusinessStatusTypeDO getBusinessStatusType(Long id) { + return businessStatusTypeMapper.selectById(id); + } + + @Override + public List getBusinessStatusTypeList() { + return businessStatusTypeMapper.selectList(); + } + + @Override + public PageResult getBusinessStatusTypePage(PageParam pageReqVO) { + return null; + } + + @Override + public List getBusinessStatusTypeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return businessStatusTypeMapper.selectBatchIds(ids); + } + + @Override + public List getBusinessStatusListByTypeId(Long typeId) { + List list = businessStatusMapper.selectListByTypeId(typeId); + list.sort(Comparator.comparingInt(CrmBusinessStatusDO::getSort)); + return list; } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java deleted file mode 100644 index a48ff0503..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java +++ /dev/null @@ -1,88 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; -import jakarta.validation.Valid; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; - -/** - * 商机状态类型 Service 接口 - * - * @author ljlleo - */ -public interface CrmBusinessStatusTypeService { - - /** - * 创建商机状态类型 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createBusinessStatusType(@Valid CrmBusinessStatusTypeSaveReqVO createReqVO); - - /** - * 更新商机状态类型 - * - * @param updateReqVO 更新信息 - */ - void updateBusinessStatusType(@Valid CrmBusinessStatusTypeSaveReqVO updateReqVO); - - /** - * 删除商机状态类型 - * - * @param id 编号 - */ - void deleteBusinessStatusType(Long id); - - /** - * 获得商机状态类型 - * - * @param id 编号 - * @return 商机状态类型 - */ - CrmBusinessStatusTypeDO getBusinessStatusType(Long id); - - /** - * 获得商机状态类型分页 - * - * @param pageReqVO 分页查询 - * @return 商机状态类型分页 - */ - PageResult getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO); - - // TODO @ljlleo 常用的 ids 之类的查询,可以封装单独的方法,不用走类似 QueryVO,用起来更方便。 - /** - * 获得商机状态类型列表 - * - * @param queryVO 查询参数 - * @return 商机状态类型列表 - */ - List selectList(CrmBusinessStatusTypeQueryVO queryVO); - - /** - * 获得商机状态类型列表 - * - * @param ids 编号数组 - * @return 商机状态类型列表 - */ - List getBusinessStatusTypeList(Collection ids); - - /** - * 获得商机状态类型 Map - * - * @param ids 编号数组 - * @return 商机状态类型 Map - */ - default Map getBusinessStatusTypeMap(Collection ids) { - return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java deleted file mode 100644 index 85d30e8ce..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper; -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NAME_EXISTS; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS; - -/** - * 商机状态类型 Service 实现类 - * - * @author ljlleo - */ -@Service -@Validated -public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeService { - - @Resource - private CrmBusinessStatusTypeMapper businessStatusTypeMapper; - - @Resource - private CrmBusinessStatusMapper businessStatusMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public Long createBusinessStatusType(CrmBusinessStatusTypeSaveReqVO createReqVO) { - //检验名称是否存在 - validateBusinessStatusTypeExists(createReqVO.getName(), null); - // 插入类型 - CrmBusinessStatusTypeDO businessStatusType = BeanUtils.toBean(createReqVO, CrmBusinessStatusTypeDO.class); - businessStatusTypeMapper.insert(businessStatusType); - // 插入状态 - if (CollUtil.isNotEmpty(createReqVO.getStatusList())) { - createReqVO.getStatusList().forEach(status -> status.setTypeId(businessStatusType.getId())); - businessStatusMapper.insertBatch(BeanUtils.toBean(createReqVO.getStatusList(), CrmBusinessStatusDO.class)); - } - return businessStatusType.getId(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateBusinessStatusType(CrmBusinessStatusTypeSaveReqVO updateReqVO) { - // 校验存在 - validateBusinessStatusTypeExists(updateReqVO.getId()); - // 校验名称是否存在 - validateBusinessStatusTypeExists(updateReqVO.getName(), updateReqVO.getId()); - // 更新类型 - CrmBusinessStatusTypeDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusTypeDO.class); - businessStatusTypeMapper.updateById(updateObj); - // 更新状态(删除 + 更新) - // TODO @ljlleo 可以参考 DeliveryExpressTemplateServiceImpl 的 updateExpressTemplateFree 方法;主要没变化的,还是不删除了哈。 - businessStatusMapper.delete(updateReqVO.getId()); - updateReqVO.getStatusList().forEach(status -> status.setTypeId(updateReqVO.getId())); - businessStatusMapper.insertBatch(BeanUtils.toBean(updateReqVO.getStatusList(), CrmBusinessStatusDO.class)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteBusinessStatusType(Long id) { - // TODO 待添加被引用校验 - //... - - // 校验存在 - validateBusinessStatusTypeExists(id); - // 删除类型 - businessStatusTypeMapper.deleteById(id); - // 删除状态 - businessStatusMapper.delete(id); - } - - private void validateBusinessStatusTypeExists(Long id) { - if (businessStatusTypeMapper.selectById(id) == null) { - throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS); - } - } - - // TODO @ljlleo 这个方法,这个参考 validateDeptNameUnique 实现。 - private void validateBusinessStatusTypeExists(String name, Long id) { - CrmBusinessStatusTypeDO businessStatusTypeDO = businessStatusTypeMapper.selectByIdAndName(id, name); - if (businessStatusTypeDO != null) { - throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS); - } -// LambdaQueryWrapper wrapper = new LambdaQueryWrapperX<>(); -// if(null != id) { -// wrapper.ne(CrmBusinessStatusTypeDO::getId, id); -// } -// long cnt = businessStatusTypeMapper.selectCount(wrapper.eq(CrmBusinessStatusTypeDO::getName, name)); -// if (cnt > 0) { -// throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS); -// } - } - - @Override - public CrmBusinessStatusTypeDO getBusinessStatusType(Long id) { - return businessStatusTypeMapper.selectById(id); - } - - @Override - public PageResult getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO) { - return businessStatusTypeMapper.selectPage(pageReqVO); - } - - @Override - public List selectList(CrmBusinessStatusTypeQueryVO queryVO) { - return businessStatusTypeMapper.selectList(queryVO); - } - - @Override - public List getBusinessStatusTypeList(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return Collections.emptyList(); - } - return businessStatusTypeMapper.selectBatchIds(ids); - } - -} From 77f98c4d129307a1128af4ba6e88d8bfb52d8737 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 21 Feb 2024 21:49:49 +0800 Subject: [PATCH 20/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=95=86=E6=9C=BA=E7=9A=84=E6=96=B0=E5=A2=9E=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/CrmBusinessStatusController.java | 18 +++++--- .../vo/status/CrmBusinessStatusSaveReqVO.java | 2 + .../business/CrmBusinessServiceImpl.java | 43 ++++++++++++++++++- .../business/CrmBusinessStatusService.java | 7 +++ .../CrmBusinessStatusServiceImpl.java | 13 ++++-- .../service/contact/CrmContactService.java | 7 +++ .../contact/CrmContactServiceImpl.java | 5 +++ 7 files changed, 84 insertions(+), 11 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java index bdc44679d..0663d1f28 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.business; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -29,6 +30,7 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - CRM 商机状态") @RestController @@ -62,7 +64,7 @@ public class CrmBusinessStatusController { @DeleteMapping("/delete") @Operation(summary = "删除商机状态") @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('crm:business-status-type:delete')") + @PreAuthorize("@ss.hasPermission('crm:business-status:delete')") public CommonResult deleteBusinessStatusType(@RequestParam("id") Long id) { businessStatusTypeService.deleteBusinessStatusType(id); return success(true); @@ -71,7 +73,7 @@ public class CrmBusinessStatusController { @GetMapping("/get") @Operation(summary = "获得商机状态") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") + @PreAuthorize("@ss.hasPermission('crm:business-status:query')") public CommonResult getBusinessStatusType(@RequestParam("id") Long id) { CrmBusinessStatusTypeDO statusType = businessStatusTypeService.getBusinessStatusType(id); if (statusType == null) { @@ -84,10 +86,13 @@ public class CrmBusinessStatusController { @GetMapping("/page") @Operation(summary = "获得商机状态分页") - @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") - public CommonResult> getBusinessStatusTypePage(@Valid PageParam pageReqVO) { + @PreAuthorize("@ss.hasPermission('crm:business-status:query')") + public CommonResult> getBusinessStatusPage(@Valid PageParam pageReqVO) { // 1. 查询数据 PageResult pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } // 2. 拼接数据 Map userMap = adminUserApi.getUserMap( convertSet(pageResult.getList(), statusType -> Long.parseLong(statusType.getCreator()))); @@ -101,9 +106,12 @@ public class CrmBusinessStatusController { } @GetMapping("/type-simple-list") - @Operation(summary = "获得商机状态列表") + @Operation(summary = "获得商机状态组列表") public CommonResult> getBusinessStatusTypeSimpleList() { List list = businessStatusTypeService.getBusinessStatusTypeList(); + // 过滤掉部门不匹配的 + Long deptId = adminUserApi.getUser(getLoginUserId()).getDeptId(); + list.removeIf(statusType -> CollUtil.isNotEmpty(statusType.getDeptIds()) && !statusType.getDeptIds().contains(deptId)); return success(BeanUtils.toBean(list, CrmBusinessStatusRespVO.class)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java index 05ea279af..e93305c6a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/status/CrmBusinessStatusSaveReqVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -24,6 +25,7 @@ public class CrmBusinessStatusSaveReqVO { @Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED) @NotEmpty(message = "商机状态集合不能为空") + @Valid private List statuses; @Data 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 2b4e09e2f..9206f741a 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 @@ -19,11 +19,14 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; @@ -57,16 +60,26 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessProductMapper businessProductMapper; + @Resource + private CrmBusinessStatusService businessStatusService; @Resource @Lazy // 延迟加载,避免循环依赖 private CrmContractService contractService; @Resource + private CrmCustomerService customerService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private CrmContactService contactService; + @Resource private CrmPermissionService permissionService; @Resource private CrmContactBusinessService contactBusinessService; @Resource private CrmProductService productService; + @Resource + private AdminUserApi adminUserApi; + @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}", @@ -74,10 +87,12 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) { // 1.1 校验产品项的有效性 List businessProducts = validateBusinessProducts(createReqVO.getProducts()); - // 1.2 TODO 芋艿:校验关联字 + // 1.2 校验关联字段 + validateBusinessForCreate(createReqVO); // 2.1 插入商机 CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId); + business.setStatusId(businessStatusService.getBusinessStatusListByTypeId(createReqVO.getStatusTypeId()).get(0).getId()); // 默认状态 calculateTotalPrice(business, businessProducts); businessMapper.insert(business); // 2.2 插入商机关联商品 @@ -101,6 +116,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // TODO @lzxhqs:CrmContactBusinessService 调用这个;这样逻辑才能收敛哈; private void createContactBusiness(Long businessId, Long contactId) { + if (contactId == null) { + return; + } CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO(); contactBusiness.setBusinessId(businessId); contactBusiness.setContactId(contactId); @@ -113,11 +131,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { success = CRM_BUSINESS_UPDATE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateBusiness(CrmBusinessSaveReqVO updateReqVO) { + updateReqVO.setOwnerUserId(null).setStatusTypeId(null); // 不允许更新的字段 // 1.1 校验存在 CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId()); // 1.2 校验产品项的有效性 List businessProducts = validateBusinessProducts(updateReqVO.getProducts()); - // 1.3 TODO 芋艿:校验关联字 + // 1.3 校验关联字段 + validateBusinessForCreate(updateReqVO); // 2.1 更新商机 CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); @@ -148,6 +168,25 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } } + private void validateBusinessForCreate(CrmBusinessSaveReqVO saveReqVO) { + // 校验商机状态 + if (saveReqVO.getStatusTypeId() != null) { + businessStatusService.validateBusinessStatusType(saveReqVO.getStatusTypeId()); + } + // 校验客户 + if (saveReqVO.getCustomerId() != null) { + customerService.validateCustomer(saveReqVO.getCustomerId()); + } + // 校验联系人 + if (saveReqVO.getContactId() != null) { + contactService.validateContact(saveReqVO.getContactId()); + } + // 校验负责人 + if (saveReqVO.getOwnerUserId() != null) { + adminUserApi.validateUser(saveReqVO.getOwnerUserId()); + } + } + private List validateBusinessProducts(List list) { // 1. 校验产品存在 productService.validProductList(convertSet(list, CrmBusinessSaveReqVO.Product::getProductId)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java index c813f37cf..cc527ec3e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java @@ -50,6 +50,13 @@ public interface CrmBusinessStatusService { */ CrmBusinessStatusTypeDO getBusinessStatusType(Long id); + /** + * 校验商机状态组 + * + * @param id 编号 + */ + void validateBusinessStatusType(Long id); + /** * 获得商机状态组列表 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java index 349b112c2..580b431aa 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java @@ -68,7 +68,7 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { @Transactional(rollbackFor = Exception.class) public void updateBusinessStatus(CrmBusinessStatusSaveReqVO updateReqVO) { // 1.1 校验存在 - validateBusinessStatusTypeNameUnique(updateReqVO.getId()); + validateBusinessStatusTypeExists(updateReqVO.getId()); // 1.2 校验名称是否存在 validateBusinessStatusTypeNameUnique(updateReqVO.getName(), updateReqVO.getId()); // 1.3 设置状态的排序 @@ -104,7 +104,7 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { } } - private void validateBusinessStatusTypeNameUnique(Long id) { + private void validateBusinessStatusTypeExists(Long id) { if (businessStatusTypeMapper.selectById(id) == null) { throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS); } @@ -123,7 +123,7 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { @Transactional(rollbackFor = Exception.class) public void deleteBusinessStatusType(Long id) { // 1.1 校验存在 - validateBusinessStatusTypeNameUnique(id); + validateBusinessStatusTypeExists(id); // 1.2 已经使用,无法更新 if (businessService.getBusinessCountByStatusTypeId(id) > 0) { throw exception(BUSINESS_STATUS_DELETE_FAIL_USED); @@ -140,6 +140,11 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { return businessStatusTypeMapper.selectById(id); } + @Override + public void validateBusinessStatusType(Long id) { + validateBusinessStatusTypeExists(id); + } + @Override public List getBusinessStatusTypeList() { return businessStatusTypeMapper.selectList(); @@ -147,7 +152,7 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { @Override public PageResult getBusinessStatusTypePage(PageParam pageReqVO) { - return null; + return businessStatusTypeMapper.selectPage(pageReqVO); } @Override 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 a096ed232..4f7c6de22 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 @@ -87,6 +87,13 @@ public interface CrmContactService { */ CrmContactDO getContact(Long id); + /** + * 校验联系人 + * + * @param id 编号 + */ + void validateContact(Long id); + /** * 获得联系人列表 * 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 7b89167e0..b073889cd 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 @@ -229,6 +229,11 @@ public class CrmContactServiceImpl implements CrmContactService { return contactMapper.selectById(id); } + @Override + public void validateContact(Long id) { + validateContactExists(id); + } + @Override public List getContactListByIds(Collection ids, Long userId) { if (CollUtil.isEmpty(ids)) { From d9b0c9b4cf1f1620c1d5e08075a6b6ddd83c3597 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 21 Feb 2024 23:37:10 +0800 Subject: [PATCH 21/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=95=86=E6=9C=BA=E7=9A=84=E8=B7=9F=E8=BF=9B=E8=AE=B0?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 2 +- .../module/crm/enums/LogRecordConstants.java | 2 + .../vo/business/CrmBusinessRespVO.java | 2 +- .../convert/business/CrmBusinessConvert.java | 12 ------ .../service/business/CrmBusinessService.java | 16 ++++++-- .../business/CrmBusinessServiceImpl.java | 37 ++++++++++++++----- .../service/contact/CrmContactService.java | 5 +-- .../contact/CrmContactServiceImpl.java | 7 ++-- .../CrmFollowUpRecordServiceImpl.java | 13 +++---- 9 files changed, 54 insertions(+), 42 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index ed4bd4d5d..300f2ad63 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -20,7 +20,7 @@ public interface ErrorCodeConstants { // ========== 商机管理 1-020-002-000 ========== ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); - ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除"); + ErrorCode BUSINESS_DELETE_FAIL_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除"); // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); 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 a64ca9af8..eaf0affc3 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 @@ -91,6 +91,8 @@ public interface LogRecordConstants { String CRM_BUSINESS_DELETE_SUCCESS = "删除了商机【{{#businessName}}】"; String CRM_BUSINESS_TRANSFER_SUB_TYPE = "转移商机"; String CRM_BUSINESS_TRANSFER_SUCCESS = "将商机【{{#business.name}}】的负责人从【{getAdminUserById{#business.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String CRM_BUSINESS_FOLLOW_UP_SUB_TYPE = "商机跟进"; + String CRM_BUSINESS_FOLLOW_UP_SUCCESS = "商机跟进【{{#businessName}}】"; // ======================= CRM_CONTRACT 合同 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index 6e8ea6741..d754c8c83 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -65,7 +65,7 @@ public class CrmBusinessRespVO { private String statusName; @Schema - @ExcelProperty("1赢单2输单3无效") + @ExcelProperty("结束状态") private Integer endStatus; @ExcelProperty("结束时的备注") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java index c86726412..381f98409 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java @@ -1,16 +1,11 @@ package cn.iocoder.yudao.module.crm.convert.business; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; -import java.util.List; - /** * 商机 Convert * @@ -24,11 +19,4 @@ public interface CrmBusinessConvert { @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId); - @Mapping(target = "id", source = "reqBO.bizId") - CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO); - - default List convertList(List list) { - return CollectionUtils.convertList(list, INSTANCE::convert); - } - } 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 696689e8a..c93504066 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 @@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -41,9 +41,19 @@ public interface CrmBusinessService { /** * 更新商机相关跟进信息 * - * @param updateFollowUpReqBOList 跟进信息 + * @param id 编号 + * @param contactNextTime 下次联系时间 + * @param contactLastContent 最后联系内容 */ - void updateBusinessFollowUpBatch(List updateFollowUpReqBOList); + void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); + + /** + * 更新商机的下次联系时间 + * + * @param ids 编号数组 + * @param contactNextTime 下次联系时间 + */ + void updateBusinessContactNextTime(Collection ids, LocalDateTime contactNextTime); /** * 删除商机 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 a50cc1667..7c4e7cb94 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 @@ -22,7 +22,6 @@ import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; @@ -37,12 +36,13 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_DELETE_FAIL_CONTRACT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; @@ -139,6 +139,28 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { LogRecordContext.putVariable("businessName", oldBusiness.getName()); } + @Override + @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}", + success = CRM_BUSINESS_FOLLOW_UP_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + public void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { + // 1. 校验存在 + CrmBusinessDO business = validateBusinessExists(id); + + // 2. 更新联系人的跟进信息 + businessMapper.updateById(new CrmBusinessDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime) + .setContactLastTime(LocalDateTime.now())); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("businessName", business.getName()); + } + + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE) + public void updateBusinessContactNextTime(Collection ids, LocalDateTime contactNextTime) { + businessMapper.updateBatch(convertList(ids, id -> new CrmBusinessDO().setId(id).setContactNextTime(contactNextTime))); + } + private void updateBusinessProduct(Long id, List newList) { List oldList = businessProductMapper.selectListByBusinessId(id); List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 @@ -189,20 +211,15 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice)); } - @Override - public void updateBusinessFollowUpBatch(List updateFollowUpReqBOList) { - businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList)); - } - @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_DELETE_SUB_TYPE, bizNo = "{{#id}}", success = CRM_BUSINESS_DELETE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteBusiness(Long id) { - // 校验存在 + // 1.1 校验存在 CrmBusinessDO business = validateBusinessExists(id); - // TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段 + // 1.2 校验是否关联合同 validateContractExists(id); // 删除 @@ -222,7 +239,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { */ private void validateContractExists(Long businessId) { if (contractService.getContractCountByBusinessId(businessId) > 0) { - throw exception(BUSINESS_CONTRACT_EXISTS); + throw exception(BUSINESS_DELETE_FAIL_CONTRACT_EXISTS); } } 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 9da4b6feb..e94807f25 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 @@ -72,13 +72,12 @@ public interface CrmContactService { void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); /** - * 更新联系人相关跟进信息 + * 更新联系人的下次联系时间 * * @param ids 编号数组 * @param contactNextTime 下次联系时间 - * @param contactLastContent 最后联系内容 */ - void updateContactFollowUpBatch(Collection ids, LocalDateTime contactNextTime, String contactLastContent); + void updateContactContactNextTime(Collection ids, LocalDateTime contactNextTime); /** * 获得联系人 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 f98351080..342401c1e 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 @@ -225,7 +225,7 @@ public class CrmContactServiceImpl implements CrmContactService { success = CRM_CONTACT_FOLLOW_UP_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) public void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { - // 1.1 校验存在 + // 1. 校验存在 CrmContactDO contact = validateContactExists(id); // 2. 更新联系人的跟进信息 @@ -238,9 +238,8 @@ public class CrmContactServiceImpl implements CrmContactService { @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE) - public void updateContactFollowUpBatch(Collection ids, LocalDateTime contactNextTime, String contactLastContent) { - contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactLastTime(LocalDateTime.now()) - .setContactNextTime(contactNextTime).setContactLastContent(contactLastContent))); + public void updateContactContactNextTime(Collection ids, LocalDateTime contactNextTime) { + contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactNextTime(contactNextTime))); } //======================= 查询相关 ======================= 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 848d4749a..1f39e4684 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 @@ -26,11 +26,9 @@ import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; import java.util.Collection; -import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_DELETE_DENIED; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_NOT_EXISTS; @@ -77,7 +75,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { .setContactLastTime(LocalDateTime.now()) .setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent()); if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息 - businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); + businessService.updateBusinessFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), record.getBizType())) { // 更新线索跟进信息 clueService.updateClueFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); @@ -92,14 +90,13 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } - // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent + // 3.1 更新 contactIds 对应的记录,只更新 nextTime if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { - contactService.updateContactFollowUpBatch(createReqVO.getContactIds(), null, null); + contactService.updateContactContactNextTime(createReqVO.getContactIds(), createReqVO.getNextTime()); } - // 3.2 需要更新 businessIds 对应的记录,不更新 lastTime 和 lastContent + // 3.2 需要更新 businessIds 对应的记录,只更新 nextTime if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { - businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), - businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); + businessService.updateBusinessContactNextTime(createReqVO.getBusinessIds(), createReqVO.getNextTime()); } return record.getId(); } From b26eb6266fa1b5195c4510d4b12f55afdc394c37 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 22 Feb 2024 00:58:50 +0800 Subject: [PATCH 22/54] =?UTF-8?q?CRM=EF=BC=9A=E6=96=B0=E5=A2=9E=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E5=AF=BC=E5=85=A5=E6=A8=A1=E7=89=88=E6=89=80=E5=B1=9E?= =?UTF-8?q?=E8=A1=8C=E4=B8=9A=E3=80=81=E5=AE=A2=E6=88=B7=E7=AD=89=E7=BA=A7?= =?UTF-8?q?=E3=80=81=E5=AE=A2=E6=88=B7=E6=9D=A5=E6=BA=90=E3=80=81=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E5=9C=B0=E5=8C=BA=E5=8D=95=E5=85=83=E6=A0=BC=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ip/core/utils/AreaUtils.java | 37 +++++- .../core/handler/SelectSheetWriteHandler.java | 105 ++++++++++++++++++ .../framework/excel/core/util/ExcelUtils.java | 43 +++++-- .../admin/customer/CrmCustomerController.java | 31 +++++- .../module/system/api/dict/DictDataApi.java | 9 ++ .../system/api/dict/DictDataApiImpl.java | 16 ++- .../system/service/dict/DictDataService.java | 8 ++ .../service/dict/DictDataServiceImpl.java | 7 +- 8 files changed, 237 insertions(+), 19 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java index 5a7340095..1a773cda5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java @@ -4,6 +4,7 @@ import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.csv.CsvRow; import cn.hutool.core.text.csv.CsvUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; @@ -74,6 +75,32 @@ public class AreaUtils { return areas.get(id); } + /** + * 获取所有节点的全路径名称如:河南省/石家庄市/新华区 + * + * @param areas 地区树 + * @return 所有节点的全路径名称 + */ + public static List getAllAreaNodePaths(List areas) { + return convertList(areas, AreaUtils::buildTreePath); + } + + // TODO @puhui999: 展开树再构建全路径 + private static String buildTreePath(Area node) { + if (node.getParent() == null || Area.ID_CHINA.equals(node.getParent().getId())) { // 忽略中国 + // 已经是根节点,直接返回节点名称 + return node.getName(); + } else { + // 递归拼接上级节点的名称 + Area parent = getArea(node.getParent().getId()); + if (parent != null) { + String parentPath = buildTreePath(parent); + return parentPath + "/" + node.getName(); + } + } + return StrUtil.EMPTY; + } + /** * 格式化区域 * @@ -88,13 +115,13 @@ public class AreaUtils { * 格式化区域 * * 例如说: - * 1. id = “静安区”时:上海 上海市 静安区 - * 2. id = “上海市”时:上海 上海市 - * 3. id = “上海”时:上海 - * 4. id = “美国”时:美国 + * 1. id = “静安区”时:上海 上海市 静安区 + * 2. id = “上海市”时:上海 上海市 + * 3. id = “上海”时:上海 + * 4. id = “美国”时:美国 * 当区域在中国时,默认不显示中国 * - * @param id 区域编号 + * @param id 区域编号 * @param separator 分隔符 * @return 格式化后的区域 */ 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 new file mode 100644 index 000000000..571f4c983 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.framework.excel.core.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import org.apache.poi.hssf.usermodel.HSSFDataValidation; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddressList; + +import java.util.List; + +/** + * 基于固定 sheet 实现下拉框 + * + * @author HUIHUI + */ +public class SelectSheetWriteHandler implements SheetWriteHandler { + + private List>> selectMap; + + private final char[] alphabet = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + + public SelectSheetWriteHandler(List>> selectMap) { + this.selectMap = selectMap; + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + if (selectMap == null || CollUtil.isEmpty(selectMap)) { + return; + } + // 需要设置下拉框的sheet页 + Sheet curSheet = writeSheetHolder.getSheet(); + DataValidationHelper helper = curSheet.getDataValidationHelper(); + String dictSheetName = "字典sheet"; + Workbook workbook = writeWorkbookHolder.getWorkbook(); + // 数据字典的sheet页 + Sheet dictSheet = workbook.createSheet(dictSheetName); + for (KeyValue> keyValue : selectMap) { + // 设置下拉单元格的首行、末行、首列、末列 + CellRangeAddressList rangeAddressList = new CellRangeAddressList(1, 65533, keyValue.getKey(), keyValue.getKey()); + int rowLen = keyValue.getValue().size(); + // 设置字典sheet页的值 每一列一个字典项 + for (int i = 0; i < rowLen; i++) { + Row row = dictSheet.getRow(i); + if (row == null) { + row = dictSheet.createRow(i); + } + row.createCell(keyValue.getKey()).setCellValue(keyValue.getValue().get(i)); + } + String excelColumn = getExcelColumn(keyValue.getKey()); + // 下拉框数据来源 eg:字典sheet!$B1:$B2 + String refers = dictSheetName + "!$" + excelColumn + "$1:$" + excelColumn + "$" + rowLen; + // 创建可被其他单元格引用的名称 + Name name = workbook.createName(); + // 设置名称的名字 + name.setNameName("dict" + keyValue.getKey()); + // 设置公式 + name.setRefersToFormula(refers); + // 设置引用约束 + DataValidationConstraint constraint = helper.createFormulaListConstraint("dict" + keyValue.getKey()); + // 设置约束 + DataValidation validation = helper.createValidation(constraint, rangeAddressList); + if (validation instanceof HSSFDataValidation) { + validation.setSuppressDropDownArrow(false); + } else { + validation.setSuppressDropDownArrow(true); + validation.setShowErrorBox(true); + } + // 阻止输入非下拉框的值 + validation.setErrorStyle(DataValidation.ErrorStyle.STOP); + validation.createErrorBox("提示", "此值不存在于下拉选择中!"); + // 添加下拉框约束 + writeSheetHolder.getSheet().addValidationData(validation); + } + } + + /** + * 将数字列转化成为字母列 + * + * @param num 数字 + * @return 字母 + */ + private String getExcelColumn(int num) { + String column = ""; + int len = alphabet.length - 1; + int first = num / len; + int second = num % len; + if (num <= len) { + column = alphabet[num] + ""; + } else { + column = alphabet[first - 1] + ""; + if (second == 0) { + column = column + alphabet[len] + ""; + } else { + column = column + alphabet[second - 1] + ""; + } + } + return column; + } + +} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index c2104693e..83877ece8 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,11 +1,13 @@ package cn.iocoder.yudao.framework.excel.core.util; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.converters.longconverter.LongStringConverter; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -21,12 +23,12 @@ public class ExcelUtils { /** * 将列表以 Excel 响应给前端 * - * @param response 响应 - * @param filename 文件名 + * @param response 响应 + * @param filename 文件名 * @param sheetName Excel sheet 名 - * @param head Excel head 头 - * @param data 数据列表哦 - * @param 泛型,保证 head 和 data 类型的一致性 + * @param head Excel head 头 + * @param data 数据列表哦 + * @param 泛型,保证 head 和 data 类型的一致性 * @throws IOException 写入失败的情况 */ public static void write(HttpServletResponse response, String filename, String sheetName, @@ -38,12 +40,37 @@ public class ExcelUtils { .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 .sheet(sheetName).doWrite(data); // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8)); + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name())); + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + } + + /** + * 将列表以 Excel 响应给前端 + * + * @param response 响应 + * @param filename 文件名 + * @param sheetName Excel sheet 名 + * @param head Excel head 头 + * @param data 数据列表哦 + * @param selectMap 下拉选择数据 Map + * @throws IOException 写入失败的情况 + */ + public static void write(HttpServletResponse response, String filename, String sheetName, + Class head, List data, List>> selectMap) throws IOException { + // 输出 Excel + EasyExcel.write(response.getOutputStream(), head) + .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 + .registerWriteHandler(new SelectSheetWriteHandler(selectMap)) // 基于固定 sheet 实现下拉框 + .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 + .sheet(sheetName).doWrite(data); + // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name())); response.setContentType("application/vnd.ms-excel;charset=UTF-8"); } public static List read(MultipartFile file, Class head) throws IOException { - return EasyExcel.read(file.getInputStream(), head, null) + return EasyExcel.read(file.getInputStream(), head, null) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .doReadAllSync(); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index e567aeecd..beb477988 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -10,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 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.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*; @@ -19,6 +21,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 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.dict.DictDataApi; 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; @@ -34,9 +37,7 @@ import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -44,6 +45,7 @@ import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*; import static java.util.Collections.singletonList; @Tag(name = "管理后台 - CRM 客户") @@ -61,6 +63,8 @@ public class CrmCustomerController { private DeptApi deptApi; @Resource private AdminUserApi adminUserApi; + @Resource + private DictDataApi dictDataApi; @PostMapping("/create") @Operation(summary = "创建客户") @@ -258,7 +262,7 @@ public class CrmCustomerController { .areaId(null).detailAddress("").remark("").build() ); // 输出 - ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list); + ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list, builderSelectMap()); } @PostMapping("/import") @@ -314,4 +318,23 @@ public class CrmCustomerController { return success(true); } + private List>> builderSelectMap() { + List>> selectMap = new ArrayList<>(); + // 获取地区下拉数据 + Area area = AreaUtils.getArea(Area.ID_CHINA); + selectMap.add(new KeyValue<>(6, AreaUtils.getAllAreaNodePaths(area.getChildren()))); + // 获取客户所属行业 + List customerIndustries = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_INDUSTRY); + selectMap.add(new KeyValue<>(8, customerIndustries)); + // 获取客户等级 + List customerLevels = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_LEVEL); + selectMap.add(new KeyValue<>(9, customerLevels)); + // 获取客户来源 + List customerSources = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_SOURCE); + selectMap.add(new KeyValue<>(10, customerSources)); + // 升序不然创建下拉会报错 + selectMap.sort(Comparator.comparing(item -> item.getValue().size())); + return selectMap; + } + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java index 107184564..bfc2a1590 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.api.dict; import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; import java.util.Collection; +import java.util.List; /** * 字典数据 API 接口 @@ -39,4 +40,12 @@ public interface DictDataApi { */ DictDataRespDTO parseDictData(String type, String label); + /** + * 获得字典数据标签列表 + * + * @param dictType 字典类型 + * @return 字典数据标签列表 + */ + List getDictDataLabelList(String dictType); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java index 55313c7cf..f3ddb6927 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java @@ -1,13 +1,18 @@ package cn.iocoder.yudao.module.system.api.dict; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.service.dict.DictDataService; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; -import jakarta.annotation.Resource; import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; /** * 字典数据 API 实现类 @@ -37,4 +42,13 @@ public class DictDataApiImpl implements DictDataApi { return BeanUtils.toBean(dictData, DictDataRespDTO.class); } + @Override + public List getDictDataLabelList(String dictType) { + List dictDataList = dictDataService.getDictDataListByDictType(dictType); + if (CollUtil.isEmpty(dictDataList)) { + return Collections.emptyList(); + } + return convertList(dictDataList, DictDataDO::getLabel); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java index a752476da..ce75c9afe 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java @@ -99,4 +99,12 @@ public interface DictDataService { */ DictDataDO parseDictData(String dictType, String label); + /** + * 获得字典数据列表 + * + * @param dictType 字典类型 + * @return 字典数据列表 + */ + List getDictDataListByDictType(String dictType); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java index 95ef27ef5..7982e2302 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java @@ -11,10 +11,10 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper; import com.google.common.annotations.VisibleForTesting; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.Comparator; import java.util.List; @@ -169,4 +169,9 @@ public class DictDataServiceImpl implements DictDataService { return dictDataMapper.selectByDictTypeAndLabel(dictType, label); } + @Override + public List getDictDataListByDictType(String dictType) { + return dictDataMapper.selectList(DictDataDO::getDictType, dictType); + } + } From 740e9297fa60d3fd5a2c4070f2f2f6852220568d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 22 Feb 2024 09:35:57 +0800 Subject: [PATCH 23/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=95=86=E6=9C=BA=E5=92=8C=E8=81=94=E7=B3=BB=E4=BA=BA?= =?UTF-8?q?=E4=B9=8B=E9=97=B4=E7=9A=84=E5=85=B3=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/CrmContactController.java | 8 +++++++ .../admin/contact/vo/CrmContactPageReqVO.java | 3 +++ .../convert/business/CrmBusinessConvert.java | 22 ------------------- .../contact/CrmContactBusinessMapper.java | 4 ++++ .../dal/mysql/contact/CrmContactMapper.java | 12 ++++++++++ .../business/CrmBusinessServiceImpl.java | 19 +++++++++++----- .../contact/CrmContactBusinessService.java | 17 +++++++------- .../CrmContactBusinessServiceImpl.java | 22 +++++-------------- .../service/contact/CrmContactService.java | 11 ++++++++++ .../contact/CrmContactServiceImpl.java | 12 ++++++++++ 10 files changed, 77 insertions(+), 53 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java 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 aedcb905e..4d9385199 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 @@ -139,6 +139,14 @@ public class CrmContactController { return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal())); } + @GetMapping("/page-by-business") + @Operation(summary = "获得联系人分页,基于指定商机") + public CommonResult> getContactPageByBusiness(@Valid CrmContactPageReqVO pageVO) { + Assert.notNull(pageVO.getBusinessId(), "商机编号不能为空"); + PageResult pageResult = contactService.getContactPageByBusinessId(pageVO); + return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal())); + } + @GetMapping("/export-excel") @Operation(summary = "导出联系人 Excel") @PreAuthorize("@ss.hasPermission('crm:contact:export')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java index 75294a1bd..6698a3855 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java @@ -39,4 +39,7 @@ public class CrmContactPageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 + @Schema(description = "商机编号", example = "10430") + private Long businessId; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java deleted file mode 100644 index 381f98409..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.business; - -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -/** - * 商机 Convert - * - * @author ljlleo - */ -@Mapper -public interface CrmBusinessConvert { - - CrmBusinessConvert INSTANCE = Mappers.getMapper(CrmBusinessConvert.class); - - @Mapping(target = "bizId", source = "reqVO.id") - CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId); - -} 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 01f8bc888..8fd82b90b 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 @@ -31,4 +31,8 @@ public interface CrmContactBusinessMapper extends BaseMapperX selectListByBusinessId(Long businessId) { + return selectList(CrmContactBusinessDO::getBusinessId, businessId); + } + } 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 2ad22dfe5..4cc7a97b4 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 @@ -40,6 +40,18 @@ public interface CrmContactMapper extends BaseMapperX { .orderByDesc(CrmContactDO::getId)); } + default PageResult selectPageByBusinessId(CrmContactPageReqVO pageVO, Collection ids) { + return selectPage(pageVO, new LambdaQueryWrapperX() + .in(CrmContactDO::getId, ids) // 指定联系人编号 + .likeIfPresent(CrmContactDO::getName, pageVO.getName()) + .eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile()) + .eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone()) + .eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail()) + .eqIfPresent(CrmContactDO::getQq, pageVO.getQq()) + .eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat()) + .orderByDesc(CrmContactDO::getId)); + } + default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 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 7c4e7cb94..18fa69419 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 @@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; +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.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; @@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 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.service.product.CrmProductService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; @@ -38,6 +39,7 @@ import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Collection; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -100,14 +102,19 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { businessProducts.forEach(item -> item.setBusinessId(business.getId())); businessProductMapper.insertBatch(businessProducts); } - // 在联系人的详情页,如果直接【新建商机】,则需要关联下。 - contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId()); + // 3. 创建数据权限 // 设置当前操作的人为负责人 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 4. 记录操作日志上下文 + // 4. 在联系人的详情页,如果直接【新建商机】,则需要关联下 + if (createReqVO.getContactId() != null) { + contactBusinessService.createContactBusinessList(new CrmContactBusinessReqVO().setContactId(createReqVO.getContactId()) + .setBusinessIds(Collections.singletonList(business.getId()))); + } + + // 5. 记录操作日志上下文 LogRecordContext.putVariable("business", business); return business.getId(); } @@ -262,8 +269,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessDO business = validateBusinessExists(reqVO.getId()); // 2.1 数据权限转移 - permissionService.transferPermission( - CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); + permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_BUSINESS.getType(), + reqVO.getNewOwnerUserId(), reqVO.getId(), CrmPermissionLevelEnum.OWNER.getLevel())); // 2.2 设置新的负责人 businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); 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 882958b64..76477c281 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 @@ -13,15 +13,6 @@ import java.util.List; */ public interface CrmContactBusinessService { - /** - * 创建联系人人商机关联 - * - * @param contactId 联系人编号 - * @param businessId 商机编号 - */ - void createContactBusiness(Long contactId, Long businessId); - - /** * 创建联系人与商机的关联 * @@ -51,4 +42,12 @@ public interface CrmContactBusinessService { */ List getContactBusinessListByContactId(Long contactId); + /** + * 获得联系人与商机的关联列表,基于商机编号 + * + * @param businessId 商机编号 + * @return 联系人商机关联 + */ + List getContactBusinessListByBusinessId(Long businessId); + } \ No newline at end of file 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 58821e07b..e975df14e 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 @@ -41,22 +41,6 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService @Lazy // 延迟加载,为了解决延迟加载 private CrmContactService contactService; - @Override - public void createContactBusiness(Long contactId, Long businessId) { - // 校验存在 - CrmContactDO contact = contactService.getContact(contactId); - if (contact == null) { - throw exception(CONTACT_NOT_EXISTS); - } - CrmBusinessDO business = businessService.getBusiness(businessId); - if (business == null) { - throw exception(BUSINESS_NOT_EXISTS); - } - - // 插入 - contactBusinessMapper.insert(new CrmContactBusinessDO(null, contactId, businessId)); - } - @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) { @@ -107,4 +91,10 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService return contactBusinessMapper.selectListByContactId(contactId); } + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#businessId", level = CrmPermissionLevelEnum.READ) + public List getContactBusinessListByBusinessId(Long businessId) { + return contactBusinessMapper.selectListByBusinessId(businessId); + } + } \ No newline at end of file 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 e94807f25..822bf095d 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 @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import jakarta.validation.Valid; @@ -150,6 +151,16 @@ public interface CrmContactService { */ PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO); + /** + * 获得联系人分页 + * + * 数据权限:基于 {@link CrmBusinessDO} + * + * @param pageVO 分页查询 + * @return 联系人分页 + */ + PageResult getContactPageByBusinessId(CrmContactPageReqVO pageVO); + /** * 获取关联客户的联系人数量 * 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 342401c1e..651da773f 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 @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusines import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; @@ -36,6 +37,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static java.util.Collections.singletonList; @@ -289,6 +291,16 @@ public class CrmContactServiceImpl implements CrmContactService { return contactMapper.selectPageByCustomerId(pageVO); } + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#pageVO.businessId", level = CrmPermissionLevelEnum.READ) + public PageResult getContactPageByBusinessId(CrmContactPageReqVO pageVO) { + List contactBusinessList = contactBusinessService.getContactBusinessListByBusinessId(pageVO.getBusinessId()); + if (CollUtil.isEmpty(contactBusinessList)) { + return PageResult.empty(); + } + return contactMapper.selectPageByBusinessId(pageVO, convertSet(contactBusinessList, CrmContactBusinessDO::getContactId)); + } + @Override public Long getContactCountByCustomerId(Long customerId) { return contactMapper.selectCount(CrmContactDO::getCustomerId, customerId); From 41b8575b8d878d872639e7be4917241ddc4899ac Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 22 Feb 2024 11:07:34 +0800 Subject: [PATCH 24/54] =?UTF-8?q?CRM=EF=BC=9A=E5=AE=8C=E5=96=84=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ip/core/utils/AreaUtils.java | 57 ++++++++++++++----- .../yudao-spring-boot-starter-excel/pom.xml | 5 ++ .../excel/core/convert/AreaConvert.java | 46 +++++++++++++++ .../core/handler/SelectSheetWriteHandler.java | 16 +++--- .../admin/customer/CrmCustomerController.java | 7 ++- .../vo/customer/CrmCustomerImportExcelVO.java | 5 +- 6 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java index 1a773cda5..adcfc345b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java @@ -4,7 +4,7 @@ import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.csv.CsvRow; import cn.hutool.core.text.csv.CsvUtil; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; @@ -18,6 +18,7 @@ import java.util.Map; import java.util.function.Function; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst; /** * 区域工具类 @@ -75,6 +76,26 @@ public class AreaUtils { return areas.get(id); } + /** + * 获得指定区域对应的编号 + * + * @param path 区域编号 + * @return 编号 + */ + public static Area getArea(String path) { + String[] paths = path.split("/"); + Area area = null; + for (int i = 0; i < paths.length; i++) { + final int finalI = i; + if (area == null) { + area = findFirst(convertList(areas.values(), a -> a), item -> ObjUtil.equal(paths[finalI], item.getName())); + continue; + } + area = findFirst(area.getChildren(), item -> ObjUtil.equal(paths[finalI], item.getName())); + } + return area; + } + /** * 获取所有节点的全路径名称如:河南省/石家庄市/新华区 * @@ -82,23 +103,29 @@ public class AreaUtils { * @return 所有节点的全路径名称 */ public static List getAllAreaNodePaths(List areas) { - return convertList(areas, AreaUtils::buildTreePath); + List paths = new ArrayList<>(); + areas.forEach(area -> traverse(area, "", paths)); + return paths; } - // TODO @puhui999: 展开树再构建全路径 - private static String buildTreePath(Area node) { - if (node.getParent() == null || Area.ID_CHINA.equals(node.getParent().getId())) { // 忽略中国 - // 已经是根节点,直接返回节点名称 - return node.getName(); - } else { - // 递归拼接上级节点的名称 - Area parent = getArea(node.getParent().getId()); - if (parent != null) { - String parentPath = buildTreePath(parent); - return parentPath + "/" + node.getName(); - } + /** + * 构建一棵树的所有节点的全路径名称,并将其存储为 "祖先/父级/子级" 的形式 + * + * @param node 父节点 + * @param path 全路径名称 + * @param paths 全路径名称列表 + */ + private static void traverse(Area node, String path, List paths) { + if (node == null) { + return; + } + // 构建当前节点的路径 + String currentPath = path.isEmpty() ? node.getName() : path + "/" + node.getName(); + paths.add(currentPath); + // 递归遍历子节点 + for (Area child : node.getChildren()) { + traverse(child, currentPath, paths); } - return StrUtil.EMPTY; } /** diff --git a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml index 5280f72f7..b5d5c24a2 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml @@ -46,6 +46,11 @@ com.alibaba easyexcel + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + provided + diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java new file mode 100644 index 000000000..f218c0b14 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.framework.excel.core.convert; + +import cn.hutool.core.convert.Convert; +import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import lombok.extern.slf4j.Slf4j; + +/** + * Excel 数据地区转换器 + * + * @author HUIHUI + */ +@Slf4j +public class AreaConvert implements Converter { + + @Override + public Class supportJavaTypeKey() { + throw new UnsupportedOperationException("暂不支持,也不需要"); + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + throw new UnsupportedOperationException("暂不支持,也不需要"); + } + + @Override + public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) { + // 解析地区编号 + String label = readCellData.getStringValue(); + Area area = AreaUtils.getArea(label); + if (area == null) { + log.error("[convertToJavaData][label({}) 解析不掉]", label); + return null; + } + // 将 value 转换成对应的属性 + Class fieldClazz = contentProperty.getField().getType(); + return Convert.convert(fieldClazz, area.getId()); + } + +} 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 571f4c983..661db5369 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 @@ -9,6 +9,7 @@ import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddressList; +import java.util.Comparator; import java.util.List; /** @@ -18,12 +19,13 @@ import java.util.List; */ public class SelectSheetWriteHandler implements SheetWriteHandler { - private List>> selectMap; + private final List>> selectMap; - private final char[] alphabet = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + private static final char[] ALPHABET = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; public SelectSheetWriteHandler(List>> selectMap) { + selectMap.sort(Comparator.comparing(item -> item.getValue().size())); // 升序不然创建下拉会报错 this.selectMap = selectMap; } @@ -86,17 +88,17 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { */ private String getExcelColumn(int num) { String column = ""; - int len = alphabet.length - 1; + int len = ALPHABET.length - 1; int first = num / len; int second = num % len; if (num <= len) { - column = alphabet[num] + ""; + column = ALPHABET[num] + ""; } else { - column = alphabet[first - 1] + ""; + column = ALPHABET[first - 1] + ""; if (second == 0) { - column = column + alphabet[len] + ""; + column = column + ALPHABET[len] + ""; } else { - column = column + alphabet[second - 1] + ""; + column = column + ALPHABET[second - 1] + ""; } } return column; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index beb477988..df6e0e625 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -37,7 +37,10 @@ import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -332,8 +335,6 @@ public class CrmCustomerController { // 获取客户来源 List customerSources = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_SOURCE); selectMap.add(new KeyValue<>(10, customerSources)); - // 升序不然创建下拉会报错 - selectMap.sort(Comparator.comparing(item -> item.getValue().size())); return selectMap; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java index 4b21fff1c..2c39472fd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import com.alibaba.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; @@ -39,14 +40,12 @@ public class CrmCustomerImportExcelVO { @ExcelProperty("邮箱") private String email; - // TODO @puhui999:需要选择省市区,需要研究下,怎么搞合理点; - @ExcelProperty("地区编号") + @ExcelProperty(value = "地区", converter = AreaConvert.class) private Integer areaId; @ExcelProperty("详细地址") private String detailAddress; - // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框 @ExcelProperty(value = "所属行业", converter = DictConvert.class) @DictFormat(CRM_CUSTOMER_INDUSTRY) private Integer industryId; From c97c9f882e387154a649092215a70ab4087e6a6c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 22 Feb 2024 20:41:28 +0800 Subject: [PATCH 25/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=95=86=E6=9C=BA=E7=8A=B6=E6=80=81=E7=9A=84=E5=8F=98?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 3 + .../module/crm/enums/LogRecordConstants.java | 3 + .../crm/enums/business/CrmBizEndStatus.java | 55 ------------------- .../business/CrmBusinessEndStatusEnum.java | 45 +++++++++++++++ .../admin/business/CrmBusinessController.java | 19 +++++-- .../vo/business/CrmBusinessRespVO.java | 2 +- .../CrmBusinessUpdateStatusReqVO.java | 30 ++++++++++ .../dataobject/business/CrmBusinessDO.java | 4 +- .../business/CrmBusinessProductDO.java | 2 +- .../business/CrmBusinessStatusDO.java | 4 +- .../business/CrmBusinessStatusTypeDO.java | 4 +- .../business/CrmBusinessStatusMapper.java | 5 ++ .../service/business/CrmBusinessService.java | 24 ++++++++ .../business/CrmBusinessServiceImpl.java | 39 ++++++++++++- .../business/CrmBusinessStatusService.java | 16 ++++++ .../CrmBusinessStatusServiceImpl.java | 14 +++++ 16 files changed, 200 insertions(+), 69 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBizEndStatus.java create mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateStatusReqVO.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 300f2ad63..fa1cec68a 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -21,6 +21,8 @@ public interface ErrorCodeConstants { // ========== 商机管理 1-020-002-000 ========== ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); ErrorCode BUSINESS_DELETE_FAIL_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除"); + ErrorCode BUSINESS_UPDATE_STATUS_FAIL_END_STATUS = new ErrorCode(1_020_002_002, "更新商机状态失败,原因:已经是结束状态"); + ErrorCode BUSINESS_UPDATE_STATUS_FAIL_STATUS_EQUALS = new ErrorCode(1_020_002_003, "更新商机状态失败,原因:已经是该状态"); // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); @@ -81,6 +83,7 @@ public interface ErrorCodeConstants { ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态组的名称已存在"); ErrorCode BUSINESS_STATUS_UPDATE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行更新"); ErrorCode BUSINESS_STATUS_DELETE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行删除"); + ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_010_003, "商机状态不存在"); // ========== 客户公海规则设置 1_020_012_000 ========== ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用"); 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 eaf0affc3..1b085b70b 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 @@ -93,6 +93,9 @@ public interface LogRecordConstants { String CRM_BUSINESS_TRANSFER_SUCCESS = "将商机【{{#business.name}}】的负责人从【{getAdminUserById{#business.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; String CRM_BUSINESS_FOLLOW_UP_SUB_TYPE = "商机跟进"; String CRM_BUSINESS_FOLLOW_UP_SUCCESS = "商机跟进【{{#businessName}}】"; + String CRM_BUSINESS_UPDATE_STATUS_SUB_TYPE = "更新商机状态"; + String CRM_BUSINESS_UPDATE_STATUS_SUCCESS = "更新了商机【{{#businessName}}】的状态从【{{#oldStatusName}}】变更为了【{{#newStatusName}}】"; +// String CRM_BUSINESS_UPDATE_STATUS_SUCCESS = "阿巴阿巴"; // ======================= CRM_CONTRACT 合同 ======================= diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBizEndStatus.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBizEndStatus.java deleted file mode 100644 index 55548dbff..000000000 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBizEndStatus.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.module.crm.enums.business; - -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -// TODO @lzxhqs:1)title、description、create 可以删除,非标准的 javadoc 注释哈,然后可以在类上加下这个类的注释;2)CrmBizEndStatus 改成 CrmBusinessEndStatus,非必要不缩写哈,可阅读比较重要 -/** - * @author lzxhqs - * @version 1.0 - * @title CrmBizEndStatus - * @description - * @create 2024/1/12 - */ -@RequiredArgsConstructor -@Getter -public enum CrmBizEndStatus implements IntArrayValuable { - - WIN(1, "赢单"), - LOSE(2, "输单"), - INVALID(3, "无效"); - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizEndStatus::getStatus).toArray(); - - // TODO @lzxhqs:这里的方法,建议放到 49 行之后;一般类里是,静态变量,普通变量;静态方法;普通方法 - public static boolean isWin(Integer status) { - return ObjectUtil.equal(WIN.getStatus(), status); - } - - public static boolean isLose(Integer status) { - return ObjectUtil.equal(LOSE.getStatus(), status); - } - - public static boolean isInvalid(Integer status) { - return ObjectUtil.equal(INVALID.getStatus(), status); - } - - /** - * 场景类型 - */ - private final Integer status; - /** - * 场景名称 - */ - private final String name; - - @Override - public int[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java new file mode 100644 index 000000000..4736c01b7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.crm.enums.business; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * 商机的结束状态枚举 + * + * @author lzxhqs + */ +@RequiredArgsConstructor +@Getter +public enum CrmBusinessEndStatusEnum implements IntArrayValuable { + + WIN(1, "赢单"), + LOSE(2, "输单"), + INVALID(3, "无效"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBusinessEndStatusEnum::getStatus).toArray(); + + /** + * 场景类型 + */ + private final Integer status; + /** + * 场景名称 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + + public static CrmBusinessEndStatusEnum fromStatus(Integer status) { + return Arrays.stream(values()) + .filter(value -> value.getStatus().equals(status)) + .findFirst() + .orElse(null); + } + +} 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 dd3c0eb4e..7603f3c3b 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 @@ -8,10 +8,7 @@ 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.business.vo.business.CrmBusinessPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; @@ -87,6 +84,14 @@ public class CrmBusinessController { return success(true); } + @PutMapping("/update-status") + @Operation(summary = "更新商机状态") + @PreAuthorize("@ss.hasPermission('crm:business:update')") + public CommonResult updateBusinessStatus(@Valid @RequestBody CrmBusinessUpdateStatusReqVO updateStatusReqVO) { + businessService.updateBusinessStatus(updateStatusReqVO); + return success(true); + } + @DeleteMapping("/delete") @Operation(summary = "删除商机") @Parameter(name = "id", description = "编号", required = true) @@ -116,7 +121,8 @@ public class CrmBusinessController { convertSet(businessProducts, CrmBusinessProductDO::getProductId)); businessVO.setProducts(BeanUtils.toBean(businessProducts, CrmBusinessRespVO.Product.class, businessProductVO -> MapUtils.findAndThen(productMap, businessProductVO.getProductId(), - product -> businessProductVO.setProductNo(product.getNo()).setProductUnit(product.getUnit())))); + product -> businessProductVO.setProductName(product.getName()) + .setProductNo(product.getNo()).setProductUnit(product.getUnit())))); return businessVO; } @@ -209,7 +215,8 @@ public class CrmBusinessController { }); // 2.3 设置商机状态 MapUtils.findAndThen(statusTypeMap, businessVO.getStatusTypeId(), statusType -> businessVO.setStatusTypeName(statusType.getName())); - MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(status.getName())); + MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName( + businessService.getBusinessStatusName(businessVO.getEndStatus(), status))); }); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index d754c8c83..bbea613c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -134,7 +134,7 @@ public class CrmBusinessRespVO { private BigDecimal businessPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") - private Integer count; + private BigDecimal count; @Schema(description = "总计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") private BigDecimal totalPrice; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateStatusReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateStatusReqVO.java new file mode 100644 index 000000000..7bfd1df93 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessUpdateStatusReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.business.CrmBusinessEndStatusEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - CRM 商机更新状态 Request VO") +@Data +public class CrmBusinessUpdateStatusReqVO { + + @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") + @NotNull(message = "商机编号不能为空") + private Long id; + + @Schema(description = "状态编号", example = "1") + private Long statusId; + + @Schema(description = "结束状态", example = "1") + @InEnum(value = CrmBusinessEndStatusEnum.class) + private Integer endStatus; + + @AssertTrue(message = "变更状态不正确") + public boolean isStatusValid() { + return statusId != null || endStatus != null; + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java index 770c0110e..a30ece21f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus; +import cn.iocoder.yudao.module.crm.enums.business.CrmBusinessEndStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -77,7 +77,7 @@ public class CrmBusinessDO extends BaseDO { /** * 结束状态 * - * 枚举 {@link CrmBizEndStatus} + * 枚举 {@link CrmBusinessEndStatusEnum} */ private Integer endStatus; /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 6adc7e42e..16990dcc5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -10,7 +10,7 @@ import lombok.*; import java.math.BigDecimal; /** - * 商机产品关联表 DO + * CRM 商机产品关联表 DO * * CrmBusinessDO : CrmBusinessProductDO = 1 : N * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java index 17ce4f88c..4ec8bbe4a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java @@ -6,7 +6,9 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; /** - * 商机状态 DO + * CRM 商机状态 DO + * + * 注意,它是个配置表 * * @author ljlleo */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java index 791a8b700..95b7a1f26 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java @@ -11,7 +11,9 @@ import lombok.*; import java.util.List; /** - * 商机状态组 DO + * CRM 商机状态组 DO + * + * 注意,它是个配置表 * * @author ljlleo */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java index f157e7dc6..dfe7afcc3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java @@ -22,4 +22,9 @@ public interface CrmBusinessStatusMapper extends BaseMapperX ids, LocalDateTime contactNextTime); + /** + * 更新商机的状态 + * + * @param reqVO 更新请求 + */ + void updateBusinessStatus(CrmBusinessUpdateStatusReqVO reqVO); + /** * 删除商机 * @@ -156,4 +166,18 @@ public interface CrmBusinessService { */ Long getBusinessCountByStatusTypeId(Long statusTypeId); + /** + * 获得商机状态名称 + * + * @param endStatus 结束状态 + * @param status 商机状态 + * @return 商机状态名称 + */ + default String getBusinessStatusName(Integer endStatus, CrmBusinessStatusDO status) { + if (endStatus != null) { + return CrmBusinessEndStatusEnum.fromStatus(endStatus).getName(); + } + return status.getName(); + } + } 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 18fa69419..a15fe8068 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 @@ -8,9 +8,11 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateStatusReqVO; 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.business.CrmBusinessProductDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; @@ -44,8 +46,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_DELETE_FAIL_CONTRACT_EXISTS; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; /** @@ -218,6 +219,40 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice)); } + + @Override + @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_STATUS_SUB_TYPE, bizNo = "{{#reqVO.id}}", + success = CRM_BUSINESS_UPDATE_STATUS_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.WRITE) + public void updateBusinessStatus(CrmBusinessUpdateStatusReqVO reqVO) { + // 1.1 校验存在 + CrmBusinessDO business = validateBusinessExists(reqVO.getId()); + // 1.2 校验商机未结束 + if (business.getEndStatus() != null) { + throw exception(BUSINESS_UPDATE_STATUS_FAIL_END_STATUS); + } + // 1.3 校验商机状态 + CrmBusinessStatusDO status = null; + if (reqVO.getStatusId() != null) { + status = businessStatusService.validateBusinessStatus(business.getStatusTypeId(), reqVO.getStatusId()); + } + // 1.4 校验是不是状态没变更 + if ((reqVO.getStatusId() != null && reqVO.getStatusId().equals(business.getStatusId())) + || (reqVO.getEndStatus() != null && reqVO.getEndStatus().equals(business.getEndStatus()))) { + throw exception(BUSINESS_UPDATE_STATUS_FAIL_STATUS_EQUALS); + } + + // 2. 更新商机状态 + businessMapper.updateById(new CrmBusinessDO().setId(reqVO.getId()).setStatusId(reqVO.getStatusId()) + .setEndStatus(reqVO.getEndStatus())); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("businessName", business.getName()); + LogRecordContext.putVariable("oldStatusName", getBusinessStatusName(business.getEndStatus(), + businessStatusService.getBusinessStatus(business.getStatusId()))); + LogRecordContext.putVariable("newStatusName", getBusinessStatusName(reqVO.getEndStatus(), status)); + } + @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_DELETE_SUB_TYPE, bizNo = "{{#id}}", diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java index cc527ec3e..bd9c16439 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java @@ -116,4 +116,20 @@ public interface CrmBusinessStatusService { return convertMap(getBusinessStatusList(ids), CrmBusinessStatusDO::getId); } + /** + * 获得商机状态 + * + * @param id 编号 + * @return 商机状态 + */ + CrmBusinessStatusDO getBusinessStatus(Long id); + + /** + * 校验商机状态 + * + * @param statusTypeId 商机状态组编号 + * @param statusId 商机状态编号 + */ + CrmBusinessStatusDO validateBusinessStatus(Long statusTypeId, Long statusId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java index 580b431aa..2ec77667a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java @@ -178,4 +178,18 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { return businessStatusMapper.selectBatchIds(ids); } + @Override + public CrmBusinessStatusDO getBusinessStatus(Long id) { + return businessStatusMapper.selectById(id); + } + + @Override + public CrmBusinessStatusDO validateBusinessStatus(Long statusTypeId, Long statusId) { + CrmBusinessStatusDO status = businessStatusMapper.selectByTypeIdAndId(statusTypeId, statusId); + if (status == null) { + throw exception(BUSINESS_STATUS_NOT_EXISTS); + } + return status; + } + } From ef26b5e8dc2512aab50bb25d52c8f92a8ef7ab01 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 22 Feb 2024 21:54:06 +0800 Subject: [PATCH 26/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=90=88=E5=90=8C=E7=9A=84=E5=88=97=E8=A1=A8=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/business/CrmBusinessRespVO.java | 2 +- .../vo/business/CrmBusinessSaveReqVO.java | 6 +- .../admin/contract/CrmContractController.java | 68 ++++++---- .../admin/contract/vo/CrmContractRespVO.java | 118 +++++++++--------- .../contract/vo/CrmContractSaveReqVO.java | 58 ++++----- .../convert/contract/CrmContractConvert.java | 70 ----------- .../business/CrmBusinessProductDO.java | 2 +- .../dataobject/contract/CrmContractDO.java | 66 +++++----- .../contract/CrmContractProductDO.java | 37 +++--- .../dal/mysql/contract/CrmContractMapper.java | 2 +- .../business/CrmBusinessServiceImpl.java | 3 +- .../contract/CrmContractServiceImpl.java | 39 +++--- 12 files changed, 204 insertions(+), 267 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index bbea613c8..49cdcb80b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -130,7 +130,7 @@ public class CrmBusinessRespVO { @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") private BigDecimal productPrice; - @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + @Schema(description = "商机价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") private BigDecimal businessPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java index 8b0c53d21..a9ebaae05 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java @@ -53,7 +53,7 @@ public class CrmBusinessSaveReqVO { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime dealTime; - @Schema(description = "整单折扣") + @Schema(description = "整单折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "55.00") @DiffLogField(name = "整单折扣") @NotNull(message = "整单折扣不能为空") private BigDecimal discountPercent; @@ -82,8 +82,8 @@ public class CrmBusinessSaveReqVO { @NotNull(message = "产品单价不能为空") private BigDecimal productPrice; - @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") - @NotNull(message = "合同价格不能为空") + @Schema(description = "商机价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + @NotNull(message = "商机价格不能为空") private BigDecimal businessPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") 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 d691a1701..65226866f 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 @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 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; @@ -12,18 +13,17 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR 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.convert.contract.CrmContractConvert; 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; -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; 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.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; +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; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -44,6 +44,7 @@ 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.*; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static java.util.Collections.singletonList; @@ -64,8 +65,11 @@ public class CrmContractController { private CrmBusinessService businessService; @Resource private CrmProductService productService; + @Resource private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; @PostMapping("/create") @Operation(summary = "创建合同") @@ -96,15 +100,21 @@ public class CrmContractController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult getContract(@RequestParam("id") Long id) { - // 1. 查询合同 CrmContractDO contract = contractService.getContract(id); - if (contract == null) { - return success(null); - } + return success(buildContractDetail(contract)); + } - // 2. 拼接合同信息 - List respVOList = buildContractDetailList(singletonList(contract)); - return success(respVOList.get(0)); + private CrmContractRespVO buildContractDetail(CrmContractDO contract) { + if (contract == null) { + return null; + } +// List productList = null; +// if (contractList.size() == 1) { +// List contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId()); +// contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId); +// productList = productService.getProductList(convertSet(contractProductList, CrmContractProductDO::getProductId)); +// } + return buildContractDetailList(singletonList(contract)).get(0); } @GetMapping("/page") @@ -161,27 +171,35 @@ public class CrmContractController { if (CollUtil.isEmpty(contractList)) { return Collections.emptyList(); } - // 1. 获取客户列表 - List customerList = customerService.getCustomerList( + // 1.1 获取客户列表 + Map customerMap = customerService.getCustomerMap( convertSet(contractList, CrmContractDO::getCustomerId)); - // 2. 获取创建人、负责人列表 + // 1.2 获取创建人、负责人列表 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contractList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); - // 3. 获取联系人 + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + // 1.3 获取联系人 Map contactMap = convertMap(contactService.getContactList(convertSet(contractList, - CrmContractDO::getContactId)), CrmContactDO::getId); - // 4. 获取商机 + CrmContractDO::getSignContactId)), CrmContactDO::getId); + // 1.4 获取商机 Map businessMap = convertMap(businessService.getBusinessList(convertSet(contractList, CrmContractDO::getBusinessId)), CrmBusinessDO::getId); - // 5. 获取合同关联的商品 - Map contractProductMap = null; - List productList = null; - if (contractList.size() == 1) { - List contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId()); - contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId); - productList = productService.getProductList(convertSet(contractProductList, CrmContractProductDO::getProductId)); - } - return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList); + // 2. 拼接数据 + return BeanUtils.toBean(contractList, CrmContractRespVO.class, contractVO -> { + // 2.1 设置客户信息 + findAndThen(customerMap, contractVO.getCustomerId(), customer -> contractVO.setCustomerName(customer.getName())); + // 2.2 设置用户信息 + findAndThen(userMap, Long.parseLong(contractVO.getCreator()), user -> contractVO.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, contractVO.getOwnerUserId(), user -> { + contractVO.setOwnerUserName(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> contractVO.setOwnerUserDeptName(dept.getName())); + }); + findAndThen(userMap, contractVO.getSignUserId(), user -> contractVO.setSignUserName(user.getNickname())); + // 2.3 设置联系人信息 + findAndThen(contactMap, contractVO.getSignContactId(), contact -> contractVO.setSignContactName(contact.getName())); + // 2.4 设置商机信息 + findAndThen(businessMap, contractVO.getBusinessId(), business -> contractVO.setBusinessName(business.getName())); + }); } @GetMapping("/check-contract-count") 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/CrmContractRespVO.java index 554e285dd..738cfaa79 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/CrmContractRespVO.java @@ -6,13 +6,11 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - @Schema(description = "管理后台 - CRM 合同 Response VO") @Data @ExcelIgnoreUnannotated @@ -26,6 +24,10 @@ public class CrmContractRespVO { @ExcelProperty("合同名称") private String name; + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20230101") + @ExcelProperty("合同编号") + private String no; + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18336") @ExcelProperty("客户编号") private Long customerId; @@ -40,72 +42,70 @@ public class CrmContractRespVO { @ExcelProperty("商机名称") private String businessName; + @Schema(description = "最后跟进时间") + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("负责人的用户编号") + private Long ownerUserId; + @Schema(description = "负责人名字", example = "25682") + @ExcelProperty("负责人名字") + private String ownerUserName; + @Schema(description = "负责人部门") + @ExcelProperty("负责人部门") + private String ownerUserDeptName; + @Schema(description = "工作流编号", example = "1043") @ExcelProperty("工作流编号") private Long processInstanceId; + @Schema(description = "审批状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("审批状态") + private Integer auditStatus; + @Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("下单日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime orderDate; - @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17144") - @ExcelProperty("负责人的用户编号") - private Long ownerUserId; - - // TODO @芋艿:未来应该支持自动生成; - @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20230101") - @ExcelProperty("合同编号") - private String no; - @Schema(description = "开始时间") @ExcelProperty("开始时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime startTime; @Schema(description = "结束时间") @ExcelProperty("结束时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime endTime; - @Schema(description = "合同金额", example = "5617") - @ExcelProperty("合同金额") - private Integer price; - - @Schema(description = "整单折扣") - @ExcelProperty("整单折扣") - private Integer discountPercent; - @Schema(description = "产品总金额", example = "19510") @ExcelProperty("产品总金额") - private Integer productPrice; + private BigDecimal totalProductPrice; - @Schema(description = "联系人编号", example = "18546") - @ExcelProperty("联系人编号") - private Long contactId; - @Schema(description = "联系人编号", example = "18546") - @ExcelProperty("联系人编号") - private String contactName; + @Schema(description = "整单折扣") + @ExcelProperty("整单折扣") + private BigDecimal discountPercent; + + @Schema(description = "合同金额", example = "5617") + @ExcelProperty("合同金额") + private BigDecimal totalPrice; + + @Schema(description = "客户签约人编号", example = "18546") + private Long signContactId; + @Schema(description = "客户签约人", example = "小豆") + @ExcelProperty("客户签约人") + private String signContactName; @Schema(description = "公司签约人", example = "14036") - @ExcelProperty("公司签约人") private Long signUserId; - @Schema(description = "公司签约人", example = "14036") + @Schema(description = "公司签约人", example = "小明") @ExcelProperty("公司签约人") private String signUserName; - @Schema(description = "最后跟进时间") - @ExcelProperty("最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime contactLastTime; - @Schema(description = "备注", example = "你猜") @ExcelProperty("备注") private String remark; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime createTime; @Schema(description = "创建人", example = "25682") @@ -118,19 +118,10 @@ public class CrmContractRespVO { @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("更新时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime updateTime; - @Schema(description = "负责人", example = "test") - @ExcelProperty("负责人") - private String ownerUserName; - - @Schema(description = "审批状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @ExcelProperty("审批状态") - private Integer auditStatus; - @Schema(description = "产品列表") - private List items; + private List products; @Schema(description = "产品列表") @Data @@ -138,26 +129,29 @@ public class CrmContractRespVO { @AllArgsConstructor public static class Item { - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") private Long id; - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是产品") - private String name; + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") + private Long productId; + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") + private String productNo; + @Schema(description = "产品单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + private Integer productUnit; - @Schema(description = "产品编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "N881") - private String no; + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + private BigDecimal productPrice; - @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer unit; + @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + private BigDecimal businessPrice; - @Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - private Integer price; + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + private BigDecimal count; - @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") - private Integer count; - - @Schema(description = "产品折扣", example = "99") - private Integer discountPercent; + @Schema(description = "总计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + private BigDecimal totalPrice; } 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/CrmContractSaveReqVO.java index 20b20580e..423c0ab93 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/CrmContractSaveReqVO.java @@ -12,6 +12,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -38,22 +39,16 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "商机", function = CrmBusinessParseFunction.NAME) private Long businessId; - @Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED) - @DiffLogField(name = "下单日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @NotNull(message = "下单日期不能为空") - private LocalDateTime orderDate; - @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17144") @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME) @NotNull(message = "负责人不能为空") private Long ownerUserId; - // TODO @芋艿:未来应该支持自动生成; - @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20230101") - @DiffLogField(name = "合同编号") - @NotNull(message = "合同编号不能为空") - private String no; + @Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED) + @DiffLogField(name = "下单日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @NotNull(message = "下单日期不能为空") + private LocalDateTime orderDate; @Schema(description = "开始时间") @DiffLogField(name = "开始时间") @@ -65,21 +60,18 @@ public class CrmContractSaveReqVO { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime endTime; + @Schema(description = "整单折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "55.00") + @DiffLogField(name = "整单折扣") + @NotNull(message = "整单折扣不能为空") + private BigDecimal discountPercent; + @Schema(description = "合同金额", example = "5617") @DiffLogField(name = "合同金额") - private Integer price; + private BigDecimal totalPrice; - @Schema(description = "整单折扣") - @DiffLogField(name = "整单折扣") - private Integer discountPercent; - - @Schema(description = "产品总金额", example = "19510") - @DiffLogField(name = "产品总金额") - private Integer productPrice; - - @Schema(description = "联系人编号", example = "18546") - @DiffLogField(name = "联系人", function = CrmContactParseFunction.NAME) - private Long contactId; + @Schema(description = "客户签约人编号", example = "18546") + @DiffLogField(name = "客户签约人", function = CrmContactParseFunction.NAME) + private Long signContactId; @Schema(description = "公司签约人", example = "14036") @DiffLogField(name = "公司签约人", function = SysAdminUserParseFunction.NAME) @@ -89,27 +81,31 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "备注") private String remark; - @Schema(description = "产品列表") - private List productItems; + private List products; @Schema(description = "产品列表") @Data @NoArgsConstructor @AllArgsConstructor - public static class CrmContractProductItem { + public static class Product { - @Schema(description = "产品编号", example = "20529") + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") @NotNull(message = "产品编号不能为空") - private Long id; + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + @NotNull(message = "产品单价不能为空") + private BigDecimal productPrice; + + @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") + @NotNull(message = "合同价格不能为空") + private BigDecimal businessPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") @NotNull(message = "产品数量不能为空") private Integer count; - @Schema(description = "产品折扣") - private Integer discountPercent; - } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java deleted file mode 100644 index 0b816f37a..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.contract; - -import cn.hutool.core.collection.CollUtil; -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.contract.vo.CrmContractRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.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; -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; - -/** - * 合同 Convert - * - * @author dhb52 - */ -@Mapper -public interface CrmContractConvert { - - CrmContractConvert INSTANCE = Mappers.getMapper(CrmContractConvert.class); - - @Mapping(target = "bizId", source = "reqVO.id") - CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId); - - default List convertList(List contractList, Map userMap, - List customerList, Map contactMap, - Map businessMap, Map contractProductMap, - List productList) { - List respVOList = BeanUtils.toBean(contractList, CrmContractRespVO.class); - // 拼接关联字段 - Map customerMap = convertMap(customerList, CrmCustomerDO::getId); - respVOList.forEach(contract -> { - findAndThen(userMap, contract.getOwnerUserId(), user -> contract.setOwnerUserName(user.getNickname())); - findAndThen(userMap, Long.parseLong(contract.getCreator()), user -> contract.setCreatorName(user.getNickname())); - findAndThen(userMap, contract.getSignUserId(), user -> contract.setSignUserName(user.getNickname())); - findAndThen(customerMap, contract.getCustomerId(), customer -> contract.setCustomerName(customer.getName())); - findAndThen(contactMap, contract.getContactId(), contact -> contract.setContactName(contact.getName())); - findAndThen(businessMap, contract.getBusinessId(), business -> contract.setBusinessName(business.getName())); - }); - if (CollUtil.isNotEmpty(respVOList) && respVOList.size() == 1) { - setContractRespVOProductItems(respVOList.get(0), contractProductMap, productList); - } - return respVOList; - } - - default void setContractRespVOProductItems(CrmContractRespVO respVO, Map contractProductMap, - List productList) { - respVO.setItems(CollectionUtils.convertList(productList, product -> { - CrmContractRespVO.Item productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.Item.class); - findAndThen(contractProductMap, product.getId(), contractProduct -> - productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent())); - return productItemRespVO; - })); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 16990dcc5..2f66fc34d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -50,7 +50,7 @@ public class CrmBusinessProductDO extends BaseDO { */ private BigDecimal productPrice; /** - * 合同价格, 单位:元 + * 商机价格, 单位:元 */ private BigDecimal businessPrice; /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java index 0c01a3394..89f4fd98a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java @@ -10,9 +10,9 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.math.BigDecimal; import java.time.LocalDateTime; -// TODO 芋艿:实体的梳理 /** * CRM 合同 DO * @@ -33,14 +33,14 @@ public class CrmContractDO extends BaseDO { */ @TableId private Long id; - /** - * 合同编号 - */ - private String no; /** * 合同名称 */ private String name; + /** + * 合同编号 + */ + private String no; /** * 客户编号 * @@ -48,17 +48,37 @@ public class CrmContractDO extends BaseDO { */ private Long customerId; /** - * 商机编号 + * 商机编号,非必须 * * 关联 {@link CrmBusinessDO#getId()} */ private Long businessId; + + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + /** * 工作流编号 * * 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; + /** + * 审批状态 + * + * 枚举 {@link CrmAuditStatusEnum} + */ + private Integer auditStatus; + /** * 下单日期 */ @@ -72,50 +92,32 @@ public class CrmContractDO extends BaseDO { */ private LocalDateTime endTime; /** - * 合同金额,单位:分 + * 产品总金额,单位:元 */ - private Integer price; + private BigDecimal totalProductPrice; /** * 整单折扣 */ - private Integer discountPercent; + private BigDecimal discountPercent; /** - * 产品总金额,单位:分 + * 合同总金额,单位:分 */ - private Integer productPrice; + private BigDecimal totalPrice; /** - * 客户签约人 + * 客户签约人,非必须 * * 关联 {@link CrmContactDO#getId()} */ - private Long contactId; + private Long signContactId; /** - * 公司签约人 + * 公司签约人,非必须 * * 关联 AdminUserDO 的 id 字段 */ private Long signUserId; - /** - * 最后跟进时间 - */ - private LocalDateTime contactLastTime; /** * 备注 */ private String remark; - /** - * 负责人的用户编号 - * - * 关联 AdminUserDO 的 id 字段 - */ - private Long ownerUserId; - - /** - * 审批状态 - * - * 枚举 {@link CrmAuditStatusEnum} - */ - private Integer auditStatus; - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java index d0489e490..88ded4391 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java @@ -7,8 +7,10 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.math.BigDecimal; + /** - * 合同产品关联表 DO + * CRM 合同产品关联表 DO * * @author HUIHUI */ @@ -27,12 +29,6 @@ public class CrmContractProductDO extends BaseDO { */ @TableId private Long id; - /** - * 产品编号 - * - * 关联 {@link CrmProductDO#getId()} - */ - private Long productId; /** * 合同编号 * @@ -40,26 +36,27 @@ public class CrmContractProductDO extends BaseDO { */ private Long contractId; /** - * 产品单价 + * 产品编号 + * + * 关联 {@link CrmProductDO#getId()} */ - private Integer price; + private Long productId; /** - * 销售价格, 单位:分 + * 产品单价,单位:元 */ - private Integer salesPrice; + private Integer productPrice; + /** + * 合同价格, 单位:分 + */ + private BigDecimal contractPrice; /** * 数量 */ - private Integer count; + private BigDecimal count; /** - * 折扣 - */ - private Integer discountPercent; - /** - * 总计价格(折扣后价格) - * = {@link #price} - * * {@link #count} - * * ({@link #discountPercent / 100}) + * 总计价格,单位:元 + * + * totalPrice = businessPrice * count */ private Integer totalPrice; 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 690bc5302..d1556be3e 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 @@ -81,7 +81,7 @@ public interface CrmContractMapper extends BaseMapperX { } default Long selectCountByContactId(Long contactId) { - return selectCount(CrmContractDO::getContactId, contactId); + return selectCount(CrmContractDO::getSignContactId, contactId); } default Long selectCountByBusinessId(Long businessId) { 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 a15fe8068..78b64a976 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 @@ -141,7 +141,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 2.2 更新商机关联商品 updateBusinessProduct(updateObj.getId(), businessProducts); - // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessSaveReqVO.class)); LogRecordContext.putVariable("businessName", oldBusiness.getName()); @@ -264,7 +263,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 1.2 校验是否关联合同 validateContractExists(id); - // 删除 + // 删除商机 businessMapper.deleteById(id); // 删除数据权限 permissionService.deletePermission(CrmBizTypeEnum.CRM_BUSINESS.getType(), id); 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 58e00a53b..27d685f1d 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 @@ -5,7 +5,6 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 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.listener.dto.BpmResultListenerRespDTO; @@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; 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.convert.contract.CrmContractConvert; 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.product.CrmProductDO; @@ -31,6 +29,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 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.service.product.CrmProductService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; @@ -95,16 +94,16 @@ public class CrmContractServiceImpl implements CrmContractService { CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); contractMapper.insert(contract); // 1.2 插入合同关联商品 - if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 + if (CollUtil.isNotEmpty(createReqVO.getProducts())) { // 如果有的话 List productList = convertContractProductList(createReqVO, contract.getId()); contractProductMapper.insertBatch(productList); - // 更新合同商品总金额 - contractMapper.updateById(new CrmContractDO().setId(contract.getId()).setProductPrice( - getSumValue(productList, CrmContractProductDO::getTotalPrice, Integer::sum))); + // 更新合同商品总金额 TODO 芋艿 +// contractMapper.updateById(new CrmContractDO().setId(contract.getId()).setTotalProductPrice( +// getSumValue(productList, CrmContractProductDO::getTotalPrice, Integer::sum))); // 如果存在合同关联了商机则更新商机商品关联 if (contract.getBusinessId() != null) { businessService.updateBusinessProduct(new CrmBusinessUpdateProductReqBO().setId(contract.getBusinessId()) - .setItems(BeanUtils.toBean(createReqVO.getProductItems(), CrmBusinessUpdateProductReqBO.Item.class))); + .setItems(BeanUtils.toBean(createReqVO.getProducts(), CrmBusinessUpdateProductReqBO.Item.class))); } } @@ -146,7 +145,7 @@ public class CrmContractServiceImpl implements CrmContractService { } private void updateContractProduct(CrmContractSaveReqVO updateReqVO, Long contractId) { - if (CollUtil.isEmpty(updateReqVO.getProductItems())) { + if (CollUtil.isEmpty(updateReqVO.getProducts())) { return; } List newProductList = convertContractProductList(updateReqVO, contractId); @@ -173,20 +172,22 @@ public class CrmContractServiceImpl implements CrmContractService { private List convertContractProductList(CrmContractSaveReqVO reqVO, Long contractId) { // 校验商品存在 - Set productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId); + Set productIds = convertSet(reqVO.getProducts(), CrmContractSaveReqVO.Product::getProductId); List productList = productService.getProductList(productIds); if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { throw exception(PRODUCT_NOT_EXISTS); } Map productMap = convertMap(productList, CrmProductDO::getId); - return convertList(reqVO.getProductItems(), productItem -> { - CrmProductDO product = productMap.get(productItem.getId()); - return BeanUtils.toBean(product, CrmContractProductDO.class) - .setId(null).setProductId(productItem.getId()).setContractId(contractId) - .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) - // TODO 芋艿:这里临时注释掉 - .setTotalPrice(MoneyUtils.calculator(null, productItem.getCount(), productItem.getDiscountPercent())); - }); + // TODO 芋艿 + return null; +// return convertList(reqVO.getProducts(), productItem -> { +// CrmProductDO product = productMap.get(productItem.getId()); +// return BeanUtils.toBean(product, CrmContractProductDO.class) +// .setId(null).setProductId(productItem.getId()).setContractId(contractId) +// .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) +// // TODO 芋艿:这里临时注释掉 +// .setTotalPrice(MoneyUtils.calculator(null, productItem.getCount(), productItem.getDiscountPercent())); +// }); } /** @@ -245,8 +246,8 @@ public class CrmContractServiceImpl implements CrmContractService { CrmContractDO contract = validateContractExists(reqVO.getId()); // 2.1 数据权限转移 - crmPermissionService.transferPermission( - CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())); + crmPermissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTRACT.getType(), + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 设置负责人 contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); From b0def8b5862dea8c81b1bf0a82832625d5744de9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 23 Feb 2024 00:04:57 +0800 Subject: [PATCH 27/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=90=88=E5=90=8C=E7=9A=84=E6=96=B0=E5=A2=9E=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/business/CrmBusinessController.java | 4 +- .../admin/contact/CrmContactController.java | 3 +- .../admin/contract/CrmContractController.java | 19 ++- .../admin/contract/vo/CrmContractRespVO.java | 6 +- .../contract/vo/CrmContractSaveReqVO.java | 2 +- .../contract/CrmContractProductDO.java | 4 +- .../service/business/CrmBusinessService.java | 16 +-- .../business/CrmBusinessServiceImpl.java | 34 ++--- .../bo/CrmBusinessUpdateProductReqBO.java | 49 ------- .../contract/CrmContractServiceImpl.java | 123 +++++++++--------- 10 files changed, 104 insertions(+), 156 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java 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 7603f3c3b..ec1b35db4 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 @@ -135,7 +135,6 @@ public class CrmBusinessController { return success(BeanUtils.toBean(businessService.getBusinessList(ids, getLoginUserId()), CrmBusinessRespVO.class)); } - // TODO 芋艿:处理下 @GetMapping("/simple-all-list") @Operation(summary = "获得联系人的精简列表") @PreAuthorize("@ss.hasPermission('crm:contact:query')") @@ -144,7 +143,8 @@ public class CrmBusinessController { reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 PageResult pageResult = businessService.getBusinessPage(reqVO, getLoginUserId()); return success(convertList(pageResult.getList(), business -> // 只返回 id、name 字段 - new CrmBusinessRespVO().setId(business.getId()).setName(business.getName()))); + new CrmBusinessRespVO().setId(business.getId()).setName(business.getName()) + .setCustomerId(business.getCustomerId()))); } @GetMapping("/page") 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 4d9385199..6c27fbb01 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 @@ -120,7 +120,8 @@ public class CrmContactController { public CommonResult> getSimpleContactList() { List list = contactService.getContactList(getLoginUserId()); return success(convertList(list, contact -> // 只返回 id、name 字段 - new CrmContactRespVO().setId(contact.getId()).setName(contact.getName()))); + new CrmContactRespVO().setId(contact.getId()).setName(contact.getName()) + .setCustomerId(contact.getCustomerId()))); } @GetMapping("/page") 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 65226866f..147c598d6 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 @@ -16,7 +16,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTrans 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; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; 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.contract.CrmContractService; @@ -108,13 +110,16 @@ public class CrmContractController { if (contract == null) { return null; } -// List productList = null; -// if (contractList.size() == 1) { -// List contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId()); -// contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId); -// productList = productService.getProductList(convertSet(contractProductList, CrmContractProductDO::getProductId)); -// } - return buildContractDetailList(singletonList(contract)).get(0); + CrmContractRespVO contractVO = buildContractDetailList(singletonList(contract)).get(0); + // 拼接产品项 + List businessProducts = contractService.getContractProductListByContractId(contractVO.getId()); + Map productMap = productService.getProductMap( + convertSet(businessProducts, CrmContractProductDO::getProductId)); + contractVO.setProducts(BeanUtils.toBean(businessProducts, CrmContractRespVO.Product.class, businessProductVO -> + MapUtils.findAndThen(productMap, businessProductVO.getProductId(), + product -> businessProductVO.setProductName(product.getName()) + .setProductNo(product.getNo()).setProductUnit(product.getUnit())))); + return contractVO; } @GetMapping("/page") 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/CrmContractRespVO.java index 738cfaa79..f32549e77 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/CrmContractRespVO.java @@ -121,13 +121,13 @@ public class CrmContractRespVO { private LocalDateTime updateTime; @Schema(description = "产品列表") - private List products; + private List products; @Schema(description = "产品列表") @Data @NoArgsConstructor @AllArgsConstructor - public static class Item { + public static class Product { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") private Long id; @@ -145,7 +145,7 @@ public class CrmContractRespVO { private BigDecimal productPrice; @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") - private BigDecimal businessPrice; + private BigDecimal contractPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") private BigDecimal count; 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/CrmContractSaveReqVO.java index 423c0ab93..322127f42 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/CrmContractSaveReqVO.java @@ -100,7 +100,7 @@ public class CrmContractSaveReqVO { @Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00") @NotNull(message = "合同价格不能为空") - private BigDecimal businessPrice; + private BigDecimal contractPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") @NotNull(message = "产品数量不能为空") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java index 88ded4391..ec50e50be 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java @@ -44,7 +44,7 @@ public class CrmContractProductDO extends BaseDO { /** * 产品单价,单位:元 */ - private Integer productPrice; + private BigDecimal productPrice; /** * 合同价格, 单位:分 */ @@ -58,6 +58,6 @@ public class CrmContractProductDO extends BaseDO { * * totalPrice = businessPrice * count */ - private Integer totalPrice; + private BigDecimal totalPrice; } 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 bcb7f0903..63ef761a7 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 @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.enums.business.CrmBusinessEndStatusEnum; -import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; import jakarta.validation.Valid; import java.time.LocalDateTime; @@ -80,13 +79,6 @@ public interface CrmBusinessService { */ void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId); - /** - * 更新商机关联商品 - * - * @param updateProductReqBO 请求 - */ - void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO); - /** * 获得商机 * @@ -95,6 +87,14 @@ public interface CrmBusinessService { */ CrmBusinessDO getBusiness(Long id); + /** + * 校验商机是否有效 + * + * @param id 编号 + * @return 商机 + */ + CrmBusinessDO validateBusiness(Long id); + /** * 获得商机列表 * 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 78b64a976..11b6193fc 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 @@ -19,7 +19,6 @@ import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; @@ -91,10 +90,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 1.1 校验产品项的有效性 List businessProducts = validateBusinessProducts(createReqVO.getProducts()); // 1.2 校验关联字段 - validateBusinessForCreate(createReqVO); + validateRelationDataExists(createReqVO); // 2.1 插入商机 - CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId); + CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class); business.setStatusId(businessStatusService.getBusinessStatusListByTypeId(createReqVO.getStatusTypeId()).get(0).getId()); // 默认状态 calculateTotalPrice(business, businessProducts); businessMapper.insert(business); @@ -105,9 +104,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } // 3. 创建数据权限 - // 设置当前操作的人为负责人 - permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) - .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); + permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(business.getOwnerUserId()) + .setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()).setBizId(business.getId()) + .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 4. 在联系人的详情页,如果直接【新建商机】,则需要关联下 if (createReqVO.getContactId() != null) { @@ -132,7 +131,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 1.2 校验产品项的有效性 List businessProducts = validateBusinessProducts(updateReqVO.getProducts()); // 1.3 校验关联字段 - validateBusinessForCreate(updateReqVO); + validateRelationDataExists(updateReqVO); // 2.1 更新商机 CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); @@ -184,7 +183,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } } - private void validateBusinessForCreate(CrmBusinessSaveReqVO saveReqVO) { + private void validateRelationDataExists(CrmBusinessSaveReqVO saveReqVO) { // 校验商机状态 if (saveReqVO.getStatusTypeId() != null) { businessStatusService.validateBusinessStatusType(saveReqVO.getStatusTypeId()); @@ -207,9 +206,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 1. 校验产品存在 productService.validProductList(convertSet(list, CrmBusinessSaveReqVO.Product::getProductId)); // 2. 转化为 CrmBusinessProductDO 列表 - return convertList(list, o -> BeanUtils.toBean(o, CrmBusinessProductDO.class, item -> { - item.setTotalPrice(MoneyUtils.priceMultiply(item.getBusinessPrice(), item.getCount())); - })); + return convertList(list, o -> BeanUtils.toBean(o, CrmBusinessProductDO.class, + item -> item.setTotalPrice(MoneyUtils.priceMultiply(item.getBusinessPrice(), item.getCount())))); } private void calculateTotalPrice(CrmBusinessDO business, List businessProducts) { @@ -218,7 +216,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice)); } - @Override @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_STATUS_SUB_TYPE, bizNo = "{{#reqVO.id}}", success = CRM_BUSINESS_UPDATE_STATUS_SUCCESS) @@ -312,14 +309,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { LogRecordContext.putVariable("business", business); } - @Override - public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) { - // 更新商机关联商品 TODO yunai -// List productList = buildBusinessProductList( -// BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.Product.class), updateProductReqBO.getId()); -// updateBusinessProduct(productList, updateProductReqBO.getId()); - } - //======================= 查询相关 ======================= @Override @@ -328,6 +317,11 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { return businessMapper.selectById(id); } + @Override + public CrmBusinessDO validateBusiness(Long id) { + return validateBusinessExists(id); + } + @Override public List getBusinessList(Collection ids, Long userId) { if (CollUtil.isEmpty(ids)) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java deleted file mode 100644 index 0c8d7efbf..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business.bo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 更新商机商品 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmBusinessUpdateProductReqBO { - - /** - * 商机编号 - */ - @NotNull(message = "商机编号不能为空") - private Long id; - - // TODO @芋艿:再想想 - @NotEmpty(message = "产品列表不能为空") - private List items; - - @Schema(description = "产品列表") - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class Item { - - @Schema(description = "产品编号", example = "20529") - @NotNull(message = "产品编号不能为空") - private Long id; - - @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") - @NotNull(message = "产品数量不能为空") - private Integer count; - - @Schema(description = "产品折扣") - private Integer discountPercent; - - } - -} 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 27d685f1d..1018cc120 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 @@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 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.listener.dto.BpmResultListenerRespDTO; @@ -16,7 +17,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractProductMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; @@ -24,7 +24,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; -import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; @@ -40,16 +40,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; /** * CRM 合同 Service 实现类 @@ -78,6 +76,8 @@ public class CrmContractServiceImpl implements CrmContractService { private CrmCustomerService customerService; @Resource private CrmBusinessService businessService; + @Resource + private CrmContactService contactService; @Resource private AdminUserApi adminUserApi; @@ -89,30 +89,29 @@ public class CrmContractServiceImpl implements CrmContractService { @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}", success = CRM_CONTRACT_CREATE_SUCCESS) public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) { + // 1.1 校验产品项的有效性 + List contractProducts = validateContractProducts(createReqVO.getProducts()); + // 1.2 校验关联字段 validateRelationDataExists(createReqVO); - // 1.1 插入合同 - CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); + // TODO 芋艿:生成 no + + // 2.1 插入合同 + CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class); + contract.setNo(System.currentTimeMillis() + ""); // TODO + calculateTotalPrice(contract, contractProducts); contractMapper.insert(contract); - // 1.2 插入合同关联商品 - if (CollUtil.isNotEmpty(createReqVO.getProducts())) { // 如果有的话 - List productList = convertContractProductList(createReqVO, contract.getId()); - contractProductMapper.insertBatch(productList); - // 更新合同商品总金额 TODO 芋艿 -// contractMapper.updateById(new CrmContractDO().setId(contract.getId()).setTotalProductPrice( -// getSumValue(productList, CrmContractProductDO::getTotalPrice, Integer::sum))); - // 如果存在合同关联了商机则更新商机商品关联 - if (contract.getBusinessId() != null) { - businessService.updateBusinessProduct(new CrmBusinessUpdateProductReqBO().setId(contract.getBusinessId()) - .setItems(BeanUtils.toBean(createReqVO.getProducts(), CrmBusinessUpdateProductReqBO.Item.class))); - } + // 2.2 插入合同关联商品 + if (CollUtil.isNotEmpty(contractProducts)) { + contractProducts.forEach(item -> item.setContractId(contract.getId())); + contractProductMapper.insertBatch(contractProducts); } - // 2. 创建数据权限 - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) + // 3. 创建数据权限 + crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(contract.getOwnerUserId()) .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 3. 记录操作日志上下文 + // 4. 记录操作日志上下文 LogRecordContext.putVariable("contract", contract); return contract.getId(); } @@ -124,6 +123,7 @@ public class CrmContractServiceImpl implements CrmContractService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContract(CrmContractSaveReqVO updateReqVO) { Assert.notNull(updateReqVO.getId(), "合同编号不能为空"); + updateReqVO.setOwnerUserId(null); // 不允许更新的字段 // 1.1 校验存在 CrmContractDO contract = validateContractExists(updateReqVO.getId()); // 1.2 只有草稿、审批中,可以编辑; @@ -131,65 +131,41 @@ public class CrmContractServiceImpl implements CrmContractService { CrmAuditStatusEnum.PROCESS.getStatus())) { throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); } + // 1.3 校验产品项的有效性 + List contractProducts = validateContractProducts(updateReqVO.getProducts()); + // 1.4 校验关联字段 validateRelationDataExists(updateReqVO); // 2.1 更新合同 CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class); + calculateTotalPrice(updateObj, contractProducts); contractMapper.updateById(updateObj); // 2.2 更新合同关联商品 - updateContractProduct(updateReqVO, updateObj.getId()); + updateContractProduct(updateReqVO.getId(), contractProducts); // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contract, CrmContractSaveReqVO.class)); LogRecordContext.putVariable("contractName", contract.getName()); } - private void updateContractProduct(CrmContractSaveReqVO updateReqVO, Long contractId) { - if (CollUtil.isEmpty(updateReqVO.getProducts())) { - return; - } - List newProductList = convertContractProductList(updateReqVO, contractId); - List oldProductList = contractProductMapper.selectListByContractId(contractId); - List> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> { - boolean match = ObjUtil.equal(oldObj.getProductId(), newObj.getProductId()); - if (match) { - newObj.setId(oldObj.getId()); // 设置一下老的编号更新时需要使用 - } - return match; - }); + private void updateContractProduct(Long id, List newList) { + List oldList = contractProductMapper.selectListByContractId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setContractId(id)); contractProductMapper.insertBatch(diffList.get(0)); } if (CollUtil.isNotEmpty(diffList.get(1))) { contractProductMapper.updateBatch(diffList.get(1)); } if (CollUtil.isNotEmpty(diffList.get(2))) { - contractProductMapper.deleteBatchIds(convertList(diffList.get(2), CrmContractProductDO::getId)); + contractProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmContractProductDO::getId)); } } // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum - private List convertContractProductList(CrmContractSaveReqVO reqVO, Long contractId) { - // 校验商品存在 - Set productIds = convertSet(reqVO.getProducts(), CrmContractSaveReqVO.Product::getProductId); - List productList = productService.getProductList(productIds); - if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { - throw exception(PRODUCT_NOT_EXISTS); - } - Map productMap = convertMap(productList, CrmProductDO::getId); - // TODO 芋艿 - return null; -// return convertList(reqVO.getProducts(), productItem -> { -// CrmProductDO product = productMap.get(productItem.getId()); -// return BeanUtils.toBean(product, CrmContractProductDO.class) -// .setId(null).setProductId(productItem.getId()).setContractId(contractId) -// .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) -// // TODO 芋艿:这里临时注释掉 -// .setTotalPrice(MoneyUtils.calculator(null, productItem.getCount(), productItem.getDiscountPercent())); -// }); - } - /** * 校验关联数据是否存在 * @@ -197,17 +173,38 @@ public class CrmContractServiceImpl implements CrmContractService { */ private void validateRelationDataExists(CrmContractSaveReqVO reqVO) { // 1. 校验客户 - if (reqVO.getCustomerId() != null && customerService.getCustomer(reqVO.getCustomerId()) == null) { - throw exception(CUSTOMER_NOT_EXISTS); + if (reqVO.getCustomerId() != null) { + customerService.validateCustomer(reqVO.getCustomerId()); } // 2. 校验负责人 - if (reqVO.getOwnerUserId() != null && adminUserApi.getUser(reqVO.getOwnerUserId()) == null) { - throw exception(USER_NOT_EXISTS); + if (reqVO.getOwnerUserId() != null) { + adminUserApi.validateUser(reqVO.getOwnerUserId()); } // 3. 如果有关联商机,则需要校验存在 - if (reqVO.getBusinessId() != null && businessService.getBusiness(reqVO.getBusinessId()) == null) { - throw exception(BUSINESS_NOT_EXISTS); + if (reqVO.getBusinessId() != null) { + businessService.validateBusiness(reqVO.getBusinessId()); } + // 4. 校验签约相关字段 + if (reqVO.getSignContactId() != null) { + contactService.validateContact(reqVO.getSignContactId()); + } + if (reqVO.getSignUserId() != null) { + adminUserApi.validateUser(reqVO.getSignUserId()); + } + } + + private List validateContractProducts(List list) { + // 1. 校验产品存在 + productService.validProductList(convertSet(list, CrmContractSaveReqVO.Product::getProductId)); + // 2. 转化为 CrmContractProductDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, CrmContractProductDO.class, + item -> item.setTotalPrice(MoneyUtils.priceMultiply(item.getContractPrice(), item.getCount())))); + } + + private void calculateTotalPrice(CrmContractDO contract, List contractProducts) { + contract.setTotalProductPrice(getSumValue(contractProducts, CrmContractProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(contract.getTotalProductPrice(), contract.getDiscountPercent()); + contract.setTotalPrice(contract.getTotalProductPrice().subtract(discountPrice)); } @Override From d604e76d16ab1a05e5ca0aa33713100ba9027827 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 23 Feb 2024 09:31:41 +0800 Subject: [PATCH 28/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=90=88=E5=90=8C=E7=9A=84=E8=B7=9F=E8=BF=9B=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 3 +- .../crm/service/clue/CrmClueServiceImpl.java | 2 -- .../service/contract/CrmContractService.java | 8 +++-- .../contract/CrmContractServiceImpl.java | 16 +++++++-- .../CrmFollowUpRecordServiceImpl.java | 7 +--- .../followup/bo/CrmUpdateFollowUpReqBO.java | 34 ------------------- 6 files changed, 21 insertions(+), 49 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java 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 1b085b70b..b55594bab 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 @@ -95,7 +95,6 @@ public interface LogRecordConstants { String CRM_BUSINESS_FOLLOW_UP_SUCCESS = "商机跟进【{{#businessName}}】"; String CRM_BUSINESS_UPDATE_STATUS_SUB_TYPE = "更新商机状态"; String CRM_BUSINESS_UPDATE_STATUS_SUCCESS = "更新了商机【{{#businessName}}】的状态从【{{#oldStatusName}}】变更为了【{{#newStatusName}}】"; -// String CRM_BUSINESS_UPDATE_STATUS_SUCCESS = "阿巴阿巴"; // ======================= CRM_CONTRACT 合同 ======================= @@ -110,6 +109,8 @@ public interface LogRecordConstants { String CRM_CONTRACT_TRANSFER_SUCCESS = "将合同【{{#contract.name}}】的负责人从【{getAdminUserById{#contract.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; String CRM_CONTRACT_SUBMIT_SUB_TYPE = "提交合同审批"; String CRM_CONTRACT_SUBMIT_SUCCESS = "提交合同【{{#contractName}}】审批成功"; + String CRM_CONTRACT_FOLLOW_UP_SUB_TYPE = "合同跟进"; + String CRM_CONTRACT_FOLLOW_UP_SUCCESS = "合同跟进【{{#contractName}}】"; // ======================= CRM_PRODUCT 产品 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 7251eee26..70ebeb44d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -19,7 +19,6 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.CrmFollowUpRecordService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; @@ -133,7 +132,6 @@ public class CrmClueServiceImpl implements CrmClueService { .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent)); // 3. 记录操作日志上下文 - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); LogRecordContext.putVariable("clueName", oldClue.getName()); } 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 300ca86a2..e9f4e6f59 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 @@ -8,9 +8,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTrans 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; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -55,9 +55,11 @@ public interface CrmContractService { /** * 更新合同相关的更进信息 * - * @param contractUpdateFollowUpReqBO 信息 + * @param id 合同编号 + * @param contactNextTime 下次联系时间 + * @param contactLastContent 最后联系内容 */ - void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO); + void updateContractFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); /** * 发起合同审批流程 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 1018cc120..d89b90351 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 @@ -26,7 +26,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm 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.customer.CrmCustomerService; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; @@ -41,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -253,8 +253,18 @@ public class CrmContractServiceImpl implements CrmContractService { } @Override - public void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO) { - contractMapper.updateById(BeanUtils.toBean(contractUpdateFollowUpReqBO, CrmContractDO.class).setId(contractUpdateFollowUpReqBO.getBizId())); + @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}", + success = CRM_CONTRACT_FOLLOW_UP_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + public void updateContractFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { + // 1. 校验存在 + CrmContractDO contract = validateContractExists(id); + + // 2. 更新联系人的跟进信息 + contractMapper.updateById(new CrmContractDO().setId(id).setContactLastTime(LocalDateTime.now())); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("contractName", contract.getName()); } @Override 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 1f39e4684..ab9c5df5b 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 @@ -17,14 +17,12 @@ import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -71,9 +69,6 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { crmFollowUpRecordMapper.insert(record); // 2. 更新 bizId 对应的记录 - CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(record.getBizId()) - .setContactLastTime(LocalDateTime.now()) - .setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent()); if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息 businessService.updateBusinessFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } @@ -84,7 +79,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { contactService.updateContactFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); } if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), record.getBizType())) { // 更新合同跟进信息 - contractService.updateContractFollowUp(updateFollowUpReqBO); + 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()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java deleted file mode 100644 index 57f1849eb..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.followup.bo; - -import com.mzt.logapi.starter.annotation.DiffLogField; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 跟进信息 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmUpdateFollowUpReqBO { - - @Schema(description = "数据编号", example = "3167") - @NotNull(message = "数据编号不能为空") - private Long bizId; - - @Schema(description = "最后跟进时间") - @DiffLogField(name = "最后跟进时间") - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @DiffLogField(name = "下次联系时间") - private LocalDateTime contactNextTime; - - @Schema(description = "最后更进内容") - @DiffLogField(name = "最后更进内容") - private String contactLastContent; - -} From b3cfad9396b55a730718957d16f061cf1260ed83 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 23 Feb 2024 10:42:36 +0800 Subject: [PATCH 29/54] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=E5=9B=9E?= =?UTF-8?q?=E6=AC=BE=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 3 +- .../CrmReceivablePlanController.java | 12 +-- .../vo/plan/CrmReceivablePlanBaseVO.java | 54 ------------ .../vo/plan/CrmReceivablePlanCreateReqVO.java | 12 --- .../vo/plan/CrmReceivablePlanRespVO.java | 44 ++++++++-- .../vo/plan/CrmReceivablePlanSaveReqVO.java | 55 ++++++++++++ .../vo/plan/CrmReceivablePlanUpdateReqVO.java | 18 ---- .../receivable/CrmReceivablePlanConvert.java | 8 -- .../receivable/CrmReceivablePlanDO.java | 35 ++++---- .../receivable/CrmReceivablePlanMapper.java | 7 -- .../receivable/CrmReceivablePlanService.java | 8 +- .../CrmReceivablePlanServiceImpl.java | 86 ++++++++++--------- .../receivable/CrmReceivableService.java | 8 ++ .../receivable/CrmReceivableServiceImpl.java | 5 ++ 14 files changed, 180 insertions(+), 175 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanBaseVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanCreateReqVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanUpdateReqVO.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index fa1cec68a..28c3404b1 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -33,8 +33,9 @@ public interface ErrorCodeConstants { // ========== 回款 1-020-004-000 ========== ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); - // ========== 合同管理 1-020-005-000 ========== + // ========== 回款计划 1-020-005-000 ========== ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "回款计划不存在"); + ErrorCode RECEIVABLE_PLAN_UPDATE_FAIL = new ErrorCode(1_020_006_000, "更想回款计划失败,原因:{}"); // ========== 客户管理 1_020_006_000 ========== ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java index 6144ae6d3..2500c6f15 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java @@ -5,12 +5,12 @@ import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO; import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -67,14 +67,14 @@ public class CrmReceivablePlanController { @PostMapping("/create") @Operation(summary = "创建回款计划") @PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')") - public CommonResult createReceivablePlan(@Valid @RequestBody CrmReceivablePlanCreateReqVO createReqVO) { - return success(receivablePlanService.createReceivablePlan(createReqVO, getLoginUserId())); + public CommonResult createReceivablePlan(@Valid @RequestBody CrmReceivablePlanSaveReqVO createReqVO) { + return success(receivablePlanService.createReceivablePlan(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新回款计划") @PreAuthorize("@ss.hasPermission('crm:receivable-plan:update')") - public CommonResult updateReceivablePlan(@Valid @RequestBody CrmReceivablePlanUpdateReqVO updateReqVO) { + public CommonResult updateReceivablePlan(@Valid @RequestBody CrmReceivablePlanSaveReqVO updateReqVO) { receivablePlanService.updateReceivablePlan(updateReqVO); return success(true); } @@ -94,7 +94,7 @@ public class CrmReceivablePlanController { @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") public CommonResult getReceivablePlan(@RequestParam("id") Long id) { CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(id); - return success(CrmReceivablePlanConvert.INSTANCE.convert(receivablePlan)); + return success(BeanUtils.toBean(receivablePlan, CrmReceivablePlanRespVO.class)); } @GetMapping("/page") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanBaseVO.java deleted file mode 100644 index 70272b8e8..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanBaseVO.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** - * 回款计划 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class CrmReceivablePlanBaseVO { - - @Schema(description = "期数", example = "1") - private Integer period; - - @Schema(description = "回款计划编号", example = "19852") - private Long receivableId; - - @Schema(description = "计划回款金额", example = "29675") - private Integer price; - - @Schema(description = "计划回款日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime returnTime; - - @Schema(description = "提前几天提醒") - private Integer remindDays; - - @Schema(description = "提醒日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime remindTime; - - @Schema(description = "客户名称", example = "18026") - private Long customerId; - - @Schema(description = "合同编号", example = "3473") - private Long contractId; - - // TODO @liuhongfeng:负责人编号 - @Schema(description = "负责人编号", example = "17828") - private Long ownerUserId; - - @Schema(description = "显示顺序") - private Integer sort; - - @Schema(description = "备注", example = "备注") - private String remark; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanCreateReqVO.java deleted file mode 100644 index 193a44bf4..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanCreateReqVO.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; - -import lombok.*; -import io.swagger.v3.oas.annotations.media.Schema; - -@Schema(description = "管理后台 - CRM 回款计划创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmReceivablePlanCreateReqVO extends CrmReceivablePlanBaseVO { - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java index d5e9de187..c710333f2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java @@ -1,18 +1,50 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; +import lombok.Data; + import java.time.LocalDateTime; @Schema(description = "管理后台 - CRM 回款计划 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmReceivablePlanRespVO extends CrmReceivablePlanBaseVO { +public class CrmReceivablePlanRespVO { @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25153") private Long id; + @Schema(description = "期数", example = "1") + private Integer period; + + @Schema(description = "回款计划编号", example = "19852") + private Long receivableId; + + @Schema(description = "计划回款金额", example = "29675") + private Integer price; + + @Schema(description = "计划回款日期") + private LocalDateTime returnTime; + + @Schema(description = "提前几天提醒") + private Integer remindDays; + + @Schema(description = "提醒日期") + private LocalDateTime remindTime; + + @Schema(description = "客户名称", example = "18026") + private Long customerId; + + @Schema(description = "合同编号", example = "3473") + private Long contractId; + + @Schema(description = "负责人编号", example = "17828") + private Long ownerUserId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "备注", example = "备注") + private String remark; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; @@ -34,7 +66,7 @@ public class CrmReceivablePlanRespVO extends CrmReceivablePlanBaseVO { @Schema(description = "完成状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Boolean finishStatus; - @Schema(description = "回款方式", example = "1") // 来自 Receivable 的 returnType 字段 - private Integer returnType; + @Schema(description = "回款方式", example = "1") + private Integer returnType; // 来自 Receivable 的 returnType 字段 } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java new file mode 100644 index 000000000..235daf328 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 回款计划新增/修改 Request VO") +@Data +public class CrmReceivablePlanSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long id; + + @Schema(description = "期数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "期数不能为空") + private Integer period; + + @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") + @NotNull(message = "计划回款金额不能为空") + private BigDecimal price; + + @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") + @NotNull(message = "计划回款日期不能为空") + private LocalDateTime returnTime; + + @Schema(description = "提前几天提醒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "提前几天提醒不能为空") + private Integer remindDays; + + @Schema(description = "提醒日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") + @NotNull(message = "提醒日期不能为空") + private LocalDateTime remindTime; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "客户编号不能为空") + private Long customerId; + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "合同编号不能为空") + private Long contractId; + + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "负责人编号不能为空") + private Long ownerUserId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanUpdateReqVO.java deleted file mode 100644 index 2e83a1cbb..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -import jakarta.validation.constraints.*; - -@Schema(description = "管理后台 - CRM 回款计划更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmReceivablePlanUpdateReqVO extends CrmReceivablePlanBaseVO { - - @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25153") - @NotNull(message = "ID不能为空") - private Long id; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java index 9b6bb3e82..bdd422e00 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java @@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.crm.convert.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; @@ -29,12 +27,6 @@ public interface CrmReceivablePlanConvert { CrmReceivablePlanConvert INSTANCE = Mappers.getMapper(CrmReceivablePlanConvert.class); - CrmReceivablePlanDO convert(CrmReceivablePlanCreateReqVO bean); - - CrmReceivablePlanDO convert(CrmReceivablePlanUpdateReqVO bean); - - CrmReceivablePlanRespVO convert(CrmReceivablePlanDO bean); - default PageResult convertPage(PageResult pageResult, Map userMap, List customerList, List contractList, List receivableList) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java index 78658e609..80a04ece7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java @@ -1,11 +1,15 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.receivable; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.math.BigDecimal; import java.time.LocalDateTime; /** @@ -24,7 +28,7 @@ import java.time.LocalDateTime; public class CrmReceivablePlanDO extends BaseDO { /** - * ID + * 编号 */ @TableId private Long id; @@ -33,19 +37,13 @@ public class CrmReceivablePlanDO extends BaseDO { */ private Integer period; /** - * 回款ID - * - * TODO @liuhongfeng:少关联实体; + * 回款编号,关联 {@link CrmReceivableDO#getId()} */ private Long receivableId; /** - * 完成状态 + * 计划回款金额,单位:元 */ - private Boolean finishStatus; - /** - * 计划回款金额,单位:分 - */ - private Integer price; + private BigDecimal price; /** * 计划回款日期 */ @@ -59,21 +57,15 @@ public class CrmReceivablePlanDO extends BaseDO { */ private LocalDateTime remindTime; /** - * 客户 ID - * - * TODO @liuhongfeng:少关联实体; + * 客户编号,关联 {@link CrmCustomerDO#getId()} */ private Long customerId; /** - * 合同 ID - * - * TODO @liuhongfeng:少关联实体; + * 合同编号,关联 {@link CrmContractDO#getId()} */ private Long contractId; /** - * 负责人 ID - * - * TODO @liuhongfeng:少关联实体; + * 负责人编号,关联 {@link AdminUserRespDTO#getId()} */ private Long ownerUserId; /** @@ -85,4 +77,9 @@ public class CrmReceivablePlanDO extends BaseDO { */ private String remark; + /** + * 完成状态 + */ + private Boolean finishStatus; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index 119af7b37..9862048f5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.time.LocalDateTime; @@ -25,12 +24,6 @@ import java.util.List; @Mapper public interface CrmReceivablePlanMapper extends BaseMapperX { - default int updateOwnerUserIdById(Long id, Long ownerUserId) { - return update(new LambdaUpdateWrapper() - .eq(CrmReceivablePlanDO::getId, id) - .set(CrmReceivablePlanDO::getOwnerUserId, ownerUserId)); - } - default PageResult selectPageByCustomerId(CrmReceivablePlanPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eq(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java index ebc80f25c..a67c91c48 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.crm.service.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; import jakarta.validation.Valid; @@ -24,14 +23,14 @@ public interface CrmReceivablePlanService { * @param createReqVO 创建信息 * @return 编号 */ - Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO, Long userId); + Long createReceivablePlan(@Valid CrmReceivablePlanSaveReqVO createReqVO); /** * 更新回款计划 * * @param updateReqVO 更新信息 */ - void updateReceivablePlan(@Valid CrmReceivablePlanUpdateReqVO updateReqVO); + void updateReceivablePlan(@Valid CrmReceivablePlanSaveReqVO updateReqVO); /** * 删除回款计划 @@ -84,4 +83,5 @@ public interface CrmReceivablePlanService { * @return 提醒数量 */ Long getRemindReceivablePlanCount(Long userId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index d74219a6e..3ac385998 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -5,10 +5,8 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; -import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; @@ -20,22 +18,24 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; +import org.hibernate.validator.internal.util.stereotypes.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.List; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; -// TODO @liuhongfeng:参考 CrmReceivableServiceImpl 写的 todo 哈; - /** * 回款计划 Service 实现类 * @@ -48,73 +48,79 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { @Resource private CrmReceivablePlanMapper receivablePlanMapper; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private CrmReceivableService receivableService; @Resource private CrmContractService contractService; @Resource private CrmCustomerService customerService; @Resource private CrmPermissionService permissionService; + @Resource + private AdminUserApi adminUserApi; @Override + @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_CREATE_SUB_TYPE, bizNo = "{{#receivablePlan.id}}", success = CRM_RECEIVABLE_PLAN_CREATE_SUCCESS) - public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) { - // TODO @liuhongfeng:第几期的计算;基于是 contractId + contractDO 的第几个还款 - // TODO @liuhongfeng contractId:校验合同是否存在 - // 插入 - CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO); - receivablePlan.setFinishStatus(false); - - checkReceivablePlan(receivablePlan); + public Long createReceivablePlan(CrmReceivablePlanSaveReqVO createReqVO) { + // 1.1 校验关联数据是否存在 + checkReceivablePlan(createReqVO); + // 1.2 查验关联合同回款数量 + Long count = receivableService.getReceivableCountByContractId(createReqVO.getContractId()); + int period = (int) (count + 1); + createReqVO.setPeriod(createReqVO.getPeriod() != period ? period : createReqVO.getPeriod()); // 如果期数不对则纠正 + // 2.1 插入 + CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class).setId(null).setFinishStatus(false); receivablePlanMapper.insert(receivablePlan); - // 创建数据权限 - permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) + // 2.2 创建数据权限 + permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(createReqVO.getOwnerUserId()) .setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()).setBizId(receivablePlan.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 4. 记录操作日志上下文 + // 3. 记录操作日志上下文 LogRecordContext.putVariable("receivablePlan", receivablePlan); return receivablePlan.getId(); } - private void checkReceivablePlan(CrmReceivablePlanDO receivablePlan) { - - if (ObjectUtil.isNull(receivablePlan.getContractId())) { - throw exception(CONTRACT_NOT_EXISTS); - } - - CrmContractDO contract = contractService.getContract(receivablePlan.getContractId()); - if (ObjectUtil.isNull(contract)) { - throw exception(CONTRACT_NOT_EXISTS); - } - - CrmCustomerDO customer = customerService.getCustomer(receivablePlan.getCustomerId()); - if (ObjectUtil.isNull(customer)) { - throw exception(CUSTOMER_NOT_EXISTS); - } - - } - @Override + @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CRM_RECEIVABLE_PLAN_UPDATE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) - public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) { - // TODO @liuhongfeng:如果已经有对应的还款,则不允许编辑; - // 校验存在 + public void updateReceivablePlan(CrmReceivablePlanSaveReqVO updateReqVO) { + // 1. 校验存在 + checkReceivablePlan(updateReqVO); CrmReceivablePlanDO oldReceivablePlan = validateReceivablePlanExists(updateReqVO.getId()); + if (Objects.nonNull(oldReceivablePlan.getReceivableId())) { // 如果已经有对应的还款,则不允许编辑; + throw exception(RECEIVABLE_PLAN_UPDATE_FAIL, "已经有对应的还款"); + } - // 更新 - CrmReceivablePlanDO updateObj = CrmReceivablePlanConvert.INSTANCE.convert(updateReqVO); + // 2. 更新 + CrmReceivablePlanDO updateObj = BeanUtils.toBean(updateReqVO, CrmReceivablePlanDO.class); receivablePlanMapper.updateById(updateObj); // 3. 记录操作日志上下文 - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivablePlan, CrmReceivablePlanUpdateReqVO.class)); + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivablePlan, CrmReceivablePlanSaveReqVO.class)); LogRecordContext.putVariable("receivablePlan", oldReceivablePlan); } + private void checkReceivablePlan(CrmReceivablePlanSaveReqVO reqVO) { + adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 + CrmContractDO contract = contractService.getContract(reqVO.getContractId()); + if (ObjectUtil.isNull(contract)) { // 合同不存在 + throw exception(CONTRACT_NOT_EXISTS); + } + CrmCustomerDO customer = customerService.getCustomer(reqVO.getCustomerId()); + if (ObjectUtil.isNull(customer)) { // 客户不存在 + throw exception(CUSTOMER_NOT_EXISTS); + } + } + @Override + @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_RECEIVABLE_PLAN_TYPE, subType = CRM_RECEIVABLE_PLAN_DELETE_SUB_TYPE, bizNo = "{{#id}}", success = CRM_RECEIVABLE_PLAN_DELETE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java index f92db6a4d..808b2cc2e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java @@ -86,4 +86,12 @@ public interface CrmReceivableService { */ Long getCheckReceivablesCount(Long userId); + /** + * 根据合同编号,获取合同关联的回款数量 + * + * @param contractId 合同编号 + * @return 数量 + */ + Long getReceivableCountByContractId(Long contractId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index d2f7db036..93ad4c97e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -187,4 +187,9 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { return receivableMapper.selectCheckReceivablesCount(userId); } + @Override + public Long getReceivableCountByContractId(Long contractId) { + return receivableMapper.selectCount(CrmReceivableDO::getContractId, contractId); + } + } From c6b133d9192ffbc270f4be1954c36036602a9714 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 23 Feb 2024 12:14:56 +0800 Subject: [PATCH 30/54] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=E5=9B=9E?= =?UTF-8?q?=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 4 + .../module/crm/enums/LogRecordConstants.java | 2 + .../enums/receivable/CrmReturnTypeEnum.java | 51 +++++++ .../receivable/CrmReceivableController.java | 20 ++- .../vo/plan/CrmReceivablePlanRespVO.java | 27 ++-- .../vo/receivable/CrmReceivableBaseVO.java | 61 -------- .../receivable/CrmReceivableCreateReqVO.java | 12 -- .../vo/receivable/CrmReceivableRespVO.java | 40 +++++- .../vo/receivable/CrmReceivableSaveReqVO.java | 55 +++++++ .../receivable/CrmReceivableUpdateReqVO.java | 18 --- .../receivable/CrmReceivableConvert.java | 8 -- .../receivable/CrmReceivableDO.java | 58 ++++---- .../contract/CrmContractServiceImpl.java | 28 +--- .../receivable/CrmReceivablePlanService.java | 8 ++ .../CrmReceivablePlanServiceImpl.java | 14 +- .../receivable/CrmReceivableService.java | 24 +++- .../receivable/CrmReceivableServiceImpl.java | 136 ++++++++++++------ .../listener/CrmReceivableResultListener.java | 33 +++++ .../module/crm/util/CrmAuditStatusUtils.java | 44 ++++++ 19 files changed, 410 insertions(+), 233 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReturnTypeEnum.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableBaseVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableCreateReqVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableUpdateReqVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 28c3404b1..cc12f849b 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -32,6 +32,10 @@ public interface ErrorCodeConstants { // ========== 回款 1-020-004-000 ========== ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); + ErrorCode RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_004_001, "更新回款失败,原因:禁止编辑"); + ErrorCode RECEIVABLE_DELETE_FAIL = new ErrorCode(1_020_004_002, "删除回款失败,原因: 被回款计划所使用,不允许删除"); + ErrorCode RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_004_003, "回款提交审核失败,原因:回款没处在未提交状态"); + // ========== 回款计划 1-020-005-000 ========== ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "回款计划不存在"); 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 1b085b70b..5a7809c02 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 @@ -140,6 +140,8 @@ public interface LogRecordConstants { String CRM_RECEIVABLE_UPDATE_SUCCESS = "更新了合同【{getContractById{#receivable.contractId}}】的第【{{#receivable.period}}】期回款: {_DIFF{#updateReqVO}}"; String CRM_RECEIVABLE_DELETE_SUB_TYPE = "删除回款"; String CRM_RECEIVABLE_DELETE_SUCCESS = "删除了合同【{getContractById{#receivable.contractId}}】的第【{{#receivable.period}}】期回款"; + String CRM_RECEIVABLE_SUBMIT_SUB_TYPE = "提交回款审批"; + String CRM_RECEIVABLE_SUBMIT_SUCCESS = "提交编号为【{{#receivableNo}}】的回款审批成功"; // ======================= CRM_RECEIVABLE_PLAN 回款计划 ======================= diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReturnTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReturnTypeEnum.java new file mode 100644 index 000000000..8aacadce3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReturnTypeEnum.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.crm.enums.receivable; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * CRM 回款方式枚举 + * + * @author HUIHUI + */ +@Getter +@AllArgsConstructor +public enum CrmReturnTypeEnum implements IntArrayValuable { + + // 支票 + CHECK(1, "支票"), + // 现金 + CASH(2, "现金"), + // 邮政汇款 + POSTAL_REMITTANCE(3, "邮政汇款"), + // 电汇 + TELEGRAPHIC_TRANSFER(4, "电汇"), + // 网上转账 + ONLINE_TRANSFER(5, "网上转账"), + // 支付宝 + ALIPAY(6, "支付宝"), + // 微信支付 + WECHAT_PAY(7, "微信支付"), + // 其他 + OTHER(8, "其它"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmReturnTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java index f29bc5139..5bbaefb5b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java @@ -5,12 +5,12 @@ import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -61,14 +61,14 @@ public class CrmReceivableController { @PostMapping("/create") @Operation(summary = "创建回款") @PreAuthorize("@ss.hasPermission('crm:receivable:create')") - public CommonResult createReceivable(@Valid @RequestBody CrmReceivableCreateReqVO createReqVO) { - return success(receivableService.createReceivable(createReqVO, getLoginUserId())); + public CommonResult createReceivable(@Valid @RequestBody CrmReceivableSaveReqVO createReqVO) { + return success(receivableService.createReceivable(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新回款") @PreAuthorize("@ss.hasPermission('crm:receivable:update')") - public CommonResult updateReceivable(@Valid @RequestBody CrmReceivableUpdateReqVO updateReqVO) { + public CommonResult updateReceivable(@Valid @RequestBody CrmReceivableSaveReqVO updateReqVO) { receivableService.updateReceivable(updateReqVO); return success(true); } @@ -88,7 +88,7 @@ public class CrmReceivableController { @PreAuthorize("@ss.hasPermission('crm:receivable:query')") public CommonResult getReceivable(@RequestParam("id") Long id) { CrmReceivableDO receivable = receivableService.getReceivable(id); - return success(CrmReceivableConvert.INSTANCE.convert(receivable)); + return success(BeanUtils.toBean(receivable, CrmReceivableRespVO.class)); } @GetMapping("/page") @@ -152,4 +152,12 @@ public class CrmReceivableController { return success(receivableService.getCheckReceivablesCount(getLoginUserId())); } + @PutMapping("/submit") + @Operation(summary = "提交回款审批") + @PreAuthorize("@ss.hasPermission('crm:receivable:submit')") + public CommonResult submitContract(@RequestParam("id") Long id) { + receivableService.submitReceivable(id, getLoginUserId()); + return success(true); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java index c710333f2..9e6d1a03f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java @@ -3,40 +3,41 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.math.BigDecimal; import java.time.LocalDateTime; @Schema(description = "管理后台 - CRM 回款计划 Response VO") @Data public class CrmReceivablePlanRespVO { - @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25153") + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Long id; - @Schema(description = "期数", example = "1") - private Integer period; - - @Schema(description = "回款计划编号", example = "19852") + @Schema(description = "回款编号", example = "19852") private Long receivableId; - @Schema(description = "计划回款金额", example = "29675") - private Integer price; + @Schema(description = "期数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer period; - @Schema(description = "计划回款日期") + @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") + private BigDecimal price; + + @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") private LocalDateTime returnTime; - @Schema(description = "提前几天提醒") + @Schema(description = "提前几天提醒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer remindDays; - @Schema(description = "提醒日期") + @Schema(description = "提醒日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") private LocalDateTime remindTime; - @Schema(description = "客户名称", example = "18026") + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Long customerId; - @Schema(description = "合同编号", example = "3473") + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Long contractId; - @Schema(description = "负责人编号", example = "17828") + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Long ownerUserId; @Schema(description = "显示顺序") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableBaseVO.java deleted file mode 100644 index c32bc9ad5..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableBaseVO.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** - * 回款 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class CrmReceivableBaseVO { - - @Schema(description = "回款编号",requiredMode = Schema.RequiredMode.REQUIRED, example = "31177") - private String no; - - // TODO @liuhongfeng:回款计划编号 - @Schema(description = "回款计划", example = "31177") - private Long planId; - - // TODO @liuhongfeng:客户编号 - @Schema(description = "客户名称", example = "4963") - private Long customerId; - - // TODO @liuhongfeng:客户编号 - @Schema(description = "合同名称", example = "30305") - private Long contractId; - - // TODO @liuhongfeng:这个字段,应该不是前端传递的噢,而是后端自己生成的 - @Schema(description = "审批状态", example = "1") - @InEnum(CrmAuditStatusEnum.class) - private Integer checkStatus; - - @Schema(description = "回款日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime returnTime; - - @Schema(description = "回款方式", example = "2") - private Integer returnType; - - @Schema(description = "回款金额,单位:分", example = "31859") - private Integer price; - - // TODO @liuhongfeng:负责人编号 - @Schema(description = "负责人", example = "22202") - private Long ownerUserId; - - @Schema(description = "显示顺序") - private Integer sort; - - @Schema(description = "备注", example = "备注") - private String remark; - - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableCreateReqVO.java deleted file mode 100644 index 4471b780a..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableCreateReqVO.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; - -import lombok.*; -import io.swagger.v3.oas.annotations.media.Schema; - -@Schema(description = "管理后台 - CRM 回款创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmReceivableCreateReqVO extends CrmReceivableBaseVO { - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java index 7c536bd51..2bb721b46 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java @@ -1,19 +1,49 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; +import lombok.Data; + +import java.math.BigDecimal; import java.time.LocalDateTime; // TODO 芋艿:导出的 VO,可以考虑使用 @Excel 注解,实现导出功能 @Schema(description = "管理后台 - CRM 回款 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmReceivableRespVO extends CrmReceivableBaseVO { +public class CrmReceivableRespVO { - @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25787") + @Schema(description = "编号", example = "25787") private Long id; + @Schema(description = "回款编号", example = "31177") + private String no; + + @Schema(description = "回款计划编号", example = "1024") + private Long planId; + + @Schema(description = "回款方式", example = "2") + private Integer returnType; + + @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") + private BigDecimal price; + + @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") + private LocalDateTime returnTime; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long customerId; + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long contractId; + + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long ownerUserId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "备注", example = "备注") + private String remark; + @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/receivable/vo/receivable/CrmReceivableSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java new file mode 100644 index 000000000..5340b4319 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.receivable.CrmReturnTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 回款新增/修改 Request VO") +@Data +public class CrmReceivableSaveReqVO { + + @Schema(description = "编号", example = "25787") + private Long id; + + @Schema(description = "回款编号", example = "31177") + private String no; + + @Schema(description = "回款计划编号", example = "1024") + private Long planId; // 不是通过回款计划创建的回款没有回款计划编号 + + @Schema(description = "回款方式", example = "2") + @InEnum(CrmReturnTypeEnum.class) + private Integer returnType; + + @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") + @NotNull(message = "回款金额不能为空") + private BigDecimal price; + + @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") + @NotNull(message = "计划回款日期不能为空") + private LocalDateTime returnTime; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "客户编号不能为空") + private Long customerId; + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "合同编号不能为空") + private Long contractId; + + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "负责人编号不能为空") + private Long ownerUserId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableUpdateReqVO.java deleted file mode 100644 index 0f63978c8..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -import jakarta.validation.constraints.*; - -@Schema(description = "管理后台 - CRM 回款更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmReceivableUpdateReqVO extends CrmReceivableBaseVO { - - @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25787") - @NotNull(message = "ID不能为空") - private Long id; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java index 3b0c23aae..d53d14fda 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java @@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.crm.convert.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; @@ -28,12 +26,6 @@ public interface CrmReceivableConvert { CrmReceivableConvert INSTANCE = Mappers.getMapper(CrmReceivableConvert.class); - CrmReceivableDO convert(CrmReceivableCreateReqVO bean); - - CrmReceivableDO convert(CrmReceivableUpdateReqVO bean); - - CrmReceivableRespVO convert(CrmReceivableDO bean); - default PageResult convertPage(PageResult pageResult, Map userMap, List customerList, List contractList) { PageResult voPageResult = BeanUtils.toBean(pageResult, CrmReceivableRespVO.class); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java index 842fc96b4..6c1610935 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java @@ -2,11 +2,16 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.receivable; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; +import cn.iocoder.yudao.module.crm.enums.receivable.CrmReturnTypeEnum; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.math.BigDecimal; import java.time.LocalDateTime; /** @@ -33,64 +38,55 @@ public class CrmReceivableDO extends BaseDO { * 回款编号 */ private String no; - // TODO @liuhongfeng:“对应实体”,参考别的模块,关联 {@link TableField.MetaInfo#getJdbcType()} /** - * 回款计划 - * - * TODO @liuhongfeng:这个字段什么时候更新,也可以写下 - * - * 对应实体 {@link CrmReceivablePlanDO} + * 回款计划编号,关联 {@link CrmReceivablePlanDO#getId()} */ private Long planId; /** - * 客户 ID - * - * 对应实体 {@link cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO} + * 客户编号,关联 {@link CrmCustomerDO#getId()} */ private Long customerId; /** - * 合同 ID - * - * 对应实体 {@link CrmContractDO} + * 合同编号,关联 {@link CrmContractDO#getId()} */ private Long contractId; /** - * 工作流编号 - * - * TODO @liuhongfeng:这个字段,后续要写下关联的实体哈 + * 负责人编号,关联 {@link AdminUserRespDTO#getId()} */ - private Long processInstanceId; + private Long ownerUserId; + /** * 回款日期 */ private LocalDateTime returnTime; - // TODO @liuhongfeng:少个枚举 /** - * 回款方式 + * 回款方式,关联枚举{@link CrmReturnTypeEnum} */ private Integer returnType; /** - * 回款金额 + * 计划回款金额,单位:元 */ - private Integer price; - // TODO @liuhongfeng:少关联实体; - /** - * 负责人 - */ - private Long ownerUserId; + private BigDecimal price; /** * 显示顺序 */ private Integer sort; - /** - * 审核状态 - * - * 枚举 {@link cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum} - */ - private Integer auditStatus; /** * 备注 */ private String remark; + /** + * 工作流编号 + * + * 关联 ProcessInstance 的 id 属性 + */ + private String processInstanceId; + /** + * 审批状态 + * + * 枚举 {@link CrmAuditStatusEnum} + */ + private Integer auditStatus; + } 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 58e00a53b..211cec690 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 @@ -11,7 +11,6 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; 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; @@ -50,6 +49,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; +import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertAuditStatus; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; /** @@ -284,36 +284,12 @@ public class CrmContractServiceImpl implements CrmContractService { @Override public void updateContractAuditStatus(BpmResultListenerRespDTO event) { - // 判断下状态是否符合预期 - if (!isEndResult(event.getResult())) { - return; - } - // 状态转换 - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { - event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { - event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { - event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); - } + convertAuditStatus(event); // 更新合同状态 contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())) .setAuditStatus(event.getResult())); } - /** - * 判断该结果是否处于 End 最终结果 - * - * @param result 结果 - * @return 是否 - */ - public static boolean isEndResult(Integer result) { - return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), - BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); - } - //======================= 查询相关 ======================= @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java index a67c91c48..7f5854b44 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java @@ -32,6 +32,14 @@ public interface CrmReceivablePlanService { */ void updateReceivablePlan(@Valid CrmReceivablePlanSaveReqVO updateReqVO); + /** + * 更新回款计划关联的回款编号 + * + * @param id 编号 + * @param receivableId 回款编号 + */ + void updateReceivableId(Long id, Long receivableId); + /** * 删除回款计划 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index 3ac385998..db8ea9e0c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -66,7 +66,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { success = CRM_RECEIVABLE_PLAN_CREATE_SUCCESS) public Long createReceivablePlan(CrmReceivablePlanSaveReqVO createReqVO) { // 1.1 校验关联数据是否存在 - checkReceivablePlan(createReqVO); + validateRelationDataExists(createReqVO); // 1.2 查验关联合同回款数量 Long count = receivableService.getReceivableCountByContractId(createReqVO.getContractId()); int period = (int) (count + 1); @@ -92,7 +92,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateReceivablePlan(CrmReceivablePlanSaveReqVO updateReqVO) { // 1. 校验存在 - checkReceivablePlan(updateReqVO); + validateRelationDataExists(updateReqVO); CrmReceivablePlanDO oldReceivablePlan = validateReceivablePlanExists(updateReqVO.getId()); if (Objects.nonNull(oldReceivablePlan.getReceivableId())) { // 如果已经有对应的还款,则不允许编辑; throw exception(RECEIVABLE_PLAN_UPDATE_FAIL, "已经有对应的还款"); @@ -107,7 +107,15 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { LogRecordContext.putVariable("receivablePlan", oldReceivablePlan); } - private void checkReceivablePlan(CrmReceivablePlanSaveReqVO reqVO) { + @Override + public void updateReceivableId(Long id, Long receivableId) { + // 校验存在 + validateReceivablePlanExists(id); + // 更新回款计划 + receivablePlanMapper.updateById(new CrmReceivablePlanDO().setReceivableId(receivableId).setFinishStatus(true)); + } + + private void validateRelationDataExists(CrmReceivablePlanSaveReqVO reqVO) { adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 CrmContractDO contract = contractService.getContract(reqVO.getContractId()); if (ObjectUtil.isNull(contract)) { // 合同不存在 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java index 808b2cc2e..7b7d7599d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.crm.service.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; import jakarta.validation.Valid; @@ -22,17 +22,23 @@ public interface CrmReceivableService { * 创建回款 * * @param createReqVO 创建信息 - * @param userId 用户编号 * @return 编号 */ - Long createReceivable(@Valid CrmReceivableCreateReqVO createReqVO, Long userId); + Long createReceivable(@Valid CrmReceivableSaveReqVO createReqVO); /** * 更新回款 * * @param updateReqVO 更新信息 */ - void updateReceivable(@Valid CrmReceivableUpdateReqVO updateReqVO); + void updateReceivable(@Valid CrmReceivableSaveReqVO updateReqVO); + + /** + * 更新回款流程审批结果 + * + * @param event 审批结果 + */ + void updateReceivableAuditStatus(BpmResultListenerRespDTO event); /** * 删除回款 @@ -41,6 +47,14 @@ public interface CrmReceivableService { */ void deleteReceivable(Long id); + /** + * 发起回款审批流程 + * + * @param id 回款编号 + * @param userId 用户编号 + */ + void submitReceivable(Long id, Long userId); + /** * 获得回款 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index 93ad4c97e..0d26cf3b7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -2,14 +2,17 @@ package cn.iocoder.yudao.module.crm.service.receivable; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +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.receivable.vo.receivable.CrmReceivablePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; -import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; @@ -23,19 +26,23 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.List; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; +import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertAuditStatus; /** * CRM 回款 Service 实现类 @@ -46,6 +53,11 @@ import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; @Validated public class CrmReceivableServiceImpl implements CrmReceivableService { + /** + * BPM 回款审批流程标识 + */ + public static final String RECEIVABLE_APPROVE = "receivable-approve"; + @Resource private CrmReceivableMapper receivableMapper; @@ -57,51 +69,47 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { private CrmReceivablePlanService receivablePlanService; @Resource private CrmPermissionService permissionService; + @Resource + private AdminUserApi adminUserApi; + @Resource + private BpmProcessInstanceApi bpmProcessInstanceApi; @Override + @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_CREATE_SUB_TYPE, bizNo = "{{#receivable.id}}", success = CRM_RECEIVABLE_CREATE_SUCCESS) - public Long createReceivable(CrmReceivableCreateReqVO createReqVO, Long userId) { - // 插入还款 - CrmReceivableDO receivable = CrmReceivableConvert.INSTANCE.convert(createReqVO); - if (ObjectUtil.isNull(receivable.getAuditStatus())) { - receivable.setAuditStatus(CommonStatusEnum.ENABLE.getStatus()); - } - receivable.setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); - - // TODO @liuhongfeng:一般来说,逻辑的写法,是要先检查,后操作 db;所以,你这个 check 应该放到 CrmReceivableDO receivable 之前; - checkReceivable(receivable); - + public Long createReceivable(CrmReceivableSaveReqVO createReqVO) { + // 1. 校验关联数据存在 + validateRelationDataExists(createReqVO); + // 2. 插入还款 + CrmReceivableDO receivable = BeanUtils.toBean(createReqVO, CrmReceivableDO.class).setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); receivableMapper.insert(receivable); // 3. 创建数据权限 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType()) - .setBizId(receivable.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 - // TODO @liuhongfeng:需要更新关联的 plan - - // 4. 记录操作日志上下文 + .setBizId(receivable.getId()).setUserId(createReqVO.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 + // 4. 更新关联的回款计划 + if (Objects.nonNull(createReqVO.getPlanId())) { + receivablePlanService.updateReceivableId(receivable.getPlanId(), receivable.getId()); + } + // 5. 记录操作日志上下文 LogRecordContext.putVariable("receivable", receivable); return receivable.getId(); } - // TODO @liuhongfeng:这里的括号要注意排版; - private void checkReceivable(CrmReceivableDO receivable) { - // TODO @liuhongfeng:校验 no 的唯一性 - // TODO @liuhongfeng:这个放在参数校验合适 - if (ObjectUtil.isNull(receivable.getContractId())) { - throw exception(CONTRACT_NOT_EXISTS); - } - - CrmContractDO contract = contractService.getContract(receivable.getContractId()); + private void validateRelationDataExists(CrmReceivableSaveReqVO reqVO) { + adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 + CrmContractDO contract = contractService.getContract(reqVO.getContractId()); if (ObjectUtil.isNull(contract)) { throw exception(CONTRACT_NOT_EXISTS); } - - CrmCustomerDO customer = customerService.getCustomer(receivable.getCustomerId()); + CrmCustomerDO customer = customerService.getCustomer(reqVO.getCustomerId()); if (ObjectUtil.isNull(customer)) { throw exception(CUSTOMER_NOT_EXISTS); } - - CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(receivable.getPlanId()); + if (Objects.isNull(reqVO.getPlanId())) { // 没有回款计划编号则不校验 + return; + } + CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(reqVO.getPlanId()); if (ObjectUtil.isNull(receivablePlan)) { throw exception(RECEIVABLE_PLAN_NOT_EXISTS); } @@ -109,46 +117,84 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { } @Override + @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CRM_RECEIVABLE_UPDATE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) - public void updateReceivable(CrmReceivableUpdateReqVO updateReqVO) { - // 校验存在 - CrmReceivableDO oldReceivable = validateReceivableExists(updateReqVO.getId()); - // TODO @liuhongfeng:只有在草稿、审核中,可以提交修改 + public void updateReceivable(CrmReceivableSaveReqVO updateReqVO) { + Assert.notNull(updateReqVO.getId(), "回款编号不能为空"); + // 1.1 校验存在 + CrmReceivableDO receivable = validateReceivableExists(updateReqVO.getId()); + // 1.2 只有草稿、审批中,可以编辑; + if (!ObjectUtils.equalsAny(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), + CrmAuditStatusEnum.PROCESS.getStatus())) { + throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED); + } - // 更新还款 - CrmReceivableDO updateObj = CrmReceivableConvert.INSTANCE.convert(updateReqVO); + // 2. 更新还款 + CrmReceivableDO updateObj = BeanUtils.toBean(updateReqVO, CrmReceivableDO.class); receivableMapper.updateById(updateObj); - // TODO @liuhongfeng:需要更新关联的 plan // 3. 记录操作日志上下文 - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivable, CrmReceivableUpdateReqVO.class)); - LogRecordContext.putVariable("receivable", oldReceivable); + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(receivable, CrmReceivableSaveReqVO.class)); + LogRecordContext.putVariable("receivable", receivable); } - // TODO @liuhongfeng:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum + @Override + public void updateReceivableAuditStatus(BpmResultListenerRespDTO event) { + convertAuditStatus(event); + // 更新回款审批状态 + receivableMapper.updateById(new CrmReceivableDO().setId(Long.parseLong(event.getBusinessKey())) + .setAuditStatus(event.getResult())); + } - // TODO @liuhongfeng:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum + // TODO @liuhongfeng:缺一个取消回款的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum @Override + @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_DELETE_SUB_TYPE, bizNo = "{{#id}}", success = CRM_RECEIVABLE_DELETE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteReceivable(Long id) { - // TODO @liuhongfeng:如果被 CrmReceivablePlanDO 所使用,则不允许删除 // 校验存在 CrmReceivableDO receivable = validateReceivableExists(id); + // 如果被 CrmReceivablePlanDO 所使用,则不允许删除 + if (Objects.nonNull(receivable.getPlanId()) && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) { + throw exception(RECEIVABLE_DELETE_FAIL); + } // 删除 receivableMapper.deleteById(id); // 删除数据权限 - permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); + permissionService.deletePermission(CrmBizTypeEnum.CRM_RECEIVABLE.getType(), id); // 记录操作日志上下文 LogRecordContext.putVariable("receivable", receivable); } + @Override + @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_SUBMIT_SUB_TYPE, bizNo = "{{#id}}", + success = CRM_RECEIVABLE_SUBMIT_SUCCESS) + public void submitReceivable(Long id, Long userId) { + // 1. 校验回款是否在审批 + CrmReceivableDO receivable = validateReceivableExists(id); + if (ObjUtil.notEqual(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus())) { + throw exception(RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT); + } + + // 2. 创建回款审批流程实例 + String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() + .setProcessDefinitionKey(RECEIVABLE_APPROVE).setBusinessKey(String.valueOf(id))); + + // 3. 更新回款工作流编号 + receivableMapper.updateById(new CrmReceivableDO().setId(id).setProcessInstanceId(processInstanceId) + .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); + + // 4. 记录日志 + LogRecordContext.putVariable("receivableNo", receivable.getNo()); + } + private CrmReceivableDO validateReceivableExists(Long id) { CrmReceivableDO receivable = receivableMapper.selectById(id); if (receivable == null) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java new file mode 100644 index 000000000..099d228af --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.crm.service.receivable.listener; + +import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService; +import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableServiceImpl; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +// TODO @芋艿:后续改成支持 RPC + +/** + * 回款审批的结果的监听器实现类 + * + * @author HUIHUI + */ +@Component +public class CrmReceivableResultListener implements BpmResultListenerApi { + + @Resource + private CrmReceivableService receivableService; + + @Override + public String getProcessDefinitionKey() { + return CrmReceivableServiceImpl.RECEIVABLE_APPROVE; + } + + @Override + public void onEvent(BpmResultListenerRespDTO event) { + receivableService.updateReceivableAuditStatus(event); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java new file mode 100644 index 000000000..017045e6e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.crm.util; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; + +/** + * CRM 流程工具类 + * + * @author HUIHUI + */ +public class CrmAuditStatusUtils { + + public static void convertAuditStatus(BpmResultListenerRespDTO event) { + // 判断下状态是否符合预期 + if (!isEndResult(event.getResult())) { + return; + } + // 状态转换 + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { + event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); + } + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { + event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); + } + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { + event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); + } + } + + /** + * 判断该结果是否处于 End 最终结果 + * + * @param result 结果 + * @return 是否 + */ + public static boolean isEndResult(Integer result) { + return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), + BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); + } + +} From 5892c8897fa86e41d670b1ec93b196f076899608 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 23 Feb 2024 12:20:08 +0800 Subject: [PATCH 31/54] =?UTF-8?q?CRM:=20=E6=B5=81=E7=A8=8B=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E8=BD=AC=E6=8D=A2=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contract/CrmContractServiceImpl.java | 25 +++---------------- .../receivable/CrmReceivableServiceImpl.java | 5 ++++ .../module/crm/util/CrmAuditStatusUtils.java | 9 ++++--- 3 files changed, 13 insertions(+), 26 deletions(-) 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 d89b90351..fae8f2e18 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 @@ -11,7 +11,6 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; 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; @@ -48,6 +47,8 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; +import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertAuditStatus; +import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.isEndResult; /** * CRM 合同 Service 实现类 @@ -296,32 +297,12 @@ public class CrmContractServiceImpl implements CrmContractService { if (!isEndResult(event.getResult())) { return; } - // 状态转换 - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { - event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { - event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { - event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); - } + convertAuditStatus(event); // 更新合同状态 contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())) .setAuditStatus(event.getResult())); } - /** - * 判断该结果是否处于 End 最终结果 - * - * @param result 结果 - * @return 是否 - */ - public static boolean isEndResult(Integer result) { - return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), - BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); - } - //======================= 查询相关 ======================= @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index 0d26cf3b7..a032c1423 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -43,6 +43,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertAuditStatus; +import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.isEndResult; /** * CRM 回款 Service 实现类 @@ -142,6 +143,10 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @Override public void updateReceivableAuditStatus(BpmResultListenerRespDTO event) { + // 判断下状态是否符合预期 + if (!isEndResult(event.getResult())) { + return; + } convertAuditStatus(event); // 更新回款审批状态 receivableMapper.updateById(new CrmReceivableDO().setId(Long.parseLong(event.getBusinessKey())) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java index 017045e6e..f5d1d67df 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java @@ -13,11 +13,12 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; */ public class CrmAuditStatusUtils { + /** + * 流程审批状态转换 + * + * @param event 业务流程实例的结果 + */ public static void convertAuditStatus(BpmResultListenerRespDTO event) { - // 判断下状态是否符合预期 - if (!isEndResult(event.getResult())) { - return; - } // 状态转换 if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); From 4066ad3e1ae8b08cedb13d713dfef7ea5c3be6c4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 23 Feb 2024 12:59:16 +0800 Subject: [PATCH 32/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=90=88=E5=90=8C=E7=9A=84=E5=AE=A1=E6=89=B9=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/listener/BpmResultListenerApi.java | 27 ----------- .../dto/BpmResultListenerRespDTO.java | 32 ------------- .../event/BpmProcessInstanceResultEvent.java | 8 ++-- ...BpmProcessInstanceResultEventListener.java | 2 +- .../task/BpmProcessInstanceConvert.java | 2 +- ...pmProcessInstanceResultEventPublisher.java | 1 + .../listener/BpmServiceResultListener.java | 36 --------------- .../oa/listener/BpmOALeaveResultListener.java | 4 +- .../module/crm/enums/ErrorCodeConstants.java | 3 +- .../admin/contract/vo/CrmContractRespVO.java | 2 +- .../service/contract/CrmContractService.java | 6 +-- .../contract/CrmContractServiceImpl.java | 46 +++++++------------ .../listener/CrmContractResultListener.java | 11 ++--- 13 files changed, 36 insertions(+), 144 deletions(-) delete mode 100644 yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java rename yudao-module-bpm/{yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core => yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm}/event/BpmProcessInstanceResultEvent.java (87%) rename yudao-module-bpm/{yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core => yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm}/event/BpmProcessInstanceResultEventListener.java (93%) delete mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java deleted file mode 100644 index d519ed9ed..000000000 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.bpm.api.listener; - -import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; - -// TODO @芋艿:后续改成支持 RPC -/** - * 业务流程实例的结果发生变化的监听器 Api - * - * @author HUIHUI - */ -public interface BpmResultListenerApi { - - /** - * 监听的流程定义 Key - * - * @return 返回监听的流程定义 Key - */ - String getProcessDefinitionKey(); - - /** - * 处理事件 - * - * @param event 事件 - */ - void onEvent(BpmResultListenerRespDTO event); - -} diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java deleted file mode 100644 index 30721785d..000000000 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.bpm.api.listener.dto; - -import lombok.Data; - -// TODO @芋艿:后续改成支持 RPC -/** - * 业务流程实例的结果 Response DTO - * - * @author HUIHUI - */ -@Data -public class BpmResultListenerRespDTO { - - /** - * 流程实例的编号 - */ - private String id; - /** - * 流程实例的 key - */ - private String processDefinitionKey; - /** - * 流程实例的结果 - */ - private Integer result; - /** - * 流程实例对应的业务标识 - * 例如说,请假 - */ - private String businessKey; - -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEvent.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceResultEvent.java similarity index 87% rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEvent.java rename to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceResultEvent.java index f94f20ac3..9b703728d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEvent.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceResultEvent.java @@ -1,10 +1,8 @@ -package cn.iocoder.yudao.module.bpm.framework.bpm.core.event; - -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; -import lombok.Data; -import org.springframework.context.ApplicationEvent; +package cn.iocoder.yudao.module.bpm.event; import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.context.ApplicationEvent; /** * 流程实例的结果发生变化的 Event diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventListener.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceResultEventListener.java similarity index 93% rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventListener.java rename to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceResultEventListener.java index c2b215394..bff99a8c1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceResultEventListener.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.bpm.framework.bpm.core.event; +package cn.iocoder.yudao.module.bpm.event; import cn.hutool.core.util.StrUtil; import org.springframework.context.ApplicationListener; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java index 8296b8bb3..41f2184c5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessI import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; -import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEvent; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java index 05434f7c2..b759fe1e1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.framework.bpm.core.event; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEvent; import lombok.AllArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java deleted file mode 100644 index 34a045a23..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.bpm.framework.bpm.listener; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; -import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; -import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; -import jakarta.annotation.Resource; -import org.springframework.context.ApplicationListener; -import org.springframework.stereotype.Component; - -import java.util.List; - -// TODO @芋艿:后续改成支持 RPC -/** - * 业务流程结果监听器实现类 - * - * @author HUIHUI - */ -@Component -public class BpmServiceResultListener implements ApplicationListener { - - @Resource - private List bpmResultListenerApis; - - @Override - public final void onApplicationEvent(BpmProcessInstanceResultEvent event) { - bpmResultListenerApis.forEach(bpmResultListenerApi -> { - if (!StrUtil.equals(event.getProcessDefinitionKey(), bpmResultListenerApi.getProcessDefinitionKey())) { - return; - } - bpmResultListenerApi.onEvent(BeanUtils.toBean(event, BpmResultListenerRespDTO.class)); - }); - } - -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java index 0f8e9e569..e1dccb52b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.bpm.service.oa.listener; -import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; -import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventListener; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEvent; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEventListener; import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveService; import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveServiceImpl; import org.springframework.stereotype.Component; diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index fa1cec68a..278989c73 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -11,8 +11,9 @@ public interface ErrorCodeConstants { // ========== 合同管理 1-020-000-000 ========== ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在"); - ErrorCode CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_000_001, "更新合同失败,原因:禁止编辑"); + ErrorCode CONTRACT_UPDATE_FAIL_NOT_DRAFT = new ErrorCode(1_020_000_001, "合同更新失败,原因:合同不是草稿状态"); ErrorCode CONTRACT_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_000_002, "合同提交审核失败,原因:合同没处在未提交状态"); + ErrorCode CONTRACT_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_020_000_003, "更新合同审核状态失败,原因:合同不是处理中状态"); // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); 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/CrmContractRespVO.java index f32549e77..887bdd80a 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/CrmContractRespVO.java @@ -58,7 +58,7 @@ public class CrmContractRespVO { @Schema(description = "工作流编号", example = "1043") @ExcelProperty("工作流编号") - private Long processInstanceId; + private String processInstanceId; @Schema(description = "审批状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @ExcelProperty("审批状态") 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 e9f4e6f59..cbd9cbbe7 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,7 +1,6 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; 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; @@ -72,9 +71,10 @@ public interface CrmContractService { /** * 更新合同流程审批结果 * - * @param event 审批结果 + * @param id 合同编号 + * @param bpmResult BPM 审批结果 */ - void updateContractAuditStatus(BpmResultListenerRespDTO event); + void updateContractAuditStatus(Long id, Integer bpmResult); /** * 获得合同 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 d89b90351..2100dbd95 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 @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; 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.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; @@ -35,6 +34,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -56,6 +56,7 @@ import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; */ @Service @Validated +@Slf4j public class CrmContractServiceImpl implements CrmContractService { /** @@ -129,7 +130,7 @@ public class CrmContractServiceImpl implements CrmContractService { // 1.2 只有草稿、审批中,可以编辑; if (!ObjectUtils.equalsAny(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { - throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); + throw exception(CONTRACT_UPDATE_FAIL_NOT_DRAFT); } // 1.3 校验产品项的有效性 List contractProducts = validateContractProducts(updateReqVO.getProducts()); @@ -291,35 +292,22 @@ public class CrmContractServiceImpl implements CrmContractService { } @Override - public void updateContractAuditStatus(BpmResultListenerRespDTO event) { - // 判断下状态是否符合预期 - if (!isEndResult(event.getResult())) { - return; + public void updateContractAuditStatus(Long id, Integer bpmResult) { + // 1.1 校验合同是否存在 + CrmContractDO contract = validateContractExists(id); + // 1.2 只有审批中,可以更新审批结果 + if (ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { + log.error("[updateContractAuditStatus][contract({}) 不处于审批中,无法更新审批结果({})]", + contract.getId(), bpmResult); + throw exception(CONTRACT_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); } - // 状态转换 - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { - event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { - event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { - event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); - } - // 更新合同状态 - contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())) - .setAuditStatus(event.getResult())); - } - /** - * 判断该结果是否处于 End 最终结果 - * - * @param result 结果 - * @return 是否 - */ - public static boolean isEndResult(Integer result) { - return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), - BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); + // 2. 更新合同审批结果 + Integer auditStatus = BpmProcessInstanceResultEnum.APPROVE.getResult().equals(bpmResult) ? CrmAuditStatusEnum.APPROVE.getStatus() + : BpmProcessInstanceResultEnum.REJECT.getResult().equals(bpmResult) ? CrmAuditStatusEnum.REJECT.getStatus() + : BpmProcessInstanceResultEnum.CANCEL.getResult(); + Assert.notNull(auditStatus, "BPM 审批结果({}) 转换失败", bpmResult); + contractMapper.updateById(new CrmContractDO().setId(id).setAuditStatus(auditStatus)); } //======================= 查询相关 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index c5ee407bd..b3f4c3960 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -1,20 +1,19 @@ package cn.iocoder.yudao.module.crm.service.contract.listener; -import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; -import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEvent; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEventListener; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; -// TODO @芋艿:后续改成支持 RPC /** * 合同审批的结果的监听器实现类 * * @author HUIHUI */ @Component -public class CrmContractResultListener implements BpmResultListenerApi { +public class CrmContractResultListener extends BpmProcessInstanceResultEventListener { @Resource private CrmContractService contractService; @@ -25,8 +24,8 @@ public class CrmContractResultListener implements BpmResultListenerApi { } @Override - public void onEvent(BpmResultListenerRespDTO event) { - contractService.updateContractAuditStatus(event); + protected void onEvent(BpmProcessInstanceResultEvent event) { + contractService.updateContractAuditStatus(Long.parseLong(event.getBusinessKey()), event.getResult()); } } From be2431b73b48bbf040d86039106a3af536a3e805 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 23 Feb 2024 14:37:03 +0800 Subject: [PATCH 33/54] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=E5=9B=9E?= =?UTF-8?q?=E6=AC=BE=E5=AE=A1=E6=89=B9=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 4 +-- .../contract/CrmContractServiceImpl.java | 7 ++--- .../receivable/CrmReceivableService.java | 6 ++-- .../receivable/CrmReceivableServiceImpl.java | 26 +++++++++------- .../listener/CrmReceivableResultListener.java | 12 +++---- .../module/crm/util/CrmAuditStatusUtils.java | 31 ++++++++----------- 6 files changed, 40 insertions(+), 46 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 0855dd559..5640d16a2 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -13,7 +13,7 @@ public interface ErrorCodeConstants { ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在"); ErrorCode CONTRACT_UPDATE_FAIL_NOT_DRAFT = new ErrorCode(1_020_000_001, "合同更新失败,原因:合同不是草稿状态"); ErrorCode CONTRACT_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_000_002, "合同提交审核失败,原因:合同没处在未提交状态"); - ErrorCode CONTRACT_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_020_000_003, "更新合同审核状态失败,原因:合同不是处理中状态"); + ErrorCode CONTRACT_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_020_000_003, "更新合同审核状态失败,原因:合同不是审核中状态"); // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); @@ -36,7 +36,7 @@ public interface ErrorCodeConstants { ErrorCode RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_004_001, "更新回款失败,原因:禁止编辑"); ErrorCode RECEIVABLE_DELETE_FAIL = new ErrorCode(1_020_004_002, "删除回款失败,原因: 被回款计划所使用,不允许删除"); ErrorCode RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_004_003, "回款提交审核失败,原因:回款没处在未提交状态"); - + ErrorCode RECEIVABLE_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_020_004_004, "更新回款审核状态失败,原因:回款不是审核中状态"); // ========== 回款计划 1-020-005-000 ========== ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "回款计划不存在"); 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 2100dbd95..dcb892349 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,7 +10,6 @@ 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.bpm.enums.task.BpmProcessInstanceResultEnum; 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; @@ -48,6 +47,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; +import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertBpmResultToAuditStatus; /** * CRM 合同 Service 实现类 @@ -303,10 +303,7 @@ public class CrmContractServiceImpl implements CrmContractService { } // 2. 更新合同审批结果 - Integer auditStatus = BpmProcessInstanceResultEnum.APPROVE.getResult().equals(bpmResult) ? CrmAuditStatusEnum.APPROVE.getStatus() - : BpmProcessInstanceResultEnum.REJECT.getResult().equals(bpmResult) ? CrmAuditStatusEnum.REJECT.getStatus() - : BpmProcessInstanceResultEnum.CANCEL.getResult(); - Assert.notNull(auditStatus, "BPM 审批结果({}) 转换失败", bpmResult); + Integer auditStatus = convertBpmResultToAuditStatus(bpmResult); contractMapper.updateById(new CrmContractDO().setId(id).setAuditStatus(auditStatus)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java index 7b7d7599d..8de653a7f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.crm.service.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -36,9 +35,10 @@ public interface CrmReceivableService { /** * 更新回款流程审批结果 * - * @param event 审批结果 + * @param id 回款编号 + * @param bpmResult BPM 审批结果 */ - void updateReceivableAuditStatus(BpmResultListenerRespDTO event); + void updateReceivableAuditStatus(Long id, Integer bpmResult); /** * 删除回款 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index a032c1423..d11bb939d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -8,7 +8,6 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.listener.dto.BpmResultListenerRespDTO; 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.receivable.vo.receivable.CrmReceivablePageReqVO; @@ -31,6 +30,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -42,8 +42,7 @@ import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; -import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertAuditStatus; -import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.isEndResult; +import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertBpmResultToAuditStatus; /** * CRM 回款 Service 实现类 @@ -52,6 +51,7 @@ import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.isEndResult; */ @Service @Validated +@Slf4j public class CrmReceivableServiceImpl implements CrmReceivableService { /** @@ -142,15 +142,19 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { } @Override - public void updateReceivableAuditStatus(BpmResultListenerRespDTO event) { - // 判断下状态是否符合预期 - if (!isEndResult(event.getResult())) { - return; + public void updateReceivableAuditStatus(Long id, Integer bpmResult) { + // 1.1 校验存在 + CrmReceivableDO receivable = validateReceivableExists(id); + // 1.2 只有审批中,可以更新审批结果 + if (ObjUtil.notEqual(receivable.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { + log.error("[updateReceivableAuditStatus][receivable({}) 不处于审批中,无法更新审批结果({})]", + receivable.getId(), bpmResult); + throw exception(RECEIVABLE_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); } - convertAuditStatus(event); - // 更新回款审批状态 - receivableMapper.updateById(new CrmReceivableDO().setId(Long.parseLong(event.getBusinessKey())) - .setAuditStatus(event.getResult())); + + // 2. 更新回款审批状态 + Integer auditStatus = convertBpmResultToAuditStatus(bpmResult); + receivableMapper.updateById(new CrmReceivableDO().setId(id).setAuditStatus(auditStatus)); } // TODO @liuhongfeng:缺一个取消回款的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java index 099d228af..769fc35ad 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableResultListener.java @@ -1,21 +1,19 @@ package cn.iocoder.yudao.module.crm.service.receivable.listener; -import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; -import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEvent; +import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceResultEventListener; import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService; import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; -// TODO @芋艿:后续改成支持 RPC - /** * 回款审批的结果的监听器实现类 * * @author HUIHUI */ @Component -public class CrmReceivableResultListener implements BpmResultListenerApi { +public class CrmReceivableResultListener extends BpmProcessInstanceResultEventListener { @Resource private CrmReceivableService receivableService; @@ -26,8 +24,8 @@ public class CrmReceivableResultListener implements BpmResultListenerApi { } @Override - public void onEvent(BpmResultListenerRespDTO event) { - receivableService.updateReceivableAuditStatus(event); + public void onEvent(BpmProcessInstanceResultEvent event) { + receivableService.updateReceivableAuditStatus(Long.parseLong(event.getBusinessKey()), event.getResult()); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java index f5d1d67df..0169b0d87 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.module.crm.util; -import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; @@ -14,31 +13,27 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; public class CrmAuditStatusUtils { /** - * 流程审批状态转换 + * BPM 审批结果转换 * - * @param event 业务流程实例的结果 + * @param bpmResult BPM 审批结果 */ - public static void convertAuditStatus(BpmResultListenerRespDTO event) { - // 状态转换 - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { - event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { - event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { - event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); - } + public static Integer convertBpmResultToAuditStatus(Integer bpmResult) { + Assert.isTrue(isEndResult(bpmResult), "BPM 审批结果({}) 转换失败, 流程状态不是最终结果", bpmResult); + Integer auditStatus = BpmProcessInstanceResultEnum.APPROVE.getResult().equals(bpmResult) ? CrmAuditStatusEnum.APPROVE.getStatus() + : BpmProcessInstanceResultEnum.REJECT.getResult().equals(bpmResult) ? CrmAuditStatusEnum.REJECT.getStatus() + : BpmProcessInstanceResultEnum.CANCEL.getResult(); + Assert.notNull(auditStatus, "BPM 审批结果({}) 转换失败", bpmResult); + return auditStatus; } /** * 判断该结果是否处于 End 最终结果 * - * @param result 结果 + * @param bpmResult BPM 审批结果 * @return 是否 */ - public static boolean isEndResult(Integer result) { - return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), + public static boolean isEndResult(Integer bpmResult) { + return ObjectUtils.equalsAny(bpmResult, BpmProcessInstanceResultEnum.APPROVE.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); } From e53a0ca8845229fb298c4d77da0f09315a6a5a4f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 23 Feb 2024 18:50:22 +0800 Subject: [PATCH 34/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9Acode=20review=20?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/collection/CollectionUtils.java | 4 +- .../framework/ip/core/utils/AreaUtils.java | 32 +++++---- .../framework/ip/core/utils/IPUtils.java | 4 +- .../ip/core/utils/AreaUtilsTest.java | 2 +- .../yudao-spring-boot-starter-excel/pom.xml | 2 +- .../excel/core/convert/AreaConvert.java | 2 +- .../core/handler/SelectSheetWriteHandler.java | 56 +++++++++------- .../framework/excel/core/util/ExcelUtils.java | 10 +-- .../module/crm/enums/ErrorCodeConstants.java | 1 + ....java => CrmReceivableReturnTypeEnum.java} | 12 +--- .../admin/customer/CrmCustomerController.java | 35 +++++----- .../receivable/CrmReceivableController.java | 1 - .../CrmReceivablePlanController.java | 2 - .../vo/plan/CrmReceivablePlanRespVO.java | 59 ++++++++--------- .../vo/plan/CrmReceivablePlanSaveReqVO.java | 35 ++++------ .../vo/receivable/CrmReceivableSaveReqVO.java | 4 +- .../receivable/CrmReceivableDO.java | 4 +- .../receivable/CrmReceivablePlanDO.java | 65 +++++++++++-------- .../dal/mysql/contract/CrmContractMapper.java | 7 +- .../crm/dal/redis/RedisKeyConstants.java | 18 +++++ .../crm/dal/redis/no/CrmNoRedisDAO.java | 52 +++++++++++++++ .../contract/CrmContractServiceImpl.java | 15 +++-- .../CrmReceivablePlanServiceImpl.java | 10 +-- .../receivable/CrmReceivableServiceImpl.java | 5 +- .../module/crm/util/CrmAuditStatusUtils.java | 15 +---- .../erp/dal/redis/RedisKeyConstants.java | 2 +- .../erp/dal/redis/no/ErpNoRedisDAO.java | 2 +- .../module/system/api/dict/DictDataApi.java | 15 ++++- .../system/api/dict/DictDataApiImpl.java | 13 +--- .../controller/admin/ip/AreaController.java | 2 +- .../controller/app/ip/AppAreaController.java | 2 +- .../system/service/dict/DictDataService.java | 2 +- .../service/dict/DictDataServiceImpl.java | 4 +- 33 files changed, 277 insertions(+), 217 deletions(-) rename yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/{CrmReturnTypeEnum.java => CrmReceivableReturnTypeEnum.java} (77%) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 8ffd21ccc..cb4ddec34 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -257,11 +257,11 @@ public class CollectionUtils { return !CollectionUtil.isEmpty(from) ? from.get(0) : null; } - public static T findFirst(List from, Predicate predicate) { + public static T findFirst(Collection from, Predicate predicate) { return findFirst(from, predicate, Function.identity()); } - public static U findFirst(List from, Predicate predicate, Function func) { + public static U findFirst(Collection from, Predicate predicate, Function func) { if (CollUtil.isEmpty(from)) { return null; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java index adcfc345b..99a1ac994 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java @@ -4,7 +4,6 @@ import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.csv.CsvRow; import cn.hutool.core.text.csv.CsvUtil; -import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; @@ -72,26 +71,25 @@ public class AreaUtils { * @param id 区域编号 * @return 区域 */ - public static Area getArea(Integer id) { + public static Area parseArea(Integer id) { return areas.get(id); } /** * 获得指定区域对应的编号 * - * @param path 区域编号 - * @return 编号 + * @param pathStr 区域路径,例如说:河南省/石家庄市/新华区 + * @return 区域 */ - public static Area getArea(String path) { - String[] paths = path.split("/"); + public static Area parseArea(String pathStr) { + String[] paths = pathStr.split("/"); Area area = null; - for (int i = 0; i < paths.length; i++) { - final int finalI = i; + for (String path : paths) { if (area == null) { - area = findFirst(convertList(areas.values(), a -> a), item -> ObjUtil.equal(paths[finalI], item.getName())); - continue; + area = findFirst(areas.values(), item -> item.getName().equals(path)); + } else { + area = findFirst(area.getChildren(), item -> item.getName().equals(path)); } - area = findFirst(area.getChildren(), item -> ObjUtil.equal(paths[finalI], item.getName())); } return area; } @@ -102,9 +100,9 @@ public class AreaUtils { * @param areas 地区树 * @return 所有节点的全路径名称 */ - public static List getAllAreaNodePaths(List areas) { + public static List getAreaNodePathList(List areas) { List paths = new ArrayList<>(); - areas.forEach(area -> traverse(area, "", paths)); + areas.forEach(area -> getAreaNodePathList(area, "", paths)); return paths; } @@ -113,9 +111,9 @@ public class AreaUtils { * * @param node 父节点 * @param path 全路径名称 - * @param paths 全路径名称列表 + * @param paths 全路径名称列表,省份/城市/地区 */ - private static void traverse(Area node, String path, List paths) { + private static void getAreaNodePathList(Area node, String path, List paths) { if (node == null) { return; } @@ -124,7 +122,7 @@ public class AreaUtils { paths.add(currentPath); // 递归遍历子节点 for (Area child : node.getChildren()) { - traverse(child, currentPath, paths); + getAreaNodePathList(child, currentPath, paths); } } @@ -195,7 +193,7 @@ public class AreaUtils { */ public static Integer getParentIdByType(Integer id, @NonNull AreaTypeEnum type) { for (int i = 0; i < Byte.MAX_VALUE; i++) { - Area area = AreaUtils.getArea(id); + Area area = AreaUtils.parseArea(id); if (area == null) { return null; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java index f74f84864..4701168cd 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java @@ -72,7 +72,7 @@ public class IPUtils { * @return 地区 */ public static Area getArea(String ip) { - return AreaUtils.getArea(getAreaId(ip)); + return AreaUtils.parseArea(getAreaId(ip)); } /** @@ -82,6 +82,6 @@ public class IPUtils { * @return 地区 */ public static Area getArea(long ip) { - return AreaUtils.getArea(getAreaId(ip)); + return AreaUtils.parseArea(getAreaId(ip)); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java index 8f5646b33..704d4415d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java @@ -17,7 +17,7 @@ public class AreaUtilsTest { @Test public void testGetArea() { // 调用:北京 - Area area = AreaUtils.getArea(110100); + Area area = AreaUtils.parseArea(110100); // 断言 assertEquals(area.getId(), 110100); assertEquals(area.getName(), "北京市"); diff --git a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml index b5d5c24a2..767532cac 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml @@ -49,7 +49,7 @@ cn.iocoder.boot yudao-spring-boot-starter-biz-ip - provided + true diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java index f218c0b14..9778b17ae 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java @@ -33,7 +33,7 @@ public class AreaConvert implements Converter { GlobalConfiguration globalConfiguration) { // 解析地区编号 String label = readCellData.getStringValue(); - Area area = AreaUtils.getArea(label); + Area area = AreaUtils.parseArea(label); if (area == null) { log.error("[convertToJavaData][label({}) 解析不掉]", label); return null; 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 661db5369..db3fc2776 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 @@ -19,33 +19,40 @@ import java.util.List; */ public class SelectSheetWriteHandler implements SheetWriteHandler { + private static final String DICT_SHEET_NAME = "字典sheet"; + + // TODO @puhui999:key 不使用 int 值么?感觉不是很优雅哈。 private final List>> selectMap; private static final char[] ALPHABET = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; public SelectSheetWriteHandler(List>> selectMap) { + if (CollUtil.isEmpty(selectMap)) { + this.selectMap = null; + return; + } selectMap.sort(Comparator.comparing(item -> item.getValue().size())); // 升序不然创建下拉会报错 this.selectMap = selectMap; } @Override public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { - if (selectMap == null || CollUtil.isEmpty(selectMap)) { + if (CollUtil.isEmpty(selectMap)) { return; } - // 需要设置下拉框的sheet页 - Sheet curSheet = writeSheetHolder.getSheet(); - DataValidationHelper helper = curSheet.getDataValidationHelper(); - String dictSheetName = "字典sheet"; + // 需要设置下拉框的 sheet 页 + Sheet currentSheet = writeSheetHolder.getSheet(); + DataValidationHelper helper = currentSheet.getDataValidationHelper(); Workbook workbook = writeWorkbookHolder.getWorkbook(); - // 数据字典的sheet页 - Sheet dictSheet = workbook.createSheet(dictSheetName); + + // 数据字典的 sheet 页 + Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME); for (KeyValue> keyValue : selectMap) { // 设置下拉单元格的首行、末行、首列、末列 CellRangeAddressList rangeAddressList = new CellRangeAddressList(1, 65533, keyValue.getKey(), keyValue.getKey()); int rowLen = keyValue.getValue().size(); - // 设置字典sheet页的值 每一列一个字典项 + // 设置字典 sheet 页的值 每一列一个字典项 for (int i = 0; i < rowLen; i++) { Row row = dictSheet.getRow(i); if (row == null) { @@ -53,18 +60,18 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { } row.createCell(keyValue.getKey()).setCellValue(keyValue.getValue().get(i)); } - String excelColumn = getExcelColumn(keyValue.getKey()); - // 下拉框数据来源 eg:字典sheet!$B1:$B2 - String refers = dictSheetName + "!$" + excelColumn + "$1:$" + excelColumn + "$" + rowLen; - // 创建可被其他单元格引用的名称 + + // TODO @puhui999:下面 1. 2.1 2.2 2.3 我是按照已经理解的,调整了下格式;这样可读性更好;在 52 到 62 行,你可以看看,是不是也弄下序号; + // 1. 创建可被其他单元格引用的名称 Name name = workbook.createName(); - // 设置名称的名字 - name.setNameName("dict" + keyValue.getKey()); - // 设置公式 - name.setRefersToFormula(refers); - // 设置引用约束 - DataValidationConstraint constraint = helper.createFormulaListConstraint("dict" + keyValue.getKey()); - // 设置约束 + // TODO @puhui999:下面的 excelColumn 和 refers 两行,是不是可以封装成一个方法,替代 getExcelColumn; + String excelColumn = getExcelColumn(keyValue.getKey()); + String refers = DICT_SHEET_NAME + "!$" + excelColumn + "$1:$" + excelColumn + "$" + rowLen; // 下拉框数据来源 eg:字典sheet!$B1:$B2 + name.setNameName("dict" + keyValue.getKey()); // 设置名称的名字 + name.setRefersToFormula(refers); // 设置公式 + + // 2.1 设置约束 + DataValidationConstraint constraint = helper.createFormulaListConstraint("dict" + keyValue.getKey()); // 设置引用约束 DataValidation validation = helper.createValidation(constraint, rangeAddressList); if (validation instanceof HSSFDataValidation) { validation.setSuppressDropDownArrow(false); @@ -72,10 +79,10 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { validation.setSuppressDropDownArrow(true); validation.setShowErrorBox(true); } - // 阻止输入非下拉框的值 + // 2.2 阻止输入非下拉框的值 validation.setErrorStyle(DataValidation.ErrorStyle.STOP); validation.createErrorBox("提示", "此值不存在于下拉选择中!"); - // 添加下拉框约束 + // 2.3 添加下拉框约束 writeSheetHolder.getSheet().addValidationData(validation); } } @@ -86,8 +93,9 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { * @param num 数字 * @return 字母 */ + // TODO @puhui999:这个是必须字母列哇?还是数字其实也可以哈?主要想看看,怎么能把这个逻辑,进一步简化 private String getExcelColumn(int num) { - String column = ""; + String column; int len = ALPHABET.length - 1; int first = num / len; int second = num % len; @@ -96,9 +104,9 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { } else { column = ALPHABET[first - 1] + ""; if (second == 0) { - column = column + ALPHABET[len] + ""; + column = column + ALPHABET[len]; } else { - column = column + ALPHABET[second - 1] + ""; + column = column + ALPHABET[second - 1]; } } return column; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index 83877ece8..ee4ba25c7 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -33,15 +33,7 @@ public class ExcelUtils { */ public static void write(HttpServletResponse response, String filename, String sheetName, Class head, List data) throws IOException { - // 输出 Excel - EasyExcel.write(response.getOutputStream(), head) - .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 - .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 - .sheet(sheetName).doWrite(data); - // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name())); - response.setContentType("application/vnd.ms-excel;charset=UTF-8"); + write(response, filename, sheetName, head, data, null); } /** diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 5640d16a2..b9c3898ce 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -14,6 +14,7 @@ public interface ErrorCodeConstants { ErrorCode CONTRACT_UPDATE_FAIL_NOT_DRAFT = new ErrorCode(1_020_000_001, "合同更新失败,原因:合同不是草稿状态"); ErrorCode CONTRACT_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_000_002, "合同提交审核失败,原因:合同没处在未提交状态"); ErrorCode CONTRACT_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_020_000_003, "更新合同审核状态失败,原因:合同不是审核中状态"); + ErrorCode CONTRACT_NO_EXISTS = new ErrorCode(1_020_000_004, "生成合同序列号重复,请重试"); // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReturnTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReceivableReturnTypeEnum.java similarity index 77% rename from yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReturnTypeEnum.java rename to yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReceivableReturnTypeEnum.java index 8aacadce3..3c01fe95c 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReturnTypeEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReceivableReturnTypeEnum.java @@ -13,26 +13,18 @@ import java.util.Arrays; */ @Getter @AllArgsConstructor -public enum CrmReturnTypeEnum implements IntArrayValuable { +public enum CrmReceivableReturnTypeEnum implements IntArrayValuable { - // 支票 CHECK(1, "支票"), - // 现金 CASH(2, "现金"), - // 邮政汇款 POSTAL_REMITTANCE(3, "邮政汇款"), - // 电汇 TELEGRAPHIC_TRANSFER(4, "电汇"), - // 网上转账 ONLINE_TRANSFER(5, "网上转账"), - // 支付宝 ALIPAY(6, "支付宝"), - // 微信支付 WECHAT_PAY(7, "微信支付"), - // 其他 OTHER(8, "其它"); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmReturnTypeEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmReceivableReturnTypeEnum::getType).toArray(); /** * 类型 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index df6e0e625..54327c24c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -268,6 +268,24 @@ public class CrmCustomerController { ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list, builderSelectMap()); } + private List>> builderSelectMap() { + List>> selectMap = new ArrayList<>(); + // 获取地区下拉数据 + // TODO @puhui999:嘿嘿,这里改成省份、城市、区域,三个选项,难度大么? + Area area = AreaUtils.parseArea(Area.ID_CHINA); + selectMap.add(new KeyValue<>(6, AreaUtils.getAreaNodePathList(area.getChildren()))); + // 获取客户所属行业 + List customerIndustries = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_INDUSTRY); + selectMap.add(new KeyValue<>(8, customerIndustries)); + // 获取客户等级 + List customerLevels = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_LEVEL); + selectMap.add(new KeyValue<>(9, customerLevels)); + // 获取客户来源 + List customerSources = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_SOURCE); + selectMap.add(new KeyValue<>(10, customerSources)); + return selectMap; + } + @PostMapping("/import") @Operation(summary = "导入客户") @PreAuthorize("@ss.hasPermission('system:customer:import')") @@ -321,21 +339,4 @@ public class CrmCustomerController { return success(true); } - private List>> builderSelectMap() { - List>> selectMap = new ArrayList<>(); - // 获取地区下拉数据 - Area area = AreaUtils.getArea(Area.ID_CHINA); - selectMap.add(new KeyValue<>(6, AreaUtils.getAllAreaNodePaths(area.getChildren()))); - // 获取客户所属行业 - List customerIndustries = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_INDUSTRY); - selectMap.add(new KeyValue<>(8, customerIndustries)); - // 获取客户等级 - List customerLevels = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_LEVEL); - selectMap.add(new KeyValue<>(9, customerLevels)); - // 获取客户来源 - List customerSources = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_SOURCE); - selectMap.add(new KeyValue<>(10, customerSources)); - return selectMap; - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java index 5bbaefb5b..fcbbfed72 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java @@ -107,7 +107,6 @@ public class CrmReceivableController { return success(buildReceivableDetailPage(pageResult)); } - // TODO 芋艿:后面在优化导出 @GetMapping("/export-excel") @Operation(summary = "导出回款 Excel") @PreAuthorize("@ss.hasPermission('crm:receivable:export')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java index 2500c6f15..cbb9d51e4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java @@ -28,7 +28,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; -import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -56,7 +55,6 @@ public class CrmReceivablePlanController { @Resource private CrmReceivableService receivableService; @Resource - @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java index 9e6d1a03f..9b503db40 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java @@ -6,6 +6,7 @@ import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; +// TODO @puhui999:缺导出 @Schema(description = "管理后台 - CRM 回款计划 Response VO") @Data public class CrmReceivablePlanRespVO { @@ -13,17 +14,38 @@ public class CrmReceivablePlanRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Long id; - @Schema(description = "回款编号", example = "19852") - private Long receivableId; - @Schema(description = "期数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Integer period; + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long customerId; + @Schema(description = "客户名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "test") + private String customerName; + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long contractId; + @Schema(description = "合同编号", example = "Q110") + private String contractNo; + + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long ownerUserId; + @Schema(description = "负责人", example = "test") + private String ownerUserName; + + @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") + private LocalDateTime returnTime; + + @Schema(description = "回款方式", example = "1") + private Integer returnType; // 来自 Receivable 的 returnType 字段 + @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") private BigDecimal price; - @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") - private LocalDateTime returnTime; + @Schema(description = "回款编号", example = "19852") + private Long receivableId; + + @Schema(description = "完成状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean finishStatus; @Schema(description = "提前几天提醒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer remindDays; @@ -31,43 +53,16 @@ public class CrmReceivablePlanRespVO { @Schema(description = "提醒日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") private LocalDateTime remindTime; - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Long customerId; - - @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Long contractId; - - @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Long ownerUserId; - - @Schema(description = "显示顺序") - private Integer sort; - @Schema(description = "备注", example = "备注") private String remark; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; - @Schema(description = "客户名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "test") - private String customerName; - - @Schema(description = "合同编号", example = "Q110") - private String contractNo; - - @Schema(description = "负责人", example = "test") - private String ownerUserName; - @Schema(description = "创建人", example = "25682") private String creator; @Schema(description = "创建人名字", example = "test") private String creatorName; - @Schema(description = "完成状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Boolean finishStatus; - - @Schema(description = "回款方式", example = "1") - private Integer returnType; // 来自 Receivable 的 returnType 字段 - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java index 235daf328..b2bb41242 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanSaveReqVO.java @@ -14,26 +14,6 @@ public class CrmReceivablePlanSaveReqVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Long id; - @Schema(description = "期数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "期数不能为空") - private Integer period; - - @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") - @NotNull(message = "计划回款金额不能为空") - private BigDecimal price; - - @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") - @NotNull(message = "计划回款日期不能为空") - private LocalDateTime returnTime; - - @Schema(description = "提前几天提醒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "提前几天提醒不能为空") - private Integer remindDays; - - @Schema(description = "提醒日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") - @NotNull(message = "提醒日期不能为空") - private LocalDateTime remindTime; - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @NotNull(message = "客户编号不能为空") private Long customerId; @@ -46,8 +26,19 @@ public class CrmReceivablePlanSaveReqVO { @NotNull(message = "负责人编号不能为空") private Long ownerUserId; - @Schema(description = "显示顺序") - private Integer sort; + @Schema(description = "计划回款日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-02-02") + @NotNull(message = "计划回款日期不能为空") + private LocalDateTime returnTime; + + @Schema(description = "回款方式", example = "1") + private Integer returnType; + + @Schema(description = "计划回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") + @NotNull(message = "计划回款金额不能为空") + private BigDecimal price; + + @Schema(description = "提前几天提醒", example = "1") + private Integer remindDays; @Schema(description = "备注", example = "备注") private String remark; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java index 5340b4319..dfc0b1553 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableSaveReqVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.enums.receivable.CrmReturnTypeEnum; +import cn.iocoder.yudao.module.crm.enums.receivable.CrmReceivableReturnTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -23,7 +23,7 @@ public class CrmReceivableSaveReqVO { private Long planId; // 不是通过回款计划创建的回款没有回款计划编号 @Schema(description = "回款方式", example = "2") - @InEnum(CrmReturnTypeEnum.class) + @InEnum(CrmReceivableReturnTypeEnum.class) private Integer returnType; @Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "9000") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java index 6c1610935..3c8d71cd4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; -import cn.iocoder.yudao.module.crm.enums.receivable.CrmReturnTypeEnum; +import cn.iocoder.yudao.module.crm.enums.receivable.CrmReceivableReturnTypeEnum; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; @@ -60,7 +60,7 @@ public class CrmReceivableDO extends BaseDO { */ private LocalDateTime returnTime; /** - * 回款方式,关联枚举{@link CrmReturnTypeEnum} + * 回款方式,关联枚举{@link CrmReceivableReturnTypeEnum} */ private Integer returnType; /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java index 80a04ece7..d0e6a3e66 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.receivable; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.crm.enums.receivable.CrmReceivableReturnTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -13,7 +13,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; /** - * 回款计划 DO + * CRM 回款计划 DO * * @author 芋道源码 */ @@ -37,17 +37,49 @@ public class CrmReceivablePlanDO extends BaseDO { */ private Integer period; /** - * 回款编号,关联 {@link CrmReceivableDO#getId()} + * 客户编号 + * + * 关联 {@link CrmCustomerDO#getId()} */ - private Long receivableId; + private Long customerId; /** - * 计划回款金额,单位:元 + * 合同编号 + * + * 关联 {@link CrmContractDO#getId()} */ - private BigDecimal price; + private Long contractId; + + /** + * 负责人编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + /** * 计划回款日期 */ private LocalDateTime returnTime; + /** + * 回款类型 + * + * 枚举 {@link CrmReceivableReturnTypeEnum} + */ + private Integer returnType; + /** + * 计划回款金额,单位:元 + */ + private BigDecimal price; + + /** + * 回款编号,关联 {@link CrmReceivableDO#getId()} + */ + private Long receivableId; + /** + * 完成状态 + */ + private Boolean finishStatus; + /** * 提前几天提醒 */ @@ -56,30 +88,9 @@ public class CrmReceivablePlanDO extends BaseDO { * 提醒日期 */ private LocalDateTime remindTime; - /** - * 客户编号,关联 {@link CrmCustomerDO#getId()} - */ - private Long customerId; - /** - * 合同编号,关联 {@link CrmContractDO#getId()} - */ - private Long contractId; - /** - * 负责人编号,关联 {@link AdminUserRespDTO#getId()} - */ - private Long ownerUserId; - /** - * 显示顺序 - */ - private Integer sort; /** * 备注 */ private String remark; - /** - * 完成状态 - */ - private Boolean finishStatus; - } 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 d1556be3e..f1f3128c9 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 @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.time.LocalDateTime; @@ -26,10 +25,8 @@ import java.util.List; @Mapper public interface CrmContractMapper extends BaseMapperX { - default int updateOwnerUserIdById(Long id, Long ownerUserId) { - return update(new LambdaUpdateWrapper() - .eq(CrmContractDO::getId, id) - .set(CrmContractDO::getOwnerUserId, ownerUserId)); + default CrmContractDO selectByNo(String no) { + return selectOne(CrmContractDO::getNo, no); } default PageResult selectPageByCustomerId(CrmContractPageReqVO pageReqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java new file mode 100644 index 000000000..2932c1db1 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.crm.dal.redis; + +/** + * CRM Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + /** + * 序号的缓存 + * + * KEY 格式:trade_no:{prefix} + * VALUE 数据格式:编号自增 + */ + String NO = "crm:seq_no:"; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java new file mode 100644 index 000000000..7b5913905 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.crm.dal.redis.no; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.module.crm.dal.redis.RedisKeyConstants; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import java.time.Duration; +import java.time.LocalDateTime; + + +/** + * Crm 订单序号的 Redis DAO + * + * @author HUIHUI + */ +@Repository +public class CrmNoRedisDAO { + + /** + * 合同 {@link cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO} + */ + public static final String CONTRACT_NO_PREFIX = "HT"; + + /** + * 还款 {@link cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO} + */ + public static final String RECEIVABLE_PREFIX = "HK"; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 生成序号,使用当前日期,格式为 {PREFIX} + yyyyMMdd + 6 位自增 + * 例如说:QTRK 202109 000001 (没有中间空格) + * + * @param prefix 前缀 + * @return 序号 + */ + public String generate(String prefix) { + // 递增序号 + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN); + String key = RedisKeyConstants.NO + noPrefix; + Long no = stringRedisTemplate.opsForValue().increment(key); + // 设置过期时间 + stringRedisTemplate.expire(key, Duration.ofDays(1L)); + return noPrefix + String.format("%06d", no); + } + +} 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 dcb892349..9f5f603d2 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 @@ -17,6 +17,7 @@ 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; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractProductMapper; +import cn.iocoder.yudao.module.crm.dal.redis.no.CrmNoRedisDAO; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; @@ -69,6 +70,9 @@ public class CrmContractServiceImpl implements CrmContractService { @Resource private CrmContractProductMapper contractProductMapper; + @Resource + private CrmNoRedisDAO noRedisDAO; + @Resource private CrmPermissionService crmPermissionService; @Resource @@ -94,11 +98,14 @@ public class CrmContractServiceImpl implements CrmContractService { List contractProducts = validateContractProducts(createReqVO.getProducts()); // 1.2 校验关联字段 validateRelationDataExists(createReqVO); - // TODO 芋艿:生成 no + // 1.3 生成序号 + String no = noRedisDAO.generate(CrmNoRedisDAO.CONTRACT_NO_PREFIX); + if (contractMapper.selectByNo(no) != null) { + throw exception(CONTRACT_NO_EXISTS); + } // 2.1 插入合同 - CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class); - contract.setNo(System.currentTimeMillis() + ""); // TODO + CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setNo(no); calculateTotalPrice(contract, contractProducts); contractMapper.insert(contract); // 2.2 插入合同关联商品 @@ -247,7 +254,7 @@ public class CrmContractServiceImpl implements CrmContractService { crmPermissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTRACT.getType(), reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 设置负责人 - contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); + contractMapper.updateById(new CrmContractDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId())); // 3. 记录转移日志 LogRecordContext.putVariable("contract", contract); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index db8ea9e0c..55c403404 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -23,7 +23,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; -import org.hibernate.validator.internal.util.stereotypes.Lazy; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -57,6 +57,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { private CrmCustomerService customerService; @Resource private CrmPermissionService permissionService; + @Resource private AdminUserApi adminUserApi; @@ -72,15 +73,16 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { int period = (int) (count + 1); createReqVO.setPeriod(createReqVO.getPeriod() != period ? period : createReqVO.getPeriod()); // 如果期数不对则纠正 - // 2.1 插入 + // 2. 插入还款计划 CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class).setId(null).setFinishStatus(false); receivablePlanMapper.insert(receivablePlan); - // 2.2 创建数据权限 + + // 3. 创建数据权限 permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(createReqVO.getOwnerUserId()) .setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()).setBizId(receivablePlan.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 3. 记录操作日志上下文 + // 4. 记录操作日志上下文 LogRecordContext.putVariable("receivablePlan", receivablePlan); return receivablePlan.getId(); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index d11bb939d..921b714d8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -31,6 +31,7 @@ import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -66,10 +67,12 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { private CrmContractService contractService; @Resource private CrmCustomerService customerService; - @Resource +// @Resource + @Lazy // 延迟加载,避免循环依赖 private CrmReceivablePlanService receivablePlanService; @Resource private CrmPermissionService permissionService; + @Resource private AdminUserApi adminUserApi; @Resource diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java index 0169b0d87..665e98fbe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.crm.util; import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; @@ -18,23 +17,11 @@ public class CrmAuditStatusUtils { * @param bpmResult BPM 审批结果 */ public static Integer convertBpmResultToAuditStatus(Integer bpmResult) { - Assert.isTrue(isEndResult(bpmResult), "BPM 审批结果({}) 转换失败, 流程状态不是最终结果", bpmResult); Integer auditStatus = BpmProcessInstanceResultEnum.APPROVE.getResult().equals(bpmResult) ? CrmAuditStatusEnum.APPROVE.getStatus() : BpmProcessInstanceResultEnum.REJECT.getResult().equals(bpmResult) ? CrmAuditStatusEnum.REJECT.getStatus() - : BpmProcessInstanceResultEnum.CANCEL.getResult(); + : BpmProcessInstanceResultEnum.CANCEL.getResult().equals(bpmResult) ? BpmProcessInstanceResultEnum.CANCEL.getResult() : null; Assert.notNull(auditStatus, "BPM 审批结果({}) 转换失败", bpmResult); return auditStatus; } - /** - * 判断该结果是否处于 End 最终结果 - * - * @param bpmResult BPM 审批结果 - * @return 是否 - */ - public static boolean isEndResult(Integer bpmResult) { - return ObjectUtils.equalsAny(bpmResult, BpmProcessInstanceResultEnum.APPROVE.getResult(), - BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); - } - } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java index f0ba46807..daa5c1614 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java @@ -13,6 +13,6 @@ public interface RedisKeyConstants { * KEY 格式:trade_no:{prefix} * VALUE 数据格式:编号自增 */ - String NO = "seq_no:"; + String NO = "erp:seq_no:"; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index 98fb8e8ff..b6777d207 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -12,7 +12,7 @@ import java.time.LocalDateTime; /** - * 订单序号的 Redis DAO + * Erp 订单序号的 Redis DAO * * @author HUIHUI */ diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java index bfc2a1590..5c47f4de3 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; import java.util.Collection; import java.util.List; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + /** * 字典数据 API 接口 * @@ -40,12 +42,23 @@ public interface DictDataApi { */ DictDataRespDTO parseDictData(String type, String label); + /** + * 获得指定字典类型的字典数据列表 + * + * @param dictType 字典类型 + * @return 字典数据列表 + */ + List getDictDataList(String dictType); + /** * 获得字典数据标签列表 * * @param dictType 字典类型 * @return 字典数据标签列表 */ - List getDictDataLabelList(String dictType); + default List getDictDataLabelList(String dictType) { + List list = getDictDataList(dictType); + return convertList(list, DictDataRespDTO::getLabel); + } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java index f3ddb6927..450512784 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.api.dict; -import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; @@ -9,11 +8,8 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.util.Collection; -import java.util.Collections; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - /** * 字典数据 API 实现类 * @@ -43,12 +39,9 @@ public class DictDataApiImpl implements DictDataApi { } @Override - public List getDictDataLabelList(String dictType) { - List dictDataList = dictDataService.getDictDataListByDictType(dictType); - if (CollUtil.isEmpty(dictDataList)) { - return Collections.emptyList(); - } - return convertList(dictDataList, DictDataDO::getLabel); + public List getDictDataList(String dictType) { + List list = dictDataService.getDictDataListByDictType(dictType); + return BeanUtils.toBean(list, DictDataRespDTO.class); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java index b2f95d69f..b39e0a06d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java @@ -29,7 +29,7 @@ public class AreaController { @GetMapping("/tree") @Operation(summary = "获得地区树") public CommonResult> getAreaTree() { - Area area = AreaUtils.getArea(Area.ID_CHINA); + Area area = AreaUtils.parseArea(Area.ID_CHINA); Assert.notNull(area, "获取不到中国"); return success(BeanUtils.toBean(area.getChildren(), AreaNodeRespVO.class)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/AppAreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/AppAreaController.java index 54b0e87db..759b72c72 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/AppAreaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/ip/AppAreaController.java @@ -26,7 +26,7 @@ public class AppAreaController { @GetMapping("/tree") @Operation(summary = "获得地区树") public CommonResult> getAreaTree() { - Area area = AreaUtils.getArea(Area.ID_CHINA); + Area area = AreaUtils.parseArea(Area.ID_CHINA); Assert.notNull(area, "获取不到中国"); return success(BeanUtils.toBean(area.getChildren(), AppAreaNodeRespVO.class)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java index ce75c9afe..fc2498f1b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java @@ -100,7 +100,7 @@ public interface DictDataService { DictDataDO parseDictData(String dictType, String label); /** - * 获得字典数据列表 + * 获得指定数据类型的字典数据列表 * * @param dictType 字典类型 * @return 字典数据列表 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java index 7982e2302..b15fd506a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java @@ -171,7 +171,9 @@ public class DictDataServiceImpl implements DictDataService { @Override public List getDictDataListByDictType(String dictType) { - return dictDataMapper.selectList(DictDataDO::getDictType, dictType); + List list = dictDataMapper.selectList(DictDataDO::getDictType, dictType); + list.sort(Comparator.comparing(DictDataDO::getSort)); + return list; } } From a8f6a3d324c0914bd7a37a4c69444b395cf0ea9a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 08:18:10 +0800 Subject: [PATCH 35/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=20CRM=20=E7=9B=B8=E5=85=B3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrmCustomerLimitConfigController.java | 19 ++++++--- .../CrmCustomerLimitConfigConvert.java | 42 ------------------- .../contract/CrmContractServiceImpl.java | 4 +- .../listener/CrmContractResultListener.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 14 ++++--- .../CrmReceivablePlanServiceImpl.java | 4 +- 6 files changed, 26 insertions(+), 59 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerLimitConfigConvert.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java index 95f4ccd8f..ea84c9a5e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java @@ -3,10 +3,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigRespVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO; -import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerLimitConfigConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerLimitConfigService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -71,11 +72,14 @@ public class CrmCustomerLimitConfigController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:customer-limit-config:query')") public CommonResult getCustomerLimitConfig(@RequestParam("id") Long id) { - CrmCustomerLimitConfigDO customerLimitConfig = customerLimitConfigService.getCustomerLimitConfig(id); + CrmCustomerLimitConfigDO limitConfig = customerLimitConfigService.getCustomerLimitConfig(id); // 拼接数据 - Map userMap = adminUserApi.getUserMap(customerLimitConfig.getUserIds()); - Map deptMap = deptApi.getDeptMap(customerLimitConfig.getDeptIds()); - return success(CrmCustomerLimitConfigConvert.INSTANCE.convert(customerLimitConfig, userMap, deptMap)); + Map userMap = adminUserApi.getUserMap(limitConfig.getUserIds()); + Map deptMap = deptApi.getDeptMap(limitConfig.getDeptIds()); + return success(BeanUtils.toBean(limitConfig, CrmCustomerLimitConfigRespVO.class, configVO -> { + configVO.setUsers(CollectionUtils.convertList(configVO.getUserIds(), userMap::get)); + configVO.setDepts(CollectionUtils.convertList(configVO.getDeptIds(), deptMap::get)); + })); } @GetMapping("/page") @@ -91,7 +95,10 @@ public class CrmCustomerLimitConfigController { convertSetByFlatMap(pageResult.getList(), CrmCustomerLimitConfigDO::getUserIds, Collection::stream)); Map deptMap = deptApi.getDeptMap( convertSetByFlatMap(pageResult.getList(), CrmCustomerLimitConfigDO::getDeptIds, Collection::stream)); - return success(CrmCustomerLimitConfigConvert.INSTANCE.convertPage(pageResult, userMap, deptMap)); + return success(BeanUtils.toBean(pageResult, CrmCustomerLimitConfigRespVO.class, configVO -> { + configVO.setUsers(CollectionUtils.convertList(configVO.getUserIds(), userMap::get)); + configVO.setDepts(CollectionUtils.convertList(configVO.getDeptIds(), deptMap::get)); + })); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerLimitConfigConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerLimitConfigConvert.java deleted file mode 100644 index 81550b378..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerLimitConfigConvert.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.customer; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigRespVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; - -/** - * 客户限制配置 Convert - * - * @author Wanwan - */ -@Mapper -public interface CrmCustomerLimitConfigConvert { - - CrmCustomerLimitConfigConvert INSTANCE = Mappers.getMapper(CrmCustomerLimitConfigConvert.class); - - default PageResult convertPage( - PageResult pageResult, - Map userMap, Map deptMap) { - List list = CollectionUtils.convertList(pageResult.getList(), - limitConfig -> convert(limitConfig, userMap, deptMap)); - return new PageResult<>(list, pageResult.getTotal()); - } - - default CrmCustomerLimitConfigRespVO convert(CrmCustomerLimitConfigDO limitConfig, - Map userMap, Map deptMap) { - CrmCustomerLimitConfigRespVO limitConfigVO = BeanUtils.toBean(limitConfig, CrmCustomerLimitConfigRespVO.class); - limitConfigVO.setUsers(CollectionUtils.convertList(limitConfigVO.getUserIds(), userMap::get)); - limitConfigVO.setDepts(CollectionUtils.convertList(limitConfigVO.getDeptIds(), deptMap::get)); - return limitConfigVO; - } - -} 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 9f5f603d2..f09f1c0a7 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 @@ -63,7 +63,7 @@ public class CrmContractServiceImpl implements CrmContractService { /** * BPM 合同审批流程标识 */ - public static final String CONTRACT_APPROVE = "contract-approve"; + public static final String BPM_PROCESS_DEFINITION_KEY = "crm-contract-audit"; @Resource private CrmContractMapper contractMapper; @@ -288,7 +288,7 @@ public class CrmContractServiceImpl implements CrmContractService { // 2. 创建合同审批流程实例 String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() - .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); + .setProcessDefinitionKey(BPM_PROCESS_DEFINITION_KEY).setBusinessKey(String.valueOf(id))); // 3. 更新合同工作流编号 contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index b3f4c3960..256259bdf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -20,7 +20,7 @@ public class CrmContractResultListener extends BpmProcessInstanceResultEventList @Override public String getProcessDefinitionKey() { - return CrmContractServiceImpl.CONTRACT_APPROVE; + return CrmContractServiceImpl.BPM_PROCESS_DEFINITION_KEY; } @Override 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 ffc328eae..9ad36f60b 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 @@ -240,9 +240,9 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#customer.id}}", success = CRM_CUSTOMER_CREATE_SUCCESS) - public Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId) { + public Long createCustomer(CrmCustomerCreateReqBO createReqBO, Long userId) { // 1. 插入客户 - CrmCustomerDO customer = BeanUtils.toBean(customerCreateReq, CrmCustomerDO.class).setOwnerUserId(userId); + CrmCustomerDO customer = initCustomer(createReqBO, userId); customerMapper.insert(customer); // 2. 创建数据权限 @@ -419,12 +419,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { if (updateOwnerUserIncr == 0) { throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL); } - // 2. 删除负责人数据权限 + + // 2. 联系人的负责人,也要设置为 null。因为:因为领取后,负责人也要关联过来,这块和 receiveCustomer 是对应的 + contactService.updateOwnerUserIdByCustomerId(customer.getId(), null); + + // 3. 删除负责人数据权限 + // 注意:需要放在 contactService 后面,不然【客户】数据权限已经被删除,无法操作! permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), CrmPermissionLevelEnum.OWNER.getLevel()); - - // 3. 联系人的负责人,也要设置为 null。因为:因为领取后,负责人也要关联过来,这块和 receiveCustomer 是对应的 - contactService.updateOwnerUserIdByCustomerId(customer.getId(), null); } @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_RECEIVE_SUB_TYPE, bizNo = "{{#customer.id}}", diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index 55c403404..35748d85d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -71,10 +71,10 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { // 1.2 查验关联合同回款数量 Long count = receivableService.getReceivableCountByContractId(createReqVO.getContractId()); int period = (int) (count + 1); - createReqVO.setPeriod(createReqVO.getPeriod() != period ? period : createReqVO.getPeriod()); // 如果期数不对则纠正 // 2. 插入还款计划 - CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class).setId(null).setFinishStatus(false); + CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class) + .setPeriod(period).setFinishStatus(false); receivablePlanMapper.insert(receivablePlan); // 3. 创建数据权限 From 3f8fa6b1bcdb45fff1a25d82d6ecb56a5017b399 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 11:14:30 +0800 Subject: [PATCH 36/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E7=AE=80?= =?UTF-8?q?=E5=8C=96=20CRM=20=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../permission/CrmPermissionLevelEnum.java | 6 ++- .../permission/CrmPermissionRoleCodeEnum.java | 27 ----------- .../dal/mysql/business/CrmBusinessMapper.java | 6 +-- .../crm/dal/mysql/clue/CrmClueMapper.java | 8 ++-- .../dal/mysql/contact/CrmContactMapper.java | 6 +-- .../dal/mysql/contract/CrmContractMapper.java | 10 ++-- .../dal/mysql/customer/CrmCustomerMapper.java | 12 ++--- .../mysql/receivable/CrmReceivableMapper.java | 15 ++---- .../receivable/CrmReceivablePlanMapper.java | 8 ++-- .../core/aop/CrmPermissionAspect.java | 2 +- .../core/util/CrmPermissionUtils.java | 40 ---------------- .../permission/CrmPermissionServiceImpl.java | 2 +- ...pperUtils.java => CrmPermissionUtils.java} | 47 ++++++++----------- .../system/enums/permission/RoleCodeEnum.java | 1 + 14 files changed, 56 insertions(+), 134 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/{CrmQueryWrapperUtils.java => CrmPermissionUtils.java} (78%) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java index 56b0366aa..7b44fe962 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java @@ -10,6 +10,8 @@ import java.util.Arrays; /** * CRM 数据权限级别枚举 * + * OWNER > WRITE > READ + * * @author HUIHUI */ @Getter @@ -17,8 +19,8 @@ import java.util.Arrays; public enum CrmPermissionLevelEnum implements IntArrayValuable { OWNER(1, "负责人"), - READ(2, "读"), - WRITE(3, "写"); + READ(2, "只读"), + WRITE(3, "读写"); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmPermissionLevelEnum::getLevel).toArray(); diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java deleted file mode 100644 index c9a51057b..000000000 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.crm.enums.permission; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * Crm 数据权限角色枚举 - * - * @author HUIHUI - */ -@Getter -@AllArgsConstructor -public enum CrmPermissionRoleCodeEnum { - - CRM_ADMIN("crm_admin", "CRM 管理员"); - - /** - * 角色标识 - */ - private String code; - /** - * 角色名称 - */ - private String name; - -} - 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 4e93c5eb3..6b2fd84ee 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 @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -45,7 +45,7 @@ public interface CrmBusinessMapper extends BaseMapperX { default PageResult selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 query.selectAll(CrmBusinessDO.class) @@ -57,7 +57,7 @@ public interface CrmBusinessMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); + 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); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index 9d1cae206..d0665c604 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; @@ -24,7 +24,7 @@ public interface CrmClueMapper extends BaseMapperX { default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); // 拼接自身的查询条件 query.selectAll(CrmClueDO.class) @@ -43,7 +43,7 @@ public interface CrmClueMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), ids, userId); + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), ids, userId); query.selectAll(CrmClueDO.class).in(CrmClueDO::getId, ids).orderByDesc(CrmClueDO::getId); // 拼接自身的查询条件 return selectJoinList(CrmClueDO.class, query); @@ -52,7 +52,7 @@ public interface CrmClueMapper extends BaseMapperX { default Long selectCountByFollow(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 未跟进 + 未转化 query.eq(CrmClueDO::getFollowUpStatus, false) 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 4cc7a97b4..06404b7ab 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 @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -55,7 +55,7 @@ public interface CrmContactMapper extends BaseMapperX { default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 query.selectAll(CrmContactDO.class) @@ -72,7 +72,7 @@ public interface CrmContactMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, ownerUserId); + 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); } 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 f1f3128c9..7993224ca 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 @@ -10,7 +10,7 @@ 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; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import org.apache.ibatis.annotations.Mapper; import java.time.LocalDateTime; @@ -42,7 +42,7 @@ public interface CrmContractMapper extends BaseMapperX { default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 query.selectAll(CrmContractDO.class) @@ -71,7 +71,7 @@ public interface CrmContractMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 构建数据权限连表条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), ids, userId); + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), ids, userId); // 拼接自身的查询条件 query.selectAll(CrmContractDO.class).in(CrmContractDO::getId, ids).orderByDesc(CrmContractDO::getId); return selectJoinList(CrmContractDO.class, query); @@ -88,7 +88,7 @@ public interface CrmContractMapper extends BaseMapperX { default Long selectCheckContractCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), + 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()); @@ -98,7 +98,7 @@ public interface CrmContractMapper extends BaseMapperX { default Long selectEndContractCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 即将到期 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index f9495323a..615783950 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -52,7 +52,7 @@ public interface CrmCustomerMapper extends BaseMapperX { default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType(), pageReqVO.getPool()); // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class) @@ -84,7 +84,7 @@ public interface CrmCustomerMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, ownerUserId); + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, ownerUserId); // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class).in(CrmCustomerDO::getId, ids).orderByDesc(CrmCustomerDO::getId); return selectJoinList(CrmCustomerDO.class, query); @@ -113,7 +113,7 @@ public interface CrmCustomerMapper extends BaseMapperX { Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType(), null); // 未锁定 + 未成交 @@ -167,7 +167,7 @@ public interface CrmCustomerMapper extends BaseMapperX { default Long selectCountByTodayContact(Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 今天需联系 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); @@ -179,7 +179,7 @@ public interface CrmCustomerMapper extends BaseMapperX { default Long selectCountByFollow(Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 未跟进 query.eq(CrmClueDO::getFollowUpStatus, false); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index eb525d346..a591131d5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -10,8 +10,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; @@ -25,12 +24,6 @@ import java.util.List; @Mapper public interface CrmReceivableMapper extends BaseMapperX { - default int updateOwnerUserIdById(Long id, Long ownerUserId) { - return update(new LambdaUpdateWrapper() - .eq(CrmReceivableDO::getId, id) - .set(CrmReceivableDO::getOwnerUserId, ownerUserId)); - } - default PageResult selectPageByCustomerId(CrmReceivablePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 @@ -42,7 +35,7 @@ public interface CrmReceivableMapper extends BaseMapperX { default PageResult selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 query.selectAll(CrmReceivableDO.class) @@ -56,7 +49,7 @@ public interface CrmReceivableMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), ids, userId); + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), ids, userId); // 拼接自身的查询条件 query.selectAll(CrmReceivableDO.class).in(CrmReceivableDO::getId, ids).orderByDesc(CrmReceivableDO::getId); return selectJoinList(CrmReceivableDO.class, query); @@ -65,7 +58,7 @@ public interface CrmReceivableMapper extends BaseMapperX { default Long selectCheckReceivablesCount(Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // 未提交 or 审核不通过 query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index 9862048f5..4fac66a77 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import org.apache.ibatis.annotations.Mapper; import java.time.LocalDateTime; @@ -34,7 +34,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 query.selectAll(CrmReceivablePlanDO.class) @@ -64,7 +64,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId); + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId); // 拼接自身的查询条件 query.selectAll(CrmReceivablePlanDO.class).in(CrmReceivablePlanDO::getId, ids).orderByDesc(CrmReceivablePlanDO::getId); return selectJoinList(CrmReceivablePlanDO.class, query); @@ -73,7 +73,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), + CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); // TODO: @dhb52 需要配置 提前提醒天数 int REMIND_DAYS = 20; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java index 14e7c71fe..292a4d664 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; +import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java deleted file mode 100644 index 43bb729b6..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.crm.framework.permission.core.util; - -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; -import cn.iocoder.yudao.module.system.api.permission.PermissionApi; - -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -/** - * 数据权限工具类 - * - * @author HUIHUI - */ -public class CrmPermissionUtils { - - /** - * 校验用户是否是 CRM 管理员 - * - * @return 是/否 - */ - public static boolean isCrmAdmin() { - return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); - } - - /** - * 静态内部类实现单例获取 - * - * @author HUIHUI - */ - private static class SingletonManager { - - private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); - - public static PermissionApi getPermissionApi() { - return PERMISSION_API; - } - - } - -} 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 ba3e50c6d..3c1930202 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 @@ -9,7 +9,7 @@ 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.framework.permission.core.util.CrmPermissionUtils; +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.system.api.user.AdminUserApi; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java similarity index 78% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java index cfd2f8c1b..587e9ab56 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java @@ -7,9 +7,10 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties; import com.github.yulichang.wrapper.MPJLambdaWrapper; @@ -18,13 +19,24 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** - * CRM 查询工具类 + * 数据权限工具类 * * @author HUIHUI */ -public class CrmQueryWrapperUtils { +public class CrmPermissionUtils { + + /** + * 校验用户是否是 CRM 管理员 + * + * @return 是/否 + */ + public static boolean isCrmAdmin() { + PermissionApi permissionApi = SpringUtil.getBean(PermissionApi.class); + return permissionApi.hasAnyRoles(getLoginUserId(), RoleCodeEnum.CRM_ADMIN.getCode()); + } /** * 构造 CRM 数据类型数据分页查询条件 @@ -38,7 +50,8 @@ public class CrmQueryWrapperUtils { */ public static , S> void appendPermissionCondition(T query, Integer bizType, SFunction bizId, Long userId, Integer sceneType, Boolean pool) { - final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; + MybatisPlusJoinProperties mybatisPlusJoinProperties = SpringUtil.getBean(MybatisPlusJoinProperties.class); + final String ownerUserIdField = mybatisPlusJoinProperties.getTableAlias() + ".owner_user_id"; // 1. 构建数据权限连表条件 if (!CrmPermissionUtils.isCrmAdmin() && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) @@ -56,7 +69,8 @@ public class CrmQueryWrapperUtils { } // 2.3 场景三:下属负责的数据 if (CrmSceneTypeEnum.isSubordinate(sceneType)) { - List subordinateUsers = SingletonManager.getAdminUserApi().getUserListBySubordinate(userId); + AdminUserApi adminUserApi = SpringUtil.getBean(AdminUserApi.class); + List subordinateUsers = adminUserApi.getUserListBySubordinate(userId); if (CollUtil.isEmpty(subordinateUsers)) { query.eq(ownerUserIdField, -1); // 不返回任何结果 } else { @@ -81,7 +95,7 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 */ public static > void appendPermissionCondition(T query, Integer bizType, Collection bizIds, Long userId) { - if (CrmPermissionUtils.isCrmAdmin()) {// 管理员不需要数据权限 + if (isCrmAdmin()) {// 管理员不需要数据权限 return; } query.innerJoin(CrmPermissionDO.class, on -> @@ -89,25 +103,4 @@ public class CrmQueryWrapperUtils { .eq(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } - /** - * 静态内部类实现单例获取 - * - * @author HUIHUI - */ - private static class SingletonManager { - - private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); - - private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); - - public static AdminUserApi getAdminUserApi() { - return ADMIN_USER_API; - } - - public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() { - return MYBATIS_PLUS_JOIN_PROPERTIES; - } - - } - } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java index b13b3b71a..cdf9a001d 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java @@ -13,6 +13,7 @@ public enum RoleCodeEnum { SUPER_ADMIN("super_admin", "超级管理员"), TENANT_ADMIN("tenant_admin", "租户管理员"), + CRM_ADMIN("crm_admin", "CRM 管理员"); // CRM 系统专用 ; /** From 5dc1dbb3b21707ee14c19d4ea3667ee1d0bebffe Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 24 Feb 2024 11:40:58 +0800 Subject: [PATCH 37/54] =?UTF-8?q?=E5=AE=8C=E5=96=84=20Excel=20=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E7=89=88=E4=B8=8B=E6=8B=89=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/core/enums/ExcelColumn.java | 25 +++++ .../core/handler/SelectSheetWriteHandler.java | 106 ++++++++---------- .../framework/excel/core/util/ExcelUtils.java | 5 +- .../admin/customer/CrmCustomerController.java | 13 ++- .../customer/CrmCustomerServiceImpl.java | 5 +- .../CrmReceivablePlanServiceImpl.java | 5 +- .../receivable/CrmReceivableServiceImpl.java | 2 +- .../infra/enums/ErrorCodeConstants.java | 26 ++--- 8 files changed, 102 insertions(+), 85 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/enums/ExcelColumn.java 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 new file mode 100644 index 000000000..4330b820b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/enums/ExcelColumn.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.framework.excel.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Excel 列名枚举 + * 默认枚举 26 列列名如果有需求更多的列名请自行补充 + * + * @author HUIHUI + */ +@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), + Z(25); + + /** + * 列索引 + */ + private final int colNum; + +} 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 db3fc2776..6b6e70320 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 @@ -1,7 +1,9 @@ package cn.iocoder.yudao.framework.excel.core.handler; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.excel.core.enums.ExcelColumn; import com.alibaba.excel.write.handler.SheetWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; @@ -11,6 +13,8 @@ import org.apache.poi.ss.util.CellRangeAddressList; import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * 基于固定 sheet 实现下拉框 @@ -20,18 +24,20 @@ import java.util.List; public class SelectSheetWriteHandler implements SheetWriteHandler { 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; // 下拉列需要创建下拉框的行数,默认两千行如需更多请自行调整 + private final List>> selectMap; - // TODO @puhui999:key 不使用 int 值么?感觉不是很优雅哈。 - private final List>> selectMap; - - private static final char[] ALPHABET = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; - - public SelectSheetWriteHandler(List>> selectMap) { + public SelectSheetWriteHandler(List>> selectMap) { if (CollUtil.isEmpty(selectMap)) { this.selectMap = null; return; } + // 校验一下 key 是否唯一 + Map nameCounts = selectMap.stream() + .collect(Collectors.groupingBy(item -> item.getKey().name(), Collectors.counting())); + Assert.isFalse(nameCounts.entrySet().stream().allMatch(entry -> entry.getValue() > 1), "下拉数据 key 重复请排查!!!"); + selectMap.sort(Comparator.comparing(item -> item.getValue().size())); // 升序不然创建下拉会报错 this.selectMap = selectMap; } @@ -41,16 +47,14 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { if (CollUtil.isEmpty(selectMap)) { return; } - // 需要设置下拉框的 sheet 页 - Sheet currentSheet = writeSheetHolder.getSheet(); - DataValidationHelper helper = currentSheet.getDataValidationHelper(); - Workbook workbook = writeWorkbookHolder.getWorkbook(); - // 数据字典的 sheet 页 + // 1.1 获取相应操作对象 + DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper(); // 需要设置下拉框的 sheet 页的数据验证助手 + Workbook workbook = writeWorkbookHolder.getWorkbook(); // 获得工作簿 + + // 1.2 创建数据字典的 sheet 页 Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME); - for (KeyValue> keyValue : selectMap) { - // 设置下拉单元格的首行、末行、首列、末列 - CellRangeAddressList rangeAddressList = new CellRangeAddressList(1, 65533, keyValue.getKey(), keyValue.getKey()); + for (KeyValue> keyValue : selectMap) { int rowLen = keyValue.getValue().size(); // 设置字典 sheet 页的值 每一列一个字典项 for (int i = 0; i < rowLen; i++) { @@ -58,58 +62,42 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { if (row == null) { row = dictSheet.createRow(i); } - row.createCell(keyValue.getKey()).setCellValue(keyValue.getValue().get(i)); + row.createCell(keyValue.getKey().getColNum()).setCellValue(keyValue.getValue().get(i)); } - - // TODO @puhui999:下面 1. 2.1 2.2 2.3 我是按照已经理解的,调整了下格式;这样可读性更好;在 52 到 62 行,你可以看看,是不是也弄下序号; - // 1. 创建可被其他单元格引用的名称 - Name name = workbook.createName(); - // TODO @puhui999:下面的 excelColumn 和 refers 两行,是不是可以封装成一个方法,替代 getExcelColumn; - String excelColumn = getExcelColumn(keyValue.getKey()); - String refers = DICT_SHEET_NAME + "!$" + excelColumn + "$1:$" + excelColumn + "$" + rowLen; // 下拉框数据来源 eg:字典sheet!$B1:$B2 - name.setNameName("dict" + keyValue.getKey()); // 设置名称的名字 - name.setRefersToFormula(refers); // 设置公式 - - // 2.1 设置约束 - DataValidationConstraint constraint = helper.createFormulaListConstraint("dict" + keyValue.getKey()); // 设置引用约束 - DataValidation validation = helper.createValidation(constraint, rangeAddressList); - if (validation instanceof HSSFDataValidation) { - validation.setSuppressDropDownArrow(false); - } else { - validation.setSuppressDropDownArrow(true); - validation.setShowErrorBox(true); - } - // 2.2 阻止输入非下拉框的值 - validation.setErrorStyle(DataValidation.ErrorStyle.STOP); - validation.createErrorBox("提示", "此值不存在于下拉选择中!"); - // 2.3 添加下拉框约束 - writeSheetHolder.getSheet().addValidationData(validation); + // 1.3 设置单元格下拉选择 + setColSelect(writeSheetHolder, workbook, helper, keyValue); } } /** - * 将数字列转化成为字母列 - * - * @param num 数字 - * @return 字母 + * 设置单元格下拉选择 */ - // TODO @puhui999:这个是必须字母列哇?还是数字其实也可以哈?主要想看看,怎么能把这个逻辑,进一步简化 - private String getExcelColumn(int num) { - String column; - int len = ALPHABET.length - 1; - int first = num / len; - int second = num % len; - if (num <= len) { - column = ALPHABET[num] + ""; + private static void setColSelect(WriteSheetHolder writeSheetHolder, Workbook workbook, DataValidationHelper helper, + KeyValue> keyValue) { + // 1.1 创建可被其他单元格引用的名称 + Name name = workbook.createName(); + String excelColumn = keyValue.getKey().name(); + // 1.2 下拉框数据来源 eg:字典sheet!$B1:$B2 + 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()); // 设置引用约束 + // 设置下拉单元格的首行、末行、首列、末列 + CellRangeAddressList rangeAddressList = new CellRangeAddressList(FIRST_ROW, LAST_ROW, + keyValue.getKey().getColNum(), keyValue.getKey().getColNum()); + DataValidation validation = helper.createValidation(constraint, rangeAddressList); + if (validation instanceof HSSFDataValidation) { + validation.setSuppressDropDownArrow(false); } else { - column = ALPHABET[first - 1] + ""; - if (second == 0) { - column = column + ALPHABET[len]; - } else { - column = column + ALPHABET[second - 1]; - } + validation.setSuppressDropDownArrow(true); + validation.setShowErrorBox(true); } - return column; + // 2.2 阻止输入非下拉框的值 + validation.setErrorStyle(DataValidation.ErrorStyle.STOP); + validation.createErrorBox("提示", "此值不存在于下拉选择中!"); + // 2.3 添加下拉框约束 + writeSheetHolder.getSheet().addValidationData(validation); } } \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index ee4ba25c7..81d9a8a97 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.excel.core.util; import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.excel.core.enums.ExcelColumn; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.converters.longconverter.LongStringConverter; @@ -44,11 +45,11 @@ public class ExcelUtils { * @param sheetName Excel sheet 名 * @param head Excel head 头 * @param data 数据列表哦 - * @param selectMap 下拉选择数据 Map + * @param selectMap 下拉选择数据 Map<下拉所对应的列表名,下拉数据> * @throws IOException 写入失败的情况 */ public static void write(HttpServletResponse response, String filename, String sheetName, - Class head, List data, List>> selectMap) throws IOException { + Class head, List data, List>> selectMap) throws IOException { // 输出 Excel EasyExcel.write(response.getOutputStream(), head) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 54327c24c..e784447b2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 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.enums.ExcelColumn; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; @@ -268,21 +269,21 @@ public class CrmCustomerController { ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list, builderSelectMap()); } - private List>> builderSelectMap() { - List>> selectMap = new ArrayList<>(); + private List>> builderSelectMap() { + List>> selectMap = new ArrayList<>(); // 获取地区下拉数据 // TODO @puhui999:嘿嘿,这里改成省份、城市、区域,三个选项,难度大么? Area area = AreaUtils.parseArea(Area.ID_CHINA); - selectMap.add(new KeyValue<>(6, AreaUtils.getAreaNodePathList(area.getChildren()))); + selectMap.add(new KeyValue<>(ExcelColumn.G, AreaUtils.getAreaNodePathList(area.getChildren()))); // 获取客户所属行业 List customerIndustries = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_INDUSTRY); - selectMap.add(new KeyValue<>(8, customerIndustries)); + selectMap.add(new KeyValue<>(ExcelColumn.I, customerIndustries)); // 获取客户等级 List customerLevels = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_LEVEL); - selectMap.add(new KeyValue<>(9, customerLevels)); + selectMap.add(new KeyValue<>(ExcelColumn.J, customerLevels)); // 获取客户来源 List customerSources = dictDataApi.getDictDataLabelList(CRM_CUSTOMER_SOURCE); - selectMap.add(new KeyValue<>(10, customerSources)); + selectMap.add(new KeyValue<>(ExcelColumn.K, customerSources)); return selectMap; } 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 ffc328eae..ab8364373 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 @@ -41,6 +41,7 @@ import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; @@ -203,7 +204,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 2.1 数据权限转移 permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CUSTOMER.getType(), - reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); // 2.2 转移后重新设置负责人 customerMapper.updateById(new CrmCustomerDO().setId(reqVO.getId()) .setOwnerUserId(reqVO.getNewOwnerUserId()).setOwnerTime(LocalDateTime.now())); @@ -260,6 +261,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { 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/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index 55c403404..11cc291b7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -70,11 +70,10 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { validateRelationDataExists(createReqVO); // 1.2 查验关联合同回款数量 Long count = receivableService.getReceivableCountByContractId(createReqVO.getContractId()); - int period = (int) (count + 1); - createReqVO.setPeriod(createReqVO.getPeriod() != period ? period : createReqVO.getPeriod()); // 如果期数不对则纠正 // 2. 插入还款计划 - CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class).setId(null).setFinishStatus(false); + CrmReceivablePlanDO receivablePlan = BeanUtils.toBean(createReqVO, CrmReceivablePlanDO.class).setId(null) + .setPeriod((int) (count + 1)).setFinishStatus(false); receivablePlanMapper.insert(receivablePlan); // 3. 创建数据权限 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index 921b714d8..fb807c699 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -67,7 +67,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { private CrmContractService contractService; @Resource private CrmCustomerService customerService; -// @Resource + @Resource @Lazy // 延迟加载,避免循环依赖 private CrmReceivablePlanService receivablePlanService; @Resource diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index 471950017..19aa4e718 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -33,19 +33,19 @@ public interface ErrorCodeConstants { ErrorCode FILE_IS_EMPTY = new ErrorCode(1_001_003_002, "文件为空"); // ========== 代码生成器 1-001-004-000 ========== - ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1_003_001_000, "表定义已经存在"); - ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1_003_001_001, "导入的表不存在"); - ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1_003_001_002, "导入的字段不存在"); - ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_004, "表定义不存在"); - ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_005, "字段义不存在"); - ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1_003_001_006, "同步的字段不存在"); - ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_003_001_007, "同步失败,不存在改变"); - ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_003_001_008, "数据库的表注释未填写"); - ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写"); - ErrorCode CODEGEN_MASTER_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_010, "主表(id={})定义不存在,请检查"); - ErrorCode CODEGEN_SUB_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_011, "子表的字段(id={})不存在,请检查"); - ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE = new ErrorCode(1_003_001_012, "主表生成代码失败,原因:它没有子表"); - ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_COLUMN = new ErrorCode(1_003_001_013, "主表生成代码失败,原因:它的子表({})没有字段"); + ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1_001_004_002, "表定义已经存在"); + ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1_001_004_001, "导入的表不存在"); + ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1_001_004_002, "导入的字段不存在"); + ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1_001_004_004, "表定义不存在"); + ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1_001_004_005, "字段义不存在"); + ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1_001_004_006, "同步的字段不存在"); + ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_001_004_007, "同步失败,不存在改变"); + ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_001_004_008, "数据库的表注释未填写"); + ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_001_004_009, "数据库的表字段({})注释未填写"); + ErrorCode CODEGEN_MASTER_TABLE_NOT_EXISTS = new ErrorCode(1_001_004_010, "主表(id={})定义不存在,请检查"); + ErrorCode CODEGEN_SUB_COLUMN_NOT_EXISTS = new ErrorCode(1_001_004_011, "子表的字段(id={})不存在,请检查"); + ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE = new ErrorCode(1_001_004_012, "主表生成代码失败,原因:它没有子表"); + ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_COLUMN = new ErrorCode(1_001_004_013, "主表生成代码失败,原因:它的子表({})没有字段"); // ========== 文件配置 1-001-006-000 ========== ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在"); From 29f1eb2c184bf7485734d8f869a236bab337fe25 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 15:46:57 +0800 Subject: [PATCH 38/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20CRM=20=E8=B7=9F=E8=BF=9B=E8=AE=B0=E5=BD=95=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/business/CrmBusinessController.java | 9 ----- .../admin/contact/CrmContactController.java | 9 ----- .../admin/contract/CrmContractController.java | 4 +-- .../followup/CrmFollowUpRecordController.java | 35 +++++++++++++------ .../followup/vo/CrmFollowUpRecordRespVO.java | 15 ++++++-- .../dal/mysql/business/CrmBusinessMapper.java | 10 ------ .../dal/mysql/contact/CrmContactMapper.java | 8 ----- .../service/business/CrmBusinessService.java | 13 ++++--- .../business/CrmBusinessServiceImpl.java | 8 ----- .../service/contact/CrmContactService.java | 9 ----- .../contact/CrmContactServiceImpl.java | 8 ----- .../CrmFollowUpRecordServiceImpl.java | 6 ++-- 12 files changed, 50 insertions(+), 84 deletions(-) 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 ec1b35db4..505c0ec46 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 6c27fbb01..77c443f71 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')") 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 147c598d6..7bcd98b3a 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 @@ -187,8 +187,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 设置客户信息 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 735f2e887..64026f15d 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 83bfd9edc..1ce10b73e 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/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 6b2fd84ee..4718a8d7a 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/CrmContactMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java index 06404b7ab..4a77665ad 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/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 63ef761a7..ab7982024 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 11b6193fc..e709b6547 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/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index 822bf095d..23c29d3bc 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 651da773f..d8e356124 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/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index ab9c5df5b..31c62d32a 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())) { From b6098cff83184edb23da95a7325263ce3bbd771d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 16:08:07 +0800 Subject: [PATCH 39/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=95=86?= =?UTF-8?q?=E6=9C=BA=E6=8E=A5=E5=85=A5=E5=90=88=E5=90=8C=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contract/CrmContractController.java | 8 ++++++++ .../crm/dal/mysql/contract/CrmContractMapper.java | 10 ++++++++++ .../crm/service/contract/CrmContractService.java | 13 ++++++++++++- .../service/contract/CrmContractServiceImpl.java | 6 ++++++ 4 files changed, 36 insertions(+), 1 deletion(-) 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 7bcd98b3a..a3c9a70fb 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 @@ -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')") 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 7993224ca..4acbd03ab 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 @@ -39,6 +39,16 @@ public interface CrmContractMapper extends BaseMapperX { .orderByDesc(CrmContractDO::getId)); } + 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) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 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 cbd9cbbe7..77c50f9a6 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 @@ -4,6 +4,7 @@ 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.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); + /** * 查询属于某个联系人的合同数量 * 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 f09f1c0a7..45ad6b53d 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 @@ -341,6 +341,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); From 0b0830f445f7aeca1977954e0439e69a170aebed Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 16:51:16 +0800 Subject: [PATCH 40/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=90=88=E5=90=8C=E9=85=8D=E7=BD=AE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 6 ++ .../contract/CrmContractConfigController.java | 44 +++++++++++++++ .../admin/contract/CrmContractController.java | 8 +-- .../vo/config/CrmContractConfigRespVO.java | 16 ++++++ .../vo/config/CrmContractConfigSaveReqVO.java | 33 +++++++++++ .../{ => contract}/CrmContractPageReqVO.java | 2 +- .../vo/{ => contract}/CrmContractRespVO.java | 2 +- .../{ => contract}/CrmContractSaveReqVO.java | 2 +- .../CrmContractTransferReqVO.java | 2 +- .../permission/CrmPermissionConvert.java | 1 + .../contract/CrmContractConfigDO.java | 33 +++++++++++ .../contract/CrmContractConfigMapper.java | 20 +++++++ .../dal/mysql/contract/CrmContractMapper.java | 2 +- .../contract/CrmContractConfigService.java | 28 ++++++++++ .../CrmContractConfigServiceImpl.java | 56 +++++++++++++++++++ .../service/contract/CrmContractService.java | 6 +- .../contract/CrmContractServiceImpl.java | 6 +- .../CrmCustomerPoolConfigServiceImpl.java | 15 +---- 18 files changed, 255 insertions(+), 27 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractConfigController.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigRespVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/config/CrmContractConfigSaveReqVO.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/{ => contract}/CrmContractPageReqVO.java (99%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/{ => contract}/CrmContractRespVO.java (99%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/{ => contract}/CrmContractSaveReqVO.java (99%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/{ => contract}/CrmContractTransferReqVO.java (98%) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java 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 65bdc1b89..c2c835b7f 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/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 000000000..a97c3bfd6 --- /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 a3c9a70fb..05560318d 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; 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 000000000..c39cf9269 --- /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 000000000..7ecd650e3 --- /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 c61a64ccf..74f8008b8 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 887bdd80a..8f5469eb1 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 322127f42..47491eef4 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 88227c560..4b8245c40 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/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java index f51544cae..6e6fae85a 100644 --- 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 @@ -20,6 +20,7 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; +// TODO @芋艿:要干掉 /** * Crm 数据权限 Convert * 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 000000000..ab0c2d28e --- /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/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 000000000..64e6f918b --- /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 4acbd03ab..047302fe8 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,7 @@ 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.CrmContractDO; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 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 000000000..79471aaf9 --- /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 000000000..c9379dcec --- /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 77c50f9a6..4bf73f5c4 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,9 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.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; 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 45ad6b53d..28d6f8969 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,9 @@ 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.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; 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 303a758d2..9099b1954 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); From 53ebd39c73783018faf09723b1e4ea68caa432ef Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 17:55:40 +0800 Subject: [PATCH 41/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=BE=85?= =?UTF-8?q?=E5=8A=9E=E4=BA=8B=E9=A1=B9=EF=BC=88=E6=8E=A5=E5=85=A5=E5=90=88?= =?UTF-8?q?=E5=90=8C=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contract/CrmContractController.java | 14 ++++---- .../dal/mysql/contract/CrmContractMapper.java | 21 ++++++------ .../service/contract/CrmContractService.java | 6 ++-- .../contract/CrmContractServiceImpl.java | 32 +++++++++++++------ 4 files changed, 41 insertions(+), 32 deletions(-) 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 05560318d..9cce6c0d9 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 @@ -215,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())); } } 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 047302fe8..e06afb257 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 @@ -6,6 +6,7 @@ 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.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; @@ -49,7 +50,7 @@ public interface CrmContractMapper extends BaseMapperX { .orderByDesc(CrmContractDO::getId)); } - default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { + default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId, CrmContractConfigDO config) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), @@ -67,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); @@ -95,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(), @@ -113,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/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 4bf73f5c4..3732c1737 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 @@ -162,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 28d6f8969..4c8f8eca5 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 @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; 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 @@ -367,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); } } From e7bd2a568d466cbdfb7e1671ea3c1e8aee1c7a66 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 19:35:32 +0800 Subject: [PATCH 42/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=95=86=E6=9C=BA=E5=85=B3=E8=81=94=E8=81=94=E7=B3=BB?= =?UTF-8?q?=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/CrmContactController.java | 17 ++++++++ .../contact/vo/CrmContactBusiness2ReqVO.java | 22 +++++++++++ .../contact/vo/CrmContactBusinessReqVO.java | 2 +- .../contact/CrmContactBusinessMapper.java | 6 +++ .../contact/CrmContactBusinessService.java | 19 ++++++++- .../CrmContactBusinessServiceImpl.java | 39 +++++++++++++++++++ 6 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusiness2ReqVO.java 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 77c443f71..5c7413159 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 @@ -199,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')") @@ -207,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 000000000..5fac57cff --- /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 9b360f84b..7218494b4 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/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 8fd82b90b..7bff0c204 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/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 76477c281..2deaf0009 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 e975df14e..c8850e3eb 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) { From cd87f2e4aa24a91e10e90894a65a930ab2e94a3e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 19:57:26 +0800 Subject: [PATCH 43/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9Acode=20review=20?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E5=AF=BC=E5=87=BA=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/core/enums/ExcelColumn.java | 2 + .../core/handler/SelectSheetWriteHandler.java | 34 +++++++---- .../permission/CrmPermissionController.java | 40 +++++++++---- .../permission/CrmPermissionConvert.java | 57 ------------------- .../customer/CrmCustomerServiceImpl.java | 6 +- .../permission/CrmPermissionServiceImpl.java | 9 +-- 6 files changed, 64 insertions(+), 84 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java 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 4330b820b..dd8a8374c 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 6b6e70320..38d01bd87 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-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 88b4b3011..428bd07ad 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/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 6e6fae85a..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ /dev/null @@ -1,57 +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; - -// TODO @芋艿:要干掉 -/** - * 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/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 03245b271..314349865 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/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 3c1930202..7191df880 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) { From c726cd3aff1500e5a9affbb53f9a0c42d9409b88 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 24 Feb 2024 22:26:24 +0800 Subject: [PATCH 44/54] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E5=B0=86=20bi=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=88=90=20statistics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/bi/CrmBiRankController.http | 9 --- .../CrmStatisticsRankController.http | 9 +++ .../CrmStatisticsRankController.java} | 48 ++++++++-------- .../vo/CrmStatisticsRanKRespVO.java} | 6 +- .../vo/CrmStatisticsRankReqVO.java} | 6 +- .../CrmStatisticsRankingMapper.java} | 26 ++++----- .../CrmStatisticsRankingService.java} | 26 ++++----- .../CrmStatisticsRankingServiceImpl.java} | 56 +++++++++---------- .../mapper/bi/CrmBiRankingMapper.xml | 20 +++---- 9 files changed, 103 insertions(+), 103 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{bi/CrmBiRankController.java => statistics/CrmStatisticsRankController.java} (51%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{bi/vo/CrmBiRanKRespVO.java => statistics/vo/CrmStatisticsRanKRespVO.java} (83%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{bi/vo/CrmBiRankReqVO.java => statistics/vo/CrmStatisticsRankReqVO.java} (86%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/{bi/CrmBiRankingMapper.java => statistics/CrmStatisticsRankingMapper.java} (52%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/{bi/CrmBiRankingService.java => statistics/CrmStatisticsRankingService.java} (52%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/{bi/CrmBiRankingServiceImpl.java => statistics/CrmStatisticsRankingServiceImpl.java} (54%) 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 b9e9a4edf..000000000 --- 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/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 000000000..e878ba1a9 --- /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 21463aed0..e4cf61f7a 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 404ee3352..d5c865fd3 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 6d36f6d6f..487921957 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/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 9b71df7b6..4b51ab2fe 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/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 2ff28d385..c9455708c 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 60e1b4ecb..428ec1763 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 10030e0a7..c193873ce 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 @@