Browse Source

销售统计

xgb 3 tuần trước cách đây
mục cha
commit
7026e247bf

+ 29 - 0
fs-company/src/main/java/com/fs/company/controller/company/CompanyStatisticsController.java

@@ -13,8 +13,10 @@ import com.fs.company.param.CompanyStatisticsParam;
 import com.fs.company.service.ICompanySmsLogsService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.company.service.ICompanyVoiceLogsService;
+import com.fs.company.vo.CompanyRedPacketStatisticsVO;
 import com.fs.company.vo.CompanySmsLogsStatisticsVO;
 import com.fs.company.vo.CompanyVoiceLogsStatisticsVO;
+import com.fs.course.service.IFsUserWatchStatisticsService;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,6 +48,9 @@ public class CompanyStatisticsController extends BaseController
     private ICompanyVoiceLogsService voiceLogsService;
     @Autowired
     private ICompanySmsLogsService smsLogsService;
+
+    @Autowired
+    private IFsUserWatchStatisticsService fsUserWatchStatisticsService;
     @Autowired
     private TokenService tokenService;
     @PreAuthorize("@ss.hasPermi('company:statistics:voiceLogs')")
@@ -248,6 +253,30 @@ public class CompanyStatisticsController extends BaseController
         return util.exportExcel(list, "voiceLogs");
     }
 
+    @PreAuthorize("@ss.hasPermi('company:statistics:redPacket')")
+    @GetMapping("/redPacketStatisticsBySales")
+    public R redPacket(CompanyStatisticsParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+
+        List<CompanyRedPacketStatisticsVO> list = fsUserWatchStatisticsService.selectRedPacketStatisticsBySales(param);
+        return R.ok().put("list", list);
+
+    }
+
+    @PreAuthorize("@ss.hasPermi('company:statistics:exportRedPacket')")
+    @GetMapping("/exportRedPacketStatisticsBySales")
+    public AjaxResult exportRedPacket(CompanyStatisticsParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setCompanyId(loginUser.getCompany().getCompanyId());
+        List<CompanyRedPacketStatisticsVO> list = fsUserWatchStatisticsService.selectRedPacketStatisticsBySales(param);
+
+        ExcelUtil<CompanyRedPacketStatisticsVO> util = new ExcelUtil<CompanyRedPacketStatisticsVO>(CompanyRedPacketStatisticsVO.class);
+        return util.exportExcel(list, "redPacketStatistics");
+    }
+
 
 
 }

+ 7 - 0
fs-service/src/main/java/com/fs/company/param/CompanyStatisticsParam.java

@@ -16,6 +16,13 @@ public class CompanyStatisticsParam implements Serializable
     String endTime;
     Long deptId;
 
+    private Long companyId;
+
+    private Long companyUserId;
+
+    private String startDate;
+    private String endDate;
+
 
 
 }

+ 28 - 0
fs-service/src/main/java/com/fs/company/vo/CompanyRedPacketStatisticsVO.java

@@ -0,0 +1,28 @@
+package com.fs.company.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class CompanyRedPacketStatisticsVO implements Serializable
+{
+    @Excel(name = "销售姓名")
+    private String userName;
+
+    @Excel(name = "用户数")
+    private Integer userCount;
+
+    @Excel(name = "新增用户数")
+    private Integer newUserCount;
+
+    @Excel(name = "完课数")
+    private Integer finishCount;
+
+    @Excel(name = "红包金额")
+    private BigDecimal redPacketAmount;
+
+    private Long companyUserId;
+}

+ 4 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseRedPacketLogMapper.java

@@ -5,6 +5,8 @@ import java.time.LocalDateTime;
 import java.util.List;
 import java.util.Map;
 
+import com.fs.company.param.CompanyStatisticsParam;
+import com.fs.company.vo.CompanyRedPacketStatisticsVO;
 import com.fs.company.vo.RedPacketMoneyVO;
 import com.fs.course.domain.FsCourseRedPacketLog;
 import com.fs.course.dto.CourseRedPacketStatisticsDTO;
@@ -211,4 +213,6 @@ public interface FsCourseRedPacketLogMapper
     BigDecimal getTodaySumAmountByCompanyUserId(Long userId);
 
     List<AppSalesCourseStatisticsVO> selectAppSalesRedPacketStatisticsVO(FsCourseWatchLogStatisticsListParam param);
+
+    List<CompanyRedPacketStatisticsVO> selectCourseFinishCount(CompanyStatisticsParam param);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCourseWatchLogMapper.java

@@ -1,6 +1,8 @@
 package com.fs.course.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.company.param.CompanyStatisticsParam;
+import com.fs.company.vo.CompanyRedPacketStatisticsVO;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.dto.WatchLogDTO;
 import com.fs.course.param.*;
