diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java new file mode 100644 index 000000000..c3cce4272 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.flowable.core.enums; + +/** + * 流程常量信息 + */ +public interface BpmnModelConstants { + + String BPMN_FILE_SUFFIX = ".bpmn"; + + /** + * BPMN 中的命名空间 + * + * 这个东西有可能导致无法切换工作流程的实现 + */ + String NAMESPACE = "http://flowable.org/bpmn"; + + /** + * 自定义属性 dataType + */ + String PROCESS_CUSTOM_DATA_TYPE = "dataType"; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java index fe3511af7..e1ad107ab 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -49,7 +49,7 @@ public class BpmProcessInstanceCopyController { @PostMapping("/create") @Operation(summary = "抄送流程") @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:create')") - public CommonResult createProcessInstanceCC(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { + public CommonResult createProcessInstanceCopy(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { processInstanceCopyService.createProcessInstanceCopy(getLoginUserId(), createReqVO); return success(true); } @@ -57,7 +57,7 @@ public class BpmProcessInstanceCopyController { @GetMapping("/my-page") @Operation(summary = "获得抄送流程分页列表") @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") - public CommonResult> getProcessInstanceCCPage( + public CommonResult> getProcessInstanceCopyPage( @Valid BpmProcessInstanceCopyMyPageReqVO pageReqVO) { PageResult pageResult = processInstanceCopyService.getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java deleted file mode 100644 index 977ec41d8..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -// TODO @kyle:1)明确是 Req 还是 Resp;2)注释可以合并到 swagger 里;3)example 写一下,这样一些 mock 接口平台可以读取 example -/** - * 流程抄送视图对象 - */ -@Data -public class BpmProcessInstanceCopyVO { - - /** - * 编号 - */ - @Schema(description = "抄送主键") - private Long id; - - /** - * 发起人Id - */ - @Schema(description = "发起人Id") - private Long startUserId; - - @Schema(description = "发起人别名") - private String startUserNickname; - - /** - * 流程主键 - */ - @Schema(description = "流程实例的主键") - private String processInstanceId; - - @Schema(description = "流程实例的名字") - private String processInstanceName; - - /** - * 任务主键 - */ - @Schema(description = "发起抄送的任务编号") - private String taskId; - - @Schema(description = "发起抄送的任务名称") - private String taskName; - /** - * 用户主键 - */ - @Schema(description = "用户编号") - private Long userId; - - @Schema(description = "用户别名") - private Long userNickname; - - @Schema(description = "抄送原因") - private String reason; - - @Schema(description = "抄送人") - private String creator; - - @Schema(description = "抄送时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java new file mode 100644 index 000000000..ee81a9cf4 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; +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 jakarta.annotation.Resource; +import lombok.AllArgsConstructor; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.UserTask; +import org.flowable.engine.delegate.DelegateExecution; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +// TODO @芋艿:bpmn 分配人融合时,需要搞下这块; +/** + * 多实例处理类 + */ +@AllArgsConstructor +@Component("multiInstanceHandler") +public class MultiInstanceHandler { + + @Resource + private AdminUserApi userApi; + + @Resource + private PermissionApi permissionApi; + + /** + * 流程发起人那种情况不需要处理, + * 由 flowable 完成 + * + * @param execution flowable的执行对象 + * @return 用户ID + */ + public Set getUserIds(DelegateExecution execution) { + Set candidateUserIds = new LinkedHashSet<>(); + FlowElement flowElement = execution.getCurrentFlowElement(); + if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask userTask) { + String dataType = userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, BpmnModelConstants.PROCESS_CUSTOM_DATA_TYPE); + if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) { + // 添加候选用户id + candidateUserIds.addAll(userTask.getCandidateUsers()); + } else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) { + // 获取组的ID,角色ID集合或部门ID集合 + List groups = userTask.getCandidateGroups().stream() + // 例如部门DEPT100,100才是部门id + .map(item -> Long.parseLong(item.substring(4))) + .collect(Collectors.toList()); + List userIds = new ArrayList<>(); + if ("ROLES".equals(dataType)) { + // 通过角色id,获取所有用户id集合 + Set userRoleIdListByRoleIds = permissionApi.getUserRoleIdListByRoleIds(groups); + userIds = new ArrayList<>(userRoleIdListByRoleIds); + } else if ("DEPTS".equals(dataType)) { + // 通过部门id,获取所有用户id集合 + List userListByDeptIds = userApi.getUserListByDeptIds(groups); + userIds = convertList(userListByDeptIds, AdminUserRespDTO::getId); + } + // 添加候选用户id + userIds.forEach(id -> candidateUserIds.add(String.valueOf(id))); + } + } + return candidateUserIds; + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 28487b562..c9b3872cd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -5,8 +5,8 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.PageUtils; +import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; -import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; @@ -17,6 +17,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.BpmnModel; @@ -29,13 +31,10 @@ import org.flowable.engine.repository.ProcessDefinitionQuery; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.util.*; 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.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH; import static java.util.Collections.emptyList; @@ -53,8 +52,6 @@ import static java.util.Collections.emptyList; @Slf4j public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionService { - private static final String BPMN_FILE_SUFFIX = ".bpmn"; - @Resource private RepositoryService repositoryService; @@ -125,7 +122,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ // 创建 Deployment 部署 Deployment deploy = repositoryService.createDeployment() .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory()) - .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) + .addBytes(createReqDTO.getKey() + BpmnModelConstants.BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) .tenantId(TenantContextHolder.getTenantIdStr()) .deploy(); diff --git a/yudao-module-crm/pom.xml b/yudao-module-crm/pom.xml index 770d24afb..48ef0eac4 100644 --- a/yudao-module-crm/pom.xml +++ b/yudao-module-crm/pom.xml @@ -10,8 +10,6 @@ yudao-module-crm-api yudao-module-crm-biz - yudao-module-bi-biz - yudao-module-bi-api 4.0.0 yudao-module-crm diff --git a/yudao-module-crm/yudao-module-bi-api/pom.xml b/yudao-module-crm/yudao-module-bi-api/pom.xml deleted file mode 100644 index aa21b85f9..000000000 --- a/yudao-module-crm/yudao-module-bi-api/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - cn.iocoder.boot - yudao-module-crm - ${revision} - - 4.0.0 - yudao-module-bi-api - - ${project.artifactId} - - bi 模块 API,暴露给其它模块调用 - - - - - cn.iocoder.boot - yudao-module-system-api - ${revision} - - - cn.iocoder.boot - yudao-module-crm-api - ${revision} - - - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-operatelog - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-ip - - - - - cn.iocoder.boot - yudao-spring-boot-starter-web - - - - cn.iocoder.boot - yudao-spring-boot-starter-security - - - - - cn.iocoder.boot - yudao-spring-boot-starter-mybatis - - - - - cn.iocoder.boot - yudao-spring-boot-starter-excel - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-dict - - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - - - \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java deleted file mode 100644 index 77e7d2290..000000000 --- a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.bi.api; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java deleted file mode 100644 index eb4c1e428..000000000 --- a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.bi.enums; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/pom.xml b/yudao-module-crm/yudao-module-bi-biz/pom.xml deleted file mode 100644 index 92c8e2f9f..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/pom.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - cn.iocoder.boot - yudao-module-crm - ${revision} - - 4.0.0 - yudao-module-bi-biz - - ${project.artifactId} - - crm 包下,商业智能(Business Intelligence)。 - 例如说:报表、图表、数据分析等等 - - - - - cn.iocoder.boot - yudao-module-system-api - ${revision} - - - cn.iocoder.boot - yudao-module-crm-api - ${revision} - - - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-operatelog - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-ip - - - - - cn.iocoder.boot - yudao-spring-boot-starter-web - - - - cn.iocoder.boot - yudao-spring-boot-starter-security - - - - - cn.iocoder.boot - yudao-spring-boot-starter-mybatis - - - - - cn.iocoder.boot - yudao-spring-boot-starter-excel - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-dict - - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - - - \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http deleted file mode 100644 index e56a1fcfe..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http +++ /dev/null @@ -1,9 +0,0 @@ -### 合同金额排行榜 -GET {{baseUrl}}/bi/rank/contract-ranKing -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -### 回款金额排行榜 -GET {{baseUrl}}/bi/rank/receivables-ranKing -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java deleted file mode 100644 index 131d43892..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.module.bi.controller.admin.ranking; - - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; -import cn.iocoder.yudao.module.bi.service.ranking.BiRankingService; -import io.swagger.v3.oas.annotations.Operation; -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.RestController; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -// TODO @anhaohao:写了 swagger 注解,不写注释哈 -/** - * @author anhaohao - */ -@Tag(name = "管理后台 - 排行榜") -@RestController -@RequestMapping("/bi/ranking") -@Validated -public class BiRankingController { - - @Resource - private BiRankingService biRankingService; - - /** - * 合同金额排行榜 - */ - @GetMapping("/contract-ranking") - @Operation(summary = "合同金额排行榜") - @PreAuthorize("@ss.hasPermission('bi:ranking:query')") - public CommonResult> contractAmountRanking(BiRankReqVO biRankReqVO) { - return success(biRankingService.contractRanKing(biRankReqVO)); - } - - /** - * 回款金额排行榜 - */ - @GetMapping("/receivables-ranking") - @Operation(summary = "回款金额排行榜") - @PreAuthorize("@ss.hasPermission('bi:ranking:query')") - public CommonResult> receivablesRanKing(BiRankReqVO biRankReqVO) { - return success(biRankingService.receivablesRanKing(biRankReqVO)); - } - -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java deleted file mode 100644 index 487ebe031..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -// TODO @anhaohao:VO 类有 swagger 注解,不写注释哈 -/** - * 管理后台 - BI 排行榜 Response VO - * - * @author anhaohao - */ -@Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") -@Data -public class BiContractRanKingRespVO { - - // TODO @anhaohao:如果一定返回的字段,需要加 requiredMode = Schema.RequiredMode.REQUIRED, 哈 - @Schema(description = "金额", example = "1") - private Integer price; - - @Schema(description = "姓名", example = "1") - private String nickname; - - @Schema(description = "部门名称", example = "1") - private String deptName; - -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java deleted file mode 100644 index 7cbf469c8..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -// TODO @anhaohao:这个类的命名,还是保持和其它一致使用 ReqVO 结尾;例如说,CrmStatisticsCommonParamReqVO -/** - * @author anhaohao - * bi参数 - */ -@EqualsAndHashCode(callSuper = true) -@Schema(description = "bi查询相关参数") -@Data -public class BiParams extends PageParam { - - @Schema(description = "部门ID") - private Long deptId; - - @Schema(description = "用户ID") - private Long userId; - - @Schema(description = "用户IDs") - private List userIds; - - // TODO @anhaohao:这个字段,可以融合到 startTime、endTime 里去,交给前端计算哈; - @Schema(description = "类型") - private String type; - - // TODO @anhaohao:还是使用 LocalDateTime - @Schema(description = "开始时间") - private String startTime; - - @Schema(description = "结束时间") - private String endTime; - - // TODO @anhaohao:这个字段,是不是直接只基于 deptId 和 userId 来判断即可哈? - @Schema(description = "0 部门 1员工") - private Integer isUser = 1; - -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java deleted file mode 100644 index bca6c8c10..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 管理后台 - 排行榜 Request VO - * - * @author anhaohao - */ -@Schema(description = "管理后台 - 排行榜 Request VO") -@Data -public class BiRankReqVO { - - @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long deptId; - - // TODO @anhaohao:这个字段,参考 BiParams 的 type 建议 - @Schema(description = "分析类型(1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String type; - -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java deleted file mode 100644 index 0b395acde..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -// TODO @anhaohao:参考 BiContractRanKingRespVO 的建议 -/** - * 管理后台 - BI 排行榜 Response VO - * - * @author anhaohao - */ -@Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") -@Data -public class BiReceivablesRanKingRespVO { - - @Schema(description = "金额", example = "100") - private Integer price; - - @Schema(description = "姓名", example = "张三") - private String nickname; - - @Schema(description = "部门名称", example = "研发部") - private String deptName; - -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java deleted file mode 100644 index 052f6238f..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 RESTful API 给前端: - * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 - * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 - */ -package cn.iocoder.yudao.module.bi.controller; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java deleted file mode 100644 index e37184031..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.bi.dal.mysql; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; -import cn.iocoder.yudao.module.bi.util.BiTimeUtil; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * @author anhaohao - */ -@Mapper -public interface BiRankingMapper extends BaseMapperX { - /** - * 合同金额排行榜 - * - * @param biTimeEntity 参数 - * @return List - */ - List contractRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); - - /** - * 回款金额排行榜 - * - * @param biTimeEntity 参数 - * @return List - */ - List receivablesRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java deleted file mode 100644 index 8b004cf8c..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 属于 bi 模块的 framework 封装 - * - * @author 芋道源码 - */ -package cn.iocoder.yudao.module.bi.framework; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java deleted file mode 100644 index ad10cdccd..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.bi.framework.web.config; - -import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; -import org.springdoc.core.models.GroupedOpenApi; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * bi 模块的 web 组件的 Configuration - * - * @author 芋道源码 - */ -@Configuration(proxyBeanMethods = false) -public class BiWebConfiguration { - - /** - * bi 模块的 API 分组 - */ - @Bean - public GroupedOpenApi biGroupedOpenApi() { - return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("bi"); - } - -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java deleted file mode 100644 index e17abbb1c..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * bi 模块的 web 配置 - */ -package cn.iocoder.yudao.module.bi.framework.web; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java deleted file mode 100644 index d412dd6fd..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/** - * crm 包下,商业智能(Business Intelligence)。 - * 例如说:报表、图表、数据分析等等 - *

- * 1. Controller URL:以 /bi/ 开头,避免和其它 Module 冲突 - * - * TODO @anhaohao:mall 当时独立拆分一个 statistics 模块的原因,是因为 mall 拆分了多个模块,没有模块适合承接统计的能力,所以独立了。 - * TODO crm 因为没有拆分,所以可以直接放在 crm 模块下面;这样,我们可以在 controller/admin 和 service 下,新建一个 bi 包,专门放置统计的代码。 - */ -package cn.iocoder.yudao.module.bi; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java deleted file mode 100644 index 121029b19..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.bi.service.ranking; - -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; - -import java.util.List; - -/** - * BI 排行榜 Service 接口 - * - * @author anhaohao - */ -public interface BiRankingService { // TODO @anhaohao:第一个方法,和类要有一个空行 - /** - * 合同金额排行榜 - * - * @param biRankReqVO 参数 - * @return List - */ - List contractRanKing(BiRankReqVO biRankReqVO); - - /** - * 回款金额排行榜 - * - * @param biRankReqVO 参数 - * @return List - */ - List receivablesRanKing(BiRankReqVO biRankReqVO); -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java deleted file mode 100644 index 1ed468547..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.bi.service.ranking; - -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; -import cn.iocoder.yudao.module.bi.dal.mysql.BiRankingMapper; -import cn.iocoder.yudao.module.bi.util.BiTimeUtil; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author anhaohao - */ -@Service(value = "biRankService") -@Validated -public class BiRankingServiceImpl implements BiRankingService { - - @Resource - private BiRankingMapper biRankingMapper; - - @Override - public List contractRanKing(BiRankReqVO biRankReqVO) { - BiParams biParams = new BiParams(); - biParams.setType(biRankReqVO.getType()); - biParams.setDeptId(biRankReqVO.getDeptId()); - biParams.setIsUser(0); - BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); - List userIds = biTimeEntity.getUserIds(); - if (userIds.isEmpty()) { - return new ArrayList<>(); - } - return biRankingMapper.contractRanKing(biTimeEntity); - } - - @Override - public List receivablesRanKing(BiRankReqVO biRankReqVO) { - BiParams biParams = new BiParams(); - biParams.setType(biRankReqVO.getType()); - biParams.setDeptId(biRankReqVO.getDeptId()); - biParams.setIsUser(0); - BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); - List userIds = biTimeEntity.getUserIds(); - if (userIds.isEmpty()) { - return new ArrayList<>(); - } - return biRankingMapper.receivablesRanKing(biTimeEntity); - } -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java deleted file mode 100644 index 123122328..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java +++ /dev/null @@ -1,250 +0,0 @@ -package cn.iocoder.yudao.module.bi.util; - -import cn.hutool.core.date.DateUnit; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; -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 lombok.Data; -import lombok.experimental.Accessors; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * bi时间工具类 - * - * @author anhaohao - */ -public class BiTimeUtil { - - public static BiTimeEntity analyzeType(BiParams biParams) { - // 解析时间 - BiTimeEntity biTimeEntity = analyzeTime(biParams); - // 解析权限 - // TODO @anhaohao:涉及到数据的读取,不放在 Util 里,还是搞会到 Service 哈; - biTimeEntity.setUserIds(analyzeAuth(biParams)); - return biTimeEntity; - } - - /** - * 解析权限 - * - * @param biParams bi参数 - * @return List - */ - public static List analyzeAuth(BiParams biParams) { - List userIdList = new ArrayList<>(); - Long deptId = biParams.getDeptId(); - Long userId = biParams.getUserId(); - Integer isUser = biParams.getIsUser(); - // 获取部门和用户的api - DeptApi deptApi = SpringUtil.getBean("deptApiImpl"); - AdminUserApi adminUserApi = SpringUtil.getBean("adminUserApiImpl"); - // 0.部门 1.用户 - if (isUser == 0) { - if (deptId == null) { - deptId = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getDeptId(); - } - List childDeptList = deptApi.getChildDeptList(deptId); - List deptIds = new ArrayList<>(); - deptIds.add(deptId); - if (childDeptList != null && !childDeptList.isEmpty()) { - for (DeptRespDTO deptRespDTO : childDeptList) { - deptIds.add(deptRespDTO.getId()); - } - } - // 获取部门下的用户 - adminUserApi.getUserListByDeptIds(deptIds).forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); - } else { - if (userId == null) { - List userListBySubordinate = adminUserApi.getUserListBySubordinate(SecurityFrameworkUtils.getLoginUserId()); - userListBySubordinate.forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); - } else { - userIdList.add(userId); - } - } - return userIdList; - } - - - /** - * 解析时间 - * - * @param biParams bi参数 - * @return BiTimeEntity - */ - public static BiTimeEntity analyzeTime(BiParams biParams) { - Date beginDate = DateUtil.date(); - Date endDate = DateUtil.date(); - int cycleNum = 12; - String sqlDateFormat = "%Y%m"; - String dateFormat = "yyyyMM"; - String type = biParams.getType(); - String startTime = biParams.getStartTime(); - String endTime = biParams.getEndTime(); - if (StrUtil.isNotEmpty(type)) { - //1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年 - switch (type) { - case "1": - beginDate = DateUtil.beginOfDay(DateUtil.date()); - endDate = DateUtil.endOfDay(DateUtil.date()); - sqlDateFormat = "%Y%m%d"; - dateFormat = "yyyyMMdd"; - cycleNum = 1; - break; - case "2": - beginDate = DateUtil.beginOfDay(new Date(System.currentTimeMillis() - 86400000)); - endDate = DateUtil.endOfDay(new Date(System.currentTimeMillis() - 86400000)); - sqlDateFormat = "%Y%m%d"; - dateFormat = "yyyyMMdd"; - cycleNum = 1; - break; - case "3": - beginDate = DateUtil.beginOfWeek(DateUtil.date()); - endDate = DateUtil.endOfWeek(DateUtil.date()); - sqlDateFormat = "%Y%m%d"; - dateFormat = "yyyyMMdd"; - cycleNum = 7; - break; - case "4": - beginDate = DateUtil.beginOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); - endDate = DateUtil.endOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); - sqlDateFormat = "%Y%m%d"; - dateFormat = "yyyyMMdd"; - cycleNum = 7; - break; - case "5": - beginDate = DateUtil.beginOfMonth(DateUtil.date()); - endDate = DateUtil.endOfMonth(DateUtil.date()); - sqlDateFormat = "%Y%m%d"; - dateFormat = "yyyyMMdd"; - cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; - break; - case "6": - beginDate = DateUtil.beginOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); - endDate = DateUtil.endOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); - sqlDateFormat = "%Y%m%d"; - dateFormat = "yyyyMMdd"; - cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; - break; - case "7": - beginDate = DateUtil.beginOfQuarter(DateUtil.date()); - endDate = DateUtil.endOfQuarter(DateUtil.date()); - cycleNum = 3; - break; - case "8": - beginDate = DateUtil.beginOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); - endDate = DateUtil.endOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); - cycleNum = 3; - break; - case "9": - beginDate = DateUtil.beginOfYear(DateUtil.date()); - endDate = DateUtil.endOfYear(DateUtil.date()); - break; - case "10": - beginDate = DateUtil.beginOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); - endDate = DateUtil.endOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); - break; - default: - break; - } - } else if (StrUtil.isNotEmpty(startTime) && StrUtil.isNotEmpty(endTime)) { - Date start; - Date end; - if (startTime.length() == 6) { - start = DateUtil.parse(startTime, "yyyyMM"); - end = DateUtil.endOfMonth(DateUtil.parse(endTime, "yyyyMM")); - } else { - start = DateUtil.parse(startTime); - end = DateUtil.parse(endTime); - } - Integer startMonth = Integer.valueOf(DateUtil.format(start, "yyyyMM")); - int endMonth = Integer.parseInt(DateUtil.format(end, "yyyyMM")); - if (startMonth.equals(endMonth)) { - sqlDateFormat = "%Y%m%d"; - dateFormat = "yyyyMMdd"; - long diffDay = DateUtil.between(start, end, DateUnit.DAY); - cycleNum = (int) diffDay + 1; - } else { - sqlDateFormat = "%Y%m"; - dateFormat = "yyyyMM"; - int diffYear = Integer.parseInt(Integer.toString(endMonth).substring(0, 4)) - Integer.parseInt(startMonth.toString().substring(0, 4)); - int diffMonth = endMonth % 100 - startMonth % 100 + 1; - cycleNum = diffYear * 12 + diffMonth; - } - beginDate = start; - endDate = end; - } - Integer beginTime = Integer.valueOf(DateUtil.format(beginDate, dateFormat)); - Integer finalTime = Integer.valueOf(DateUtil.format(endDate, dateFormat)); - return new BiTimeEntity(sqlDateFormat, dateFormat, beginDate, endDate, cycleNum, beginTime, finalTime, new ArrayList<>()); - } - - @Data - @Accessors(chain = true) - public static class BiTimeEntity { - /** - * sql日期格式化 - */ - private String sqlDateFormat; - - /** - * 日期格式化 - */ - private String dateFormat; - - /** - * 开始时间 - */ - private Date beginDate; - - /** - * 结束时间 - */ - private Date endDate; - - /** - * 周期 - */ - private Integer cycleNum; - - /** - * 开始时间 字符串格式 如20200101 - */ - private Integer beginTime; - - /** - * 结束时间 字符串格式 如20200101 - */ - private Integer finalTime; - - /** - * user列表 - */ - private List userIds = new ArrayList<>(); - private Integer page; - private Integer limit; - - public BiTimeEntity(String sqlDateFormat, String dateFormat, Date beginDate, Date endDate, Integer cycleNum, Integer beginTime, Integer finalTime, List userIds) { - this.sqlDateFormat = sqlDateFormat; - this.dateFormat = dateFormat; - this.beginDate = beginDate; - this.endDate = endDate; - this.cycleNum = cycleNum; - this.beginTime = beginTime; - this.finalTime = finalTime; - this.userIds = userIds; - } - - public BiTimeEntity() { - } - - } -} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml deleted file mode 100644 index a41dc5d7f..000000000 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - 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 new file mode 100644 index 000000000..b9e9a4edf --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http @@ -0,0 +1,9 @@ +### 合同金额排行榜 +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/bi/CrmBiRankController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java new file mode 100644 index 000000000..a188232ef --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi; + +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 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 java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + + +@Tag(name = "管理后台 - CRM BI 排行榜") +@RestController +@RequestMapping("/crm/bi-rank") +@Validated +public class CrmBiRankController { + + @Resource + private CrmBiRankingService rankingService; + + @GetMapping("/get-contract-price-rank") + @Operation(summary = "获得合同金额排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getContractPriceRank(@Valid CrmBiRankReqVO 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) { + return success(rankingService.getReceivablePriceRank(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/bi/vo/CrmBiRanKRespVO.java new file mode 100644 index 000000000..404ee3352 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + + +@Schema(description = "管理后台 - CRM BI 排行榜 Response VO") +@Data +public class CrmBiRanKRespVO { + + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long ownerUserId; + + @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String nickname; + + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String deptName; + + /** + * 数量是个特别“抽象”的概念,在不同排行下,代表不同含义 + * + * 1. 金额:合同金额排行、回款金额排行 + * 2. 个数:签约合同排行、产品销量排行、产品销量排行、新增客户数排行、新增联系人排行、跟进次数排行、跟进客户数排行 + */ + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer count; + +} 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/bi/vo/CrmBiRankReqVO.java new file mode 100644 index 000000000..6d36f6d6f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +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 BI 排行榜 Request VO") +@Data +public class CrmBiRankReqVO { + + @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "部门 id 不能为空") + private Long deptId; + + /** + * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来 + * + * 后续,可能会支持选择部分用户进行查询 + */ + @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2") + private List userIds; + + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @NotEmpty(message = "时间范围不能为空") + private LocalDateTime[] times; + +} 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 481914e8b..252d714f4 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,6 +28,7 @@ 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.*; @@ -55,6 +56,7 @@ 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/dal/mysql/bi/CrmBiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java new file mode 100644 index 000000000..91b7a191b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.bi; + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * CRM BI 排行榜 Mapper + * + * @author anhaohao + */ +@Mapper +public interface CrmBiRankingMapper { + + /** + * 查询合同金额排行榜 + * + * @param rankReqVO 参数 + * @return 合同金额排行榜 + */ + List selectContractPriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询回款金额排行榜 + * + * @param rankReqVO 参数 + * @return 回款金额排行榜 + */ + List selectReceivablePriceRank(CrmBiRankReqVO 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/bi/CrmBiRankingService.java new file mode 100644 index 000000000..72d1d6f97 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.crm.service.bi; + + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; + +import java.util.List; + +/** + * CRM BI 排行榜 Service 接口 + * + * @author anhaohao + */ +public interface CrmBiRankingService { + + /** + * 获得合同金额排行榜 + * + * @param rankReqVO 排行参数 + * @return 合同金额排行榜 + */ + List getContractPriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得回款金额排行榜 + * + * @param rankReqVO 排行参数 + * @return 回款金额排行榜 + */ + List getReceivablePriceRank(CrmBiRankReqVO 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/bi/CrmBiRankingServiceImpl.java new file mode 100644 index 000000000..84f47ddc9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.crm.service.bi; + +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.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 jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +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.convertSet; + +/** + * CRM BI 排行榜 Service 实现类 + * + * @author anhaohao + */ +@Service +@Validated +public class CrmBiRankingServiceImpl implements CrmBiRankingService { + + @Resource + private CrmBiRankingMapper biRankingMapper; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; + + @Override + public List getContractPriceRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectContractPriceRank); + } + + @Override + public List getReceivablePriceRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectReceivablePriceRank); + } + + /** + * 获得排行版数据 + * + * @param rankReqVO 参数 + * @param rankFunction 排行榜方法 + * @return 排行版数据 + */ + private List getRank(CrmBiRankReqVO rankReqVO, Function> rankFunction) { + // 1. 获得用户编号数组 + rankReqVO.setUserIds(getUserIds(rankReqVO.getDeptId())); + if (CollUtil.isEmpty(rankReqVO.getUserIds())) { + return Collections.emptyList(); + } + // 2. 获得排行数据 + List ranks = rankFunction.apply(rankReqVO); + if (CollUtil.isEmpty(ranks)) { + return Collections.emptyList(); + } + ranks.sort(Comparator.comparing(CrmBiRanKRespVO::getCount).reversed()); + // 3. 拼接用户信息 + appendUserInfo(ranks); + return ranks; + } + + /** + * 拼接用户信息(昵称、部门) + * + * @param ranks 排行榜数据 + */ + private void appendUserInfo(List ranks) { + Map userMap = adminUserApi.getUserMap(convertSet(ranks, CrmBiRanKRespVO::getOwnerUserId)); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + ranks.forEach(rank -> MapUtils.findAndThen(userMap, rank.getOwnerUserId(), user -> { + rank.setNickname(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> rank.setDeptName(dept.getName())); + })); + } + + /** + * 获得部门下的用户编号数组,包括子部门的 + * + * @param deptId 部门编号 + * @return 用户编号数组 + */ + public List getUserIds(Long deptId) { + // 1. 获得部门列表 + List deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId); + deptIds.add(deptId); + // 2. 获得用户编号 + return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId); + } + +} \ 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/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index f40a15bc1..1daad016a 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 @@ -57,7 +57,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessProductService businessProductService; @Resource - @Lazy + @Lazy // 延迟加载,避免循环依赖 private CrmContractService contractService; @Resource private CrmPermissionService permissionService; 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 d05647cfb..9ac2e7f43 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,6 +24,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.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; 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 54c4aa82a..effe0d720 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,6 +27,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.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; 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 new file mode 100644 index 000000000..ef90bb564 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java index 81062994e..6eb55ef48 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -20,7 +20,6 @@ import java.util.List; public class DeptApiImpl implements DeptApi { @Resource - @Lazy // 延迟加载,解决相互依赖的问题 private DeptService deptService; @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java index 54aaa4dc7..c26acb8ca 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java @@ -44,6 +44,9 @@ public class AuthPermissionInfoRespVO { @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg") private String avatar; + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + private Long deptId; + } @Schema(description = "管理后台 - 登录用户的菜单信息 Response VO") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java index 8343547d9..18463e7f6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.convert.auth; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; @@ -29,7 +30,7 @@ public interface AuthConvert { default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() - .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) + .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) .roles(convertSet(roleList, RoleDO::getCode)) // 权限标识信息 .permissions(convertSet(menuList, MenuDO::getPermission)) diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index bf640588b..ff17b298d 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -93,11 +93,6 @@ yudao-module-crm-biz ${revision} - - cn.iocoder.boot - yudao-module-bi-biz - ${revision} -