Переглянути джерело

CRM员工业绩统计PR v1.0

scholar 1 рік тому
батько
коміт
e86059ed80

+ 6 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java

@@ -27,6 +27,12 @@ public class DateUtils {
 
     public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
 
+    public static final String FORMAT_YEAR = "yyyy";
+
+    public static final String FORMAT_YEAR_MONTH = "yyyy-MM";
+
+
+
     public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss";
 
     /**

+ 52 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsStaffPerformanceController.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.CrmStatisticsStaffPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsStaffPerformanceRespVO;
+import cn.iocoder.yudao.module.crm.service.statistics.CrmStatisticsStaffPerformanceService;
+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 javax.annotation.Resource;
+import javax.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 CrmStatisticsStaffPerformanceController {
+
+    @Resource
+    private CrmStatisticsStaffPerformanceService performanceService;
+
+    @GetMapping("/get-contract-count-performance")
+    @Operation(summary = "员工业绩-签约合同数量")
+    @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
+    public CommonResult<List<CrmStatisticsStaffPerformanceRespVO>> getContractCountStaffPerformance(@Valid CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO) {
+        return success(performanceService.getContractCountStaffPerformance(staffPerformanceReqVO));
+    }
+
+    @GetMapping("/get-contract-price-performance")
+    @Operation(summary = "员工业绩-获得合同金额")
+    @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
+    public CommonResult<List<CrmStatisticsStaffPerformanceRespVO>> getContractPriceStaffPerformance(@Valid CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO) {
+        return success(performanceService.getContractPriceStaffPerformance(staffPerformanceReqVO));
+    }
+
+    @GetMapping("/get-receivable-price-performance")
+    @Operation(summary = "员工业绩-获得回款金额")
+    @PreAuthorize("@ss.hasPermission('crm:statistics-performance:query')")
+    public CommonResult<List<CrmStatisticsStaffPerformanceRespVO>> getReceivablePriceStaffPerformance(@Valid CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO) {
+        return success(performanceService.getReceivablePriceStaffPerformance(staffPerformanceReqVO));
+    }
+
+}

+ 29 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsStaffPerformanceReqVO.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR;
+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 CrmStatisticsStaffPerformanceReqVO {
+
+    @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "部门 id 不能为空")
+    private Long deptId;
+
+
+    @Schema(description = "年", requiredMode = Schema.RequiredMode.REQUIRED)
+    @DateTimeFormat(pattern = FORMAT_YEAR)
+    @NotEmpty(message = "时间不能为空")
+    private LocalDateTime year;
+
+}

+ 39 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/CrmStatisticsStaffPerformanceRespVO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotEmpty;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH;
+
+@Schema(description = "管理后台 - CRM 员工业绩统计 Response VO")
+@Data
+public class CrmStatisticsStaffPerformanceRespVO {
+
+    @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;
+
+    @Schema(description = "年-月", requiredMode = Schema.RequiredMode.REQUIRED)
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH)
+    @NotEmpty(message = "时间不能为空")
+    private LocalDateTime orderDate;
+
+    /**
+     * 数量是个特别“抽象”的概念,在不同排行下,代表不同含义
+     *
+     * 1. 金额:合同金额排行、回款金额排行
+     * 2. 个数:签约合同排行、产品销量排行、产品销量排行、新增客户数排行、新增联系人排行、跟进次数排行、跟进客户数排行
+     */
+    @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Integer count;
+
+}

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

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsStaffPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsStaffPerformanceRespVO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+@Mapper
+public interface CrmStatisticsStaffPerformanceMapper {
+
+    /**
+     * 员工签约合同数量
+     *
+     * @param staffPerformanceReqVO 参数
+     * @return 员工签约合同数量
+     */
+    List<CrmStatisticsStaffPerformanceRespVO> selectContractCountStaffPerformance(CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO);
+
+
+    /**
+     * 员工签约合同金额
+     *
+     * @param staffPerformanceReqVO 参数
+     * @return 员工签约合同金额
+     */
+    List<CrmStatisticsStaffPerformanceRespVO> selectContractPriceStaffPerformance(CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO);
+
+    /**
+     * 员工回款金额
+     *
+     * @param staffPerformanceReqVO 参数
+     * @return 员工回款金额
+     */
+    List<CrmStatisticsStaffPerformanceRespVO> selectReceivablePriceStaffPerformance(CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO);
+
+
+}

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

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

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