@@ -807,4 +809,6 @@ public interface FsCourseWatchLogMapper extends BaseMapper<FsCourseWatchLog> {
     List<AppSalesWatchLogReportVO> selectAppDeptOrderStats(FsCourseWatchLogStatisticsListParam param);
 
     List<AppSalesCourseStatisticsVO> selectAppSalesCourseStatisticsVO(FsCourseWatchLogStatisticsListParam param);
+
+    List<CompanyRedPacketStatisticsVO> selectCourseFinishCount(CompanyStatisticsParam param);
 }

+ 7 - 1
fs-service/src/main/java/com/fs/course/mapper/FsUserCompanyUserMapper.java

@@ -1,6 +1,8 @@
 package com.fs.course.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.company.param.CompanyStatisticsParam;
+import com.fs.company.vo.CompanyRedPacketStatisticsVO;
 import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.qw.dto.FsUserTransferParamDTO;
 import com.fs.qw.dto.UserProjectDTO;
@@ -107,7 +109,7 @@ public interface FsUserCompanyUserMapper extends BaseMapper<FsUserCompanyUser>{
 
     /**
      * 根据用户id查询用户id
-     * @param companyUserId
+     * @param
      * @return
      */
     List<Long> selectIdListByCompanyUserId(FsUserPageListParam param);
@@ -119,4 +121,8 @@ public interface FsUserCompanyUserMapper extends BaseMapper<FsUserCompanyUser>{
      * @return
      */
     FsUserCompanyUser selectFsUserCompanyUserByUserId(@Param("userId") Long userId);
+
+    List<CompanyRedPacketStatisticsVO> selectSalesUserCount(CompanyStatisticsParam param);
+
+    List<CompanyRedPacketStatisticsVO> selectSalesNewUserCount(CompanyStatisticsParam param);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserWatchStatisticsService.java

@@ -1,6 +1,8 @@
 package com.fs.course.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.company.param.CompanyStatisticsParam;
+import com.fs.company.vo.CompanyRedPacketStatisticsVO;
 import com.fs.course.domain.FsUserWatchStatistics;
 
 import java.util.List;
@@ -64,4 +66,6 @@ public interface IFsUserWatchStatisticsService extends IService<FsUserWatchStati
      * 新增按营期统计会员看课表数据
      */
     void insertStatistics();
+
+    List<CompanyRedPacketStatisticsVO> selectRedPacketStatisticsBySales(CompanyStatisticsParam param);
 }

+ 123 - 2
fs-service/src/main/java/com/fs/course/service/impl/FsUserWatchStatisticsServiceImpl.java

@@ -3,14 +3,17 @@ package com.fs.course.service.impl;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fs.company.domain.Company;
 import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.param.CompanyStatisticsParam;
+import com.fs.company.vo.CompanyRedPacketStatisticsVO;
+import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.domain.FsUserWatchStatistics;
-import com.fs.course.mapper.FsUserCoursePeriodMapper;
-import com.fs.course.mapper.FsUserWatchStatisticsMapper;
+import com.fs.course.mapper.*;
 import com.fs.course.service.IFsUserWatchStatisticsService;
 import com.fs.his.mapper.FsUserMapper;
 import com.google.common.collect.Lists;
 import lombok.AllArgsConstructor;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
@@ -24,6 +27,7 @@ import java.math.RoundingMode;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -46,6 +50,15 @@ public class FsUserWatchStatisticsServiceImpl extends ServiceImpl<FsUserWatchSta
 
     private final CompanyMapper companyMapper;
 
+    @Autowired
+    private FsCourseRedPacketLogMapper  fsCourseRedPacketLogMapper;
+
+    @Autowired
+    private FsUserCompanyUserMapper fsUserCompanyUserMapper;
+
+    @Autowired
+    private FsCourseWatchLogMapper  fsCourseWatchLogMapper;
+
     /**
      * 查询会员看课统计-按营期统计
      *
@@ -208,6 +221,8 @@ public class FsUserWatchStatisticsServiceImpl extends ServiceImpl<FsUserWatchSta
 
     }
 
+
+
     private void batchInsert(List<FsUserWatchStatistics> list) {
         // 分批次处理,一次提交500条
         List<List<FsUserWatchStatistics>> batches = Lists.partition(list, 500);
@@ -222,4 +237,110 @@ public class FsUserWatchStatisticsServiceImpl extends ServiceImpl<FsUserWatchSta
             }
         });
     }
+
+
+    /**
+     * @Description: 看课统计 按销售统计用户 新增用户 完课 红包
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2026/3/26 14:16
+     */
+    @Override
+    public List<CompanyRedPacketStatisticsVO> selectRedPacketStatisticsBySales(CompanyStatisticsParam param) {
+        // 异步查询
+        // 用户数
+        CompletableFuture<List<CompanyRedPacketStatisticsVO>> userFuture = CompletableFuture.supplyAsync(() -> {
+            return fsUserCompanyUserMapper.selectSalesUserCount(param);
+        });
+
+        // 新注册用户
+        CompletableFuture<List<CompanyRedPacketStatisticsVO>> newUserFuture = CompletableFuture.supplyAsync(() -> {
+            return fsUserCompanyUserMapper.selectSalesNewUserCount(param);
+        });
+
+        // 看课记录数
+        CompletableFuture<List<CompanyRedPacketStatisticsVO>> watchLogFuture = CompletableFuture.supplyAsync(() -> {
+            return fsCourseWatchLogMapper.selectCourseFinishCount(param);
+        });
+
+        // 红包记录
+        CompletableFuture<List<CompanyRedPacketStatisticsVO>> redPacketFuture = CompletableFuture.supplyAsync(() -> {
+            return fsCourseRedPacketLogMapper.selectCourseFinishCount(param);
+        });
+
+        CompletableFuture.allOf(userFuture, newUserFuture, watchLogFuture, redPacketFuture).join();
+
+
+        // 获取各个查询结果
+        List<CompanyRedPacketStatisticsVO> userList = userFuture.join();
+        List<CompanyRedPacketStatisticsVO> newUserList = newUserFuture.join();
+        List<CompanyRedPacketStatisticsVO> watchLogList = watchLogFuture.join();
+        List<CompanyRedPacketStatisticsVO> redPacketList = redPacketFuture.join();
+
+        // 按销售 ID(company_user_id)分组,合并数据
+        Map<Long, CompanyRedPacketStatisticsVO> statisticsMap = new HashMap<>();
+
+        // 1. 先处理用户数(作为基础数据)
+        if (userList != null && !userList.isEmpty()) {
+            for (CompanyRedPacketStatisticsVO vo : userList) {
+                Long key = vo.getCompanyUserId();
+                CompanyRedPacketStatisticsVO statisticsVO = new CompanyRedPacketStatisticsVO();
+                statisticsVO.setCompanyUserId(vo.getCompanyUserId());
+                statisticsVO.setUserName(vo.getUserName());
+                statisticsVO.setUserCount(vo.getUserCount() != null ? vo.getUserCount() : 0);
+                statisticsVO.setNewUserCount(0);
+                statisticsVO.setFinishCount(0);
+                statisticsVO.setRedPacketAmount(new BigDecimal(0));
+                statisticsMap.put(key, statisticsVO);
+            }
+        }
+
+        // 2. 合并新增用户数
+        if (newUserList != null && !newUserList.isEmpty()) {
+            for (CompanyRedPacketStatisticsVO vo : newUserList) {
+                Long key = vo.getCompanyUserId();
+                CompanyRedPacketStatisticsVO statisticsVO = statisticsMap.get(key);
+                if (statisticsVO != null) {
+                    statisticsVO.setNewUserCount(vo.getNewUserCount() != null ? vo.getNewUserCount() : 0);
+                } else {
+                    // 如果该销售不在用户数列表中,创建新记录
+                    statisticsVO = new CompanyRedPacketStatisticsVO();
+                    statisticsVO.setCompanyUserId(vo.getCompanyUserId());
+                    statisticsVO.setUserName(vo.getUserName());
+                    statisticsVO.setUserCount(0);
+                    statisticsVO.setNewUserCount(vo.getNewUserCount() != null ? vo.getNewUserCount() : 0);
+                    statisticsVO.setFinishCount(0);
+                    statisticsVO.setRedPacketAmount(new BigDecimal(0));
+                    statisticsMap.put(key, statisticsVO);
+                }
+            }
+        }
+
+        // 3. 合并完课数
+        if (watchLogList != null && !watchLogList.isEmpty()) {
+            for (CompanyRedPacketStatisticsVO vo : watchLogList) {
+                Long key = vo.getCompanyUserId();
+                CompanyRedPacketStatisticsVO statisticsVO = statisticsMap.get(key);
+                if (statisticsVO != null) {
+                    statisticsVO.setFinishCount(vo.getFinishCount() != null ? vo.getFinishCount() : 0);
+                }
+            }
+        }
+
+        // 4. 合并红包金额
+        if (redPacketList != null && !redPacketList.isEmpty()) {
+            for (CompanyRedPacketStatisticsVO vo : redPacketList) {
+                Long key = vo.getCompanyUserId();
+                CompanyRedPacketStatisticsVO statisticsVO = statisticsMap.get(key);
+                if (statisticsVO != null) {
+                    statisticsVO.setRedPacketAmount(vo.getRedPacketAmount() != null ? vo.getRedPacketAmount() : new BigDecimal(0));
+                }
+            }
+        }
+
+        // 转换为列表返回
+        return new ArrayList<>(statisticsMap.values());
+    }
+
 }

