Explorar el Código

CRM员工业绩统计PR v2.0

scholar hace 1 año
padre
commit
705a3e53ca

+ 52 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPerformanceController.java

@@ -0,0 +1,52 @@
+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.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
+import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsPerformanceService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+
+@Tag(name = "管理后台 - CRM 员工业绩统计")
+@RestController
+@RequestMapping("/crm/statistics-performance")
+@Validated
+public class CrmStatisticsPerformanceController {
+
+    @Resource
+    private CrmStatisticsPerformanceService performanceService;
+
+    @GetMapping("/get-contract-count-performance")
+    @Operation(summary = "员工业绩-签约合同数量")
+    @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
+    public CommonResult<List<CrmStatisticsPerformanceRespVO>> getContractCountPerformance(@Valid CrmStatisticsPerformanceReqVO performanceReqVO) {
+        return success(performanceService.getContractCountPerformance(performanceReqVO));
+    }
+
+    @GetMapping("/get-contract-price-performance")
+    @Operation(summary = "员工业绩-获得合同金额")
+    @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
+    public CommonResult<List<CrmStatisticsPerformanceRespVO>> getContractPriceStaffPerformance(@Valid CrmStatisticsPerformanceReqVO performanceReqVO) {
+        return success(performanceService.getContractPricePerformance(performanceReqVO));
+    }
+
+    @GetMapping("/get-receivable-price-performance")
+    @Operation(summary = "员工业绩-获得回款金额")
+    @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
+    public CommonResult<List<CrmStatisticsPerformanceRespVO>> getReceivablePriceStaffPerformance(@Valid CrmStatisticsPerformanceReqVO performanceReqVO) {
+        return success(performanceService.getReceivablePricePerformance(performanceReqVO));
+    }
+
+}

+ 41 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java

@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+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 员工业绩统计 Request VO")
+@Data
+public class CrmStatisticsPerformanceReqVO {
+
+    @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "部门 id 不能为空")
+    private Long deptId;
+
+    /**
+     * 负责人用户 id, 当用户为空, 则计算部门下用户
+     */
+    @Schema(description = "负责人用户 id", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
+    private Long userId;
+
+    /**
+     * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来
+     * <p>
+     * 后续,可能会支持选择部分用户进行查询
+     */
+    @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2")
+    private List<Long> userIds;
+
+    @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED)
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @NotEmpty(message = "时间范围不能为空")
+    private LocalDateTime[] times;
+
+}

+ 24 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceRespVO.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.math.BigDecimal;
+
+
+@Schema(description = "管理后台 - CRM 员工业绩统计 Response VO")
+@Data
+public class CrmStatisticsPerformanceRespVO {
+
+    @Schema(description = "时间轴", requiredMode = Schema.RequiredMode.REQUIRED, example = "202401")
+    private String time;
+
+    @Schema(description = "当月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private BigDecimal currentMonthCount;
+
+    @Schema(description = "上月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private BigDecimal lastMonthCount;
+
+    @Schema(description = "去年同期统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
+    private BigDecimal lastYearCount;
+
+}

+ 41 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPerformanceMapper.java

@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * CRM 员工业绩分析 Mapper
+ *
+ * @author scholar
+ */
+@Mapper
+public interface CrmStatisticsPerformanceMapper {
+
+    /**
+     * 员工签约合同数量
+     *
+     * @param performanceReqVO 参数
+     * @return 员工签约合同数量
+     */
+    List<CrmStatisticsPerformanceRespVO> selectContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+    /**
+     * 员工签约合同金额
+     *
+     * @param performanceReqVO 参数
+     * @return 员工签约合同金额
+     */
+    List<CrmStatisticsPerformanceRespVO> selectContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+    /**
+     * 员工回款金额
+     *
+     * @param performanceReqVO 参数
+     * @return 员工回款金额
+     */
+    List<CrmStatisticsPerformanceRespVO> selectReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+}

+ 42 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceService.java

@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
+
+import java.util.List;
+
+/**
+ * CRM 员工绩效统计 Service 接口
+ *
+ * @author scholar
+ */
+public interface CrmStatisticsPerformanceService {
+
+    /**
+     * 员工签约合同数量分析
+     *
+     * @param performanceReqVO 排行参数
+     * @return 员工签约合同数量排行分析
+     */
+    List<CrmStatisticsPerformanceRespVO> getContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+    /**
+     * 员工签约合同金额分析
+     *
+     * @param performanceReqVO 排行参数
+     * @return 员工签约合同金额分析
+     */
+    List<CrmStatisticsPerformanceRespVO> getContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+    /**
+     * 员工获得回款金额分析
+     *
+     * @param performanceReqVO 排行参数
+     * @return 员工获得回款金额分析
+     */
+    List<CrmStatisticsPerformanceRespVO> getReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+
+}

+ 99 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java

@@ -0,0 +1,99 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
+import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPerformanceMapper;
+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 org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import jakarta.annotation.Resource;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+
+/**
+ * CRM 员工业绩分析 Service 实现类
+ *
+ * @author scholar
+ */
+@Service
+@Validated
+public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerformanceService {
+
+    @Resource
+    private CrmStatisticsPerformanceMapper performanceMapper;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+    @Resource
+    private DeptApi deptApi;
+
+
+    @Override
+    public List<CrmStatisticsPerformanceRespVO> getContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
+        return getPerformance(performanceReqVO, performanceMapper::selectContractCountPerformance);
+    }
+
+    @Override
+    public List<CrmStatisticsPerformanceRespVO> getContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
+        return getPerformance(performanceReqVO, performanceMapper::selectContractPricePerformance);
+    }
+
+    @Override
+    public List<CrmStatisticsPerformanceRespVO> getReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
+        return getPerformance(performanceReqVO, performanceMapper::selectReceivablePricePerformance);
+    }
+
+    /**
+     * 获得员工业绩数据
+     *
+     * @param performanceReqVO  参数
+     * @param performanceFunction 排行榜方法
+     * @return 排行版数据
+     */
+    private List<CrmStatisticsPerformanceRespVO> getPerformance(CrmStatisticsPerformanceReqVO performanceReqVO, Function<CrmStatisticsPerformanceReqVO,
+            List<CrmStatisticsPerformanceRespVO>> performanceFunction) {
+
+        // 1. 获得用户编号数组
+        final List<Long> userIds = getUserIds(performanceReqVO);
+        if (CollUtil.isEmpty(userIds)) {
+            return Collections.emptyList();
+        }
+        performanceReqVO.setUserIds(userIds);
+        // 2. 获得排行数据
+        List<CrmStatisticsPerformanceRespVO> performance = performanceFunction.apply(performanceReqVO);
+        if (CollUtil.isEmpty(performance)) {
+            return Collections.emptyList();
+        }
+        return performance;
+    }
+
+    /**
+     * 获取用户编号数组。如果用户编号为空, 则获得部门下的用户编号数组,包括子部门的所有用户编号
+     *
+     * @param reqVO 请求参数
+     * @return 用户编号数组
+     */
+    private List<Long> getUserIds(CrmStatisticsPerformanceReqVO reqVO) {
+        // 情况一:选中某个用户
+        if (ObjUtil.isNotNull(reqVO.getUserId())) {
+            return List.of(reqVO.getUserId());
+        }
+        // 情况二:选中某个部门
+        // 2.1 获得部门列表
+        final Long deptId = reqVO.getDeptId();
+        List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
+        deptIds.add(deptId);
+        // 2.2 获得用户编号
+        return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
+    }
+
+}