@@ -0,0 +1,95 @@
+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.statistics.vo.CrmStatisticsStaffPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsStaffPerformanceRespVO;
+import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsStaffPerformanceMapper;
+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 javax.annotation.Resource;
+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.convertSet;
+
+/**
+ * CRM 员工业绩分析 Service 实现类
+ *
+ * @author scholar
+ */
+@Service
+@Validated
+public class CrmStatisticsStaffPerformanceServiceImpl implements CrmStatisticsStaffPerformanceService {
+
+    @Resource
+    private CrmStatisticsStaffPerformanceMapper staffPerformanceMapper;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+    @Resource
+    private DeptApi deptApi;
+
+
+
+    @Override
+    public List<CrmStatisticsStaffPerformanceRespVO> getContractCountStaffPerformance(CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO) {
+        return getStaffPerformance(staffPerformanceReqVO, staffPerformanceMapper::selectContractCountStaffPerformance);
+    }
+    @Override
+    public List<CrmStatisticsStaffPerformanceRespVO> getContractPriceStaffPerformance(CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO) {
+        return getStaffPerformance(staffPerformanceReqVO, staffPerformanceMapper::selectContractPriceStaffPerformance);
+    }
+
+    @Override
+    public List<CrmStatisticsStaffPerformanceRespVO> getReceivablePriceStaffPerformance(CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO) {
+        return getStaffPerformance(staffPerformanceReqVO, staffPerformanceMapper::selectReceivablePriceStaffPerformance);
+    }
+
+
+
+    /**
+     * 获得员工业绩数据
+     *
+     * @param staffPerformanceReqVO  参数
+     * @param staffPerformanceFunction 排行榜方法
+     * @return 排行版数据
+     */
+    private List<CrmStatisticsStaffPerformanceRespVO> getStaffPerformance(CrmStatisticsStaffPerformanceReqVO staffPerformanceReqVO, Function<CrmStatisticsStaffPerformanceReqVO, List<CrmStatisticsStaffPerformanceRespVO>> staffPerformanceFunction) {
+
+        // 1. 获得员工业绩数据
+        List<CrmStatisticsStaffPerformanceRespVO> performance = staffPerformanceFunction.apply(staffPerformanceReqVO);
+        if (CollUtil.isEmpty(performance)) {
+            return Collections.emptyList();
+        }
+        performance.sort(Comparator.comparing(CrmStatisticsStaffPerformanceRespVO::getCount).reversed());
+        // 3. 拼接用户信息
+        appendUserInfo(performance);
+        return performance;
+    }
+
+    /**
+     * 拼接用户信息(昵称、部门)
+     *
+     * @param performances 员工业绩数据
+     */
+    private void appendUserInfo(List<CrmStatisticsStaffPerformanceRespVO> performances) {
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(performances, CrmStatisticsStaffPerformanceRespVO::getOwnerUserId));
+        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
+        performances.forEach(performance -> MapUtils.findAndThen(userMap, performance.getOwnerUserId(), user -> {
+            performance.setNickname(user.getNickname());
+            MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> performance.setDeptName(dept.getName()));
+        }));
+    }
+
+
+
+}

+ 36 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiStaffPerformanceMapper.xml

@@ -0,0 +1,36 @@
+<?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.CrmStatisticsStaffPerformanceMapper">
+
+
+    <select id="selectContractCountStaffPerformance"
+            resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsStaffPerformanceRespVO">
+        SELECT COUNT(1) AS count, DATE_FORMAT(order_date,'%Y-%m') AS orderDate
+        FROM crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND DATE_FORMAT(order_date,'%Y') in (#{year},#{year}-1)
+        GROUP BY DATE_FORMAT(order_date,'%Y-%m')
+    </select>
+    <select id="selectContractPriceStaffPerformance"
+            resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsStaffPerformanceRespVO">
+        SELECT IFNULL(SUM(total_price), 0) AS count, DATE_FORMAT(order_date,'%Y-%m') AS orderDate
+        FROM crm_contract
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND DATE_FORMAT(order_date,'%Y') in (#{year},#{year}-1)
+        GROUP BY DATE_FORMAT(order_date,'%Y-%m')
+    </select>
+
+    <select id="selectReceivablePriceStaffPerformance"
+            resultType="cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.CrmStatisticsStaffPerformanceRespVO">
+        SELECT IFNULL(SUM(price), 0) AS count, DATE_FORMAT(return_time,'%Y-%m') AS orderDate
+        FROM crm_receivable
+        WHERE deleted = 0
+        AND audit_status = 20
+        AND DATE_FORMAT(return_time,'%Y') in (#{year},#{year}-1)
+        GROUP BY DATE_FORMAT(return_time,'%Y-%m')
+    </select>
+
+
+</mapper>