+ 12 - 0
fs-service/src/main/resources/mapper/course/FsCourseRedPacketLogMapper.xml

@@ -312,6 +312,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
         group by rpl.company_user_id,rpl.course_id,rpl.video_id
     </select>
+    <select id="selectCourseFinishCount" resultType="com.fs.company.vo.CompanyRedPacketStatisticsVO">
+        select l.company_user_id, sum(l.amount) as redPacketAmount from fs_course_red_packet_log l where
+         l.company_id=#{companyId}
+
+        <if test="startDate != null and startDate != '' and endDate != null and endDate != ''">
+            and l.create_time &gt;= #{startDate} and l.create_time &lt;= #{endDate}
+        </if>
+        <if test="companyUserId !=null">
+            l.company_user_id = #{companyUserId}
+        </if>
+        group by l.company_user_id
+    </select>
 
 
     <insert id="batchInsert" parameterType="java.util.List">

+ 14 - 12
fs-service/src/main/resources/mapper/course/FsCourseWatchLogMapper.xml

@@ -1774,18 +1774,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             </if>
         group by l.company_user_id,l.course_id,l.video_id
     </select>
-
-
-
-
-
-
-
-
-
-
-
-
+    <select id="selectCourseFinishCount" resultType="com.fs.company.vo.CompanyRedPacketStatisticsVO">
+        select l.company_user_id,
+        SUM(CASE WHEN l.log_type = 2 THEN 1 ELSE 0 END) AS finishCount
+               from fs_course_watch_log l
+        where l.send_type = 1 and l.log_type = 2
+        and l.company_id=#{companyId}
+        <if test="startDate != null and startDate != '' and endDate != null and endDate != ''">
+            and l.create_time &gt;= #{startDate} and l.create_time &lt;= #{endDate}
+        </if>
+        <if test="companyUserId !=null">
+            l.company_user_id = #{companyUserId}
+        </if>
+        group by l.company_user_id
+    </select>
 
 
 </mapper>