+ 152 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml

@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPerformanceMapper">
+
+    <select id="selectContractCountPerformance"
+            resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO">
+        SELECT
+        t.time as time,
+        COALESCE(t.currentMonthCount,0) as currentMonthCount,
+        COALESCE(y.lastMonthCount,0) as lastMonthCount,
+        COALESCE(z.lastYearCount,0) as lastYearCount
+        FROM
+        (SELECT
+        COUNT(1) AS currentMonthCount,
+        DATE_FORMAT(order_date, '%Y-%m') AS time
+        FROM	crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
+        GROUP BY time)t
+        LEFT JOIN
+        (SELECT
+        COUNT(1) AS lastMonthCount,
+        DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 MONTH), '%Y-%m') AS time
+        FROM	crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND (DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
+        or DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1)
+        GROUP BY time)y ON t.time = y.time
+        LEFT JOIN
+        (SELECT
+        COUNT(1) AS lastYearCount,
+        DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 YEAR), '%Y-%m') AS time
+        FROM	crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1
+        GROUP BY time)z ON t.time = z.time
+    </select>
+    <select id="selectContractPricePerformance"
+            resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO">
+        SELECT
+        t.time as time,
+        COALESCE(t.currentMonthCount,0) as currentMonthCount,
+        COALESCE(y.lastMonthCount,0) as lastMonthCount,
+        COALESCE(z.lastYearCount,0) as lastYearCount
+        FROM
+        (SELECT
+        IFNULL(SUM(total_price), 0) AS currentMonthCount,
+        DATE_FORMAT(order_date, '%Y-%m') AS time
+        FROM	crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
+        GROUP BY time)t
+        LEFT JOIN
+        (SELECT
+        IFNULL(SUM(total_price), 0) AS lastMonthCount,
+        DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 MONTH), '%Y-%m') AS time
+        FROM	crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND (DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
+        or DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1)
+        GROUP BY time)y ON t.time = y.time
+        LEFT JOIN
+        (SELECT
+        IFNULL(SUM(total_price), 0) AS lastYearCount,
+        DATE_FORMAT(DATE_ADD(order_date,INTERVAL 1 YEAR), '%Y-%m') AS time
+        FROM	crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND DATE_FORMAT(order_date, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1
+        GROUP BY time)z ON t.time = z.time
+    </select>
+
+    <select id="selectReceivablePricePerformance"
+            resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO">
+        SELECT
+        t.time as time,
+        COALESCE(t.currentMonthCount,0) as currentMonthCount,
+        COALESCE(y.lastMonthCount,0) as lastMonthCount,
+        COALESCE(z.lastYearCount,0) as lastYearCount
+        FROM
+        (SELECT
+        IFNULL(SUM(price), 0) AS currentMonthCount,
+        DATE_FORMAT(return_time, '%Y-%m') AS time
+        FROM	crm_receivable
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
+        GROUP BY time)t
+        LEFT JOIN
+        (SELECT
+        IFNULL(SUM(price), 0) AS lastMonthCount,
+        DATE_FORMAT(DATE_ADD(return_time,INTERVAL 1 MONTH), '%Y-%m') AS time
+        FROM	crm_receivable
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND (DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')
+        or DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1)
+        GROUP BY time)y ON t.time = y.time
+        LEFT JOIN
+        (SELECT
+        IFNULL(SUM(price), 0) AS lastYearCount,
+        DATE_FORMAT(DATE_ADD(return_time,INTERVAL 1 YEAR), '%Y-%m') AS time
+        FROM	crm_receivable
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND owner_user_id in
+        <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
+            #{userId}
+        </foreach>
+        AND DATE_FORMAT(return_time, '%Y') = DATE_FORMAT(#{times[0],javaType=java.time.LocalDateTime},'%Y')-1
+        GROUP BY time)z ON t.time = z.time
+    </select>
+
+
+</mapper>