+ 24 - 0
fs-service/src/main/resources/mapper/course/FsUserCompanyUserMapper.xml

@@ -248,4 +248,28 @@
         ORDER BY a.create_time ASC
         LIMIT 1
     </select>
+    <select id="selectSalesUserCount"  resultType="com.fs.company.vo.CompanyRedPacketStatisticsVO">
+        select count(distinct u.user_id) as userCount, ucu.company_user_id,cu.nick_name as userName from fs_user u
+        left join fs_user_company_user ucu on u.user_id = ucu.user_id and ucu.status=1
+        left join company_user cu on cu.user_id = ucu.company_user_id
+        where u.is_del = 0
+        and ucu.company_id = #{companyId}
+        <if test="companyUserId != null ">
+            and ucu.company_user_id = #{companyUserId}
+        </if>
+        group by ucu.company_user_id
+    </select>
+    <select id="selectSalesNewUserCount" resultType="com.fs.company.vo.CompanyRedPacketStatisticsVO">
+        select count(distinct u.user_id) as newUserCount, ucu.company_user_id from fs_user u
+        left join fs_user_company_user ucu on u.user_id = ucu.user_id and ucu.status=1
+        where u.is_del = 0
+        and ucu.company_id = #{companyId}
+        <if test="companyUserId != null ">
+            and ucu.company_user_id = #{companyUserId}
+        </if>
+        <if test="startDate != null and startDate != '' and endDate != null and endDate != ''">
+            and u.create_time &gt;= #{startDate} and u.create_time &lt;= #{endDate}
+        </if>
+        group by ucu.company_user_id
+    </select>
 </mapper>

+ 2 - 2
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -2524,7 +2524,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         fs_course_watch_log.user_id
     </select>
     <select id="selectAppSalesNewUserCountVO" resultType="com.fs.his.vo.AppSalesCourseStatisticsVO">
-        select count(distinct u.user_id) as newAppUserCount, u.company_user_id from fs_user u
+        select count(distinct u.user_id) as newAppUserCount, ucu.company_user_id from fs_user u
         left join fs_user_company_user ucu on u.user_id = ucu.user_id and ucu.status=1
         where u.is_del = 0
             <if test="companyId != null ">
@@ -2540,7 +2540,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </select>
 
     <select id="selectAppSalesUserCountVO" resultType="com.fs.his.vo.AppSalesCourseStatisticsVO">
-        select count(distinct u.user_id) as appUserCount, u.company_user_id from fs_user u
+        select count(distinct u.user_id) as appUserCount, ucu.company_user_id from fs_user u
         left join fs_user_company_user ucu on u.user_id = ucu.user_id and ucu.status=1
         where u.is_del = 0 and u.source is not null
             <if test="companyId != null ">