|
|
@@ -10,6 +10,7 @@ import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.fs.common.core.redis.RedisCache;
|
|
|
+import com.fs.common.exception.base.BusinessException;
|
|
|
import com.fs.common.utils.DateUtils;
|
|
|
import com.fs.common.utils.DictUtils;
|
|
|
import com.fs.common.utils.date.DateUtil;
|
|
|
@@ -1889,23 +1890,180 @@ public class FsCourseWatchLogServiceImpl extends ServiceImpl<FsCourseWatchLogMap
|
|
|
@Override
|
|
|
public List<AppSalesCourseStatisticsVO> selectAppSalesCourseStatisticsVO(FsCourseWatchLogStatisticsListParam param) {
|
|
|
|
|
|
- // 课程统计
|
|
|
- List<AppSalesCourseStatisticsVO> list = fsCourseWatchLogMapper.selectAppSalesCourseStatisticsVO(param);
|
|
|
+ // 校验时间为必输字段而且不能大于一个月
|
|
|
+ if (StringUtils.isEmpty(param.getStartDate()) || StringUtils.isEmpty(param.getEndDate())) {
|
|
|
+ throw new BusinessException("请选择时间");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 看课记录
|
|
|
+ CompletableFuture<List<AppSalesCourseStatisticsVO>> watchFuture = CompletableFuture.supplyAsync(() -> {
|
|
|
+ return fsCourseWatchLogMapper.selectAppSalesCourseStatisticsVO(param);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 答题记录
|
|
|
+ CompletableFuture<List<AppSalesCourseStatisticsVO>> answerFuture = CompletableFuture.supplyAsync(() -> {
|
|
|
+ return fsCourseAnswerLogsMapper.selectAppSalesAnswerStatisticsVO(param);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 红包记录
|
|
|
+ CompletableFuture<List<AppSalesCourseStatisticsVO>> redPacketFuture = CompletableFuture.supplyAsync(() -> {
|
|
|
+ return fsCourseRedPacketLogMapper.selectAppSalesRedPacketStatisticsVO(param);
|
|
|
+ });
|
|
|
+
|
|
|
+ CompletableFuture.allOf(watchFuture, answerFuture, redPacketFuture).join();
|
|
|
+
|
|
|
+ List<AppSalesCourseStatisticsVO> list = watchFuture.join();
|
|
|
+ if (CollectionUtils.isEmpty(list)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 整合数据
|
|
|
+ List<AppSalesCourseStatisticsVO> answerList = answerFuture.join();
|
|
|
+ List<AppSalesCourseStatisticsVO> redPacketList = redPacketFuture.join();
|
|
|
+
|
|
|
+ Map<String, AppSalesCourseStatisticsVO> dataMap = list.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ item -> item.getCompanyUserId() + "_" + item.getCourseId() + "_" + item.getVideoId(),
|
|
|
+ Function.identity(),
|
|
|
+ (e, r) -> e
|
|
|
+ ));
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(answerList)) {
|
|
|
+ Map<String, AppSalesCourseStatisticsVO> answerMap = answerList.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ item -> item.getCompanyUserId() + "_" + item.getCourseId() + "_" + item.getVideoId(),
|
|
|
+ Function.identity(),
|
|
|
+ (e, r) -> e
|
|
|
+ ));
|
|
|
+
|
|
|
+ for (Map.Entry<String, AppSalesCourseStatisticsVO> entry : dataMap.entrySet()) {
|
|
|
+ AppSalesCourseStatisticsVO vo = entry.getValue();
|
|
|
+ AppSalesCourseStatisticsVO answerVO = answerMap.get(entry.getKey());
|
|
|
+ if (answerVO != null) {
|
|
|
+ vo.setAnsweredCount(answerVO.getAnsweredCount());
|
|
|
+ vo.setCorrectCount(answerVO.getCorrectCount());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(redPacketList)) {
|
|
|
+ Map<String, AppSalesCourseStatisticsVO> redPacketMap = redPacketList.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ item -> item.getCompanyUserId() + "_" + item.getCourseId() + "_" + item.getVideoId(),
|
|
|
+ Function.identity(),
|
|
|
+ (e, r) -> e
|
|
|
+ ));
|
|
|
+
|
|
|
+ for (Map.Entry<String, AppSalesCourseStatisticsVO> entry : dataMap.entrySet()) {
|
|
|
+ AppSalesCourseStatisticsVO vo = entry.getValue();
|
|
|
+ AppSalesCourseStatisticsVO redPacketVO = redPacketMap.get(entry.getKey());
|
|
|
+ if (redPacketVO != null) {
|
|
|
+ vo.setRedPacketAmount(redPacketVO.getRedPacketAmount());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 答题统计
|
|
|
- List<AppSalesCourseStatisticsVO> answerList = fsCourseAnswerLogsMapper.selectAppSalesAnswerStatisticsVO(param);
|
|
|
+ // 获取销售的 app会员数和 新注册的会员数
|
|
|
+ CompletableFuture<List<AppSalesCourseStatisticsVO>> appNewUserFuture = CompletableFuture.supplyAsync(() -> {
|
|
|
+ return userMapper.selectAppSalesNewUserCountVO(param);
|
|
|
+ });
|
|
|
|
|
|
- // 红包统计
|
|
|
- List<AppSalesCourseStatisticsVO> redPacketList = fsCourseRedPacketLogMapper.selectAppSalesRedPacketStatisticsVO(param);
|
|
|
+ CompletableFuture<List<AppSalesCourseStatisticsVO>> appUserFuture = CompletableFuture.supplyAsync(() -> {
|
|
|
+ return userMapper.selectAppSalesUserCountVO(param);
|
|
|
+ });
|
|
|
|
|
|
+ CompletableFuture.allOf(appNewUserFuture, appUserFuture).join();
|
|
|
|
|
|
+ // 整合数据
|
|
|
+ List<AppSalesCourseStatisticsVO> appNewUserCountList = appNewUserFuture.join();
|
|
|
+ List<AppSalesCourseStatisticsVO> appUserCountList = appUserFuture.join();
|
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(appNewUserCountList)) {
|
|
|
+ Map<Long, Long> newUserCountMap = appNewUserCountList.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ AppSalesCourseStatisticsVO::getCompanyUserId,
|
|
|
+ AppSalesCourseStatisticsVO::getNewAppUserCount,
|
|
|
+ (e, r) -> e
|
|
|
+ ));
|
|
|
|
|
|
+ for (AppSalesCourseStatisticsVO vo : dataMap.values()) {
|
|
|
+ Long newAppUserCount = newUserCountMap.get(vo.getCompanyUserId());
|
|
|
+ if (newAppUserCount != null) {
|
|
|
+ vo.setNewAppUserCount(newAppUserCount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(appUserCountList)) {
|
|
|
+ Map<Long, Long> userCountMap = appUserCountList.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ AppSalesCourseStatisticsVO::getCompanyUserId,
|
|
|
+ AppSalesCourseStatisticsVO::getAppUserCount,
|
|
|
+ (e, r) -> e
|
|
|
+ ));
|
|
|
+
|
|
|
+ for (AppSalesCourseStatisticsVO vo : dataMap.values()) {
|
|
|
+ Long appUserCount = userCountMap.get(vo.getCompanyUserId());
|
|
|
+ if (appUserCount != null) {
|
|
|
+ vo.setAppUserCount(appUserCount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<AppSalesCourseStatisticsVO> resultList = new ArrayList<>(dataMap.values());
|
|
|
+ resultList.forEach(this::setDefaultValues);
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setDefaultValues(AppSalesCourseStatisticsVO vo) {
|
|
|
+ vo.setFinishedCount(vo.getFinishedCount() != null ? vo.getFinishedCount() : 0);
|
|
|
+ vo.setNotWatchedCount(vo.getNotWatchedCount() != null ? vo.getNotWatchedCount() : 0);
|
|
|
+ vo.setInterruptCount(vo.getInterruptCount() != null ? vo.getInterruptCount() : 0);
|
|
|
+ vo.setWatchingCount(vo.getWatchingCount() != null ? vo.getWatchingCount() : 0);
|
|
|
+ vo.setAnsweredCount(vo.getAnsweredCount() != null ? vo.getAnsweredCount() : 0);
|
|
|
+ vo.setCorrectCount(vo.getCorrectCount() != null ? vo.getCorrectCount() : 0);
|
|
|
+ vo.setNewAppUserCount(vo.getNewAppUserCount() != null ? vo.getNewAppUserCount() : 0L);
|
|
|
+ vo.setAppUserCount(vo.getAppUserCount() != null ? vo.getAppUserCount() : 0L);
|
|
|
+ vo.setRedPacketCount(vo.getRedPacketCount() != null ? vo.getRedPacketCount() : 0);
|
|
|
+
|
|
|
+ if (vo.getRedPacketAmount() == null) {
|
|
|
+ vo.setRedPacketAmount(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算完课率 = 完课数 / (完课数 + 未完课数 + 中断数 + 看课中数) * 100%,保留两位小数
|
|
|
+ int total = vo.getFinishedCount() + vo.getNotWatchedCount() + vo.getInterruptCount() + vo.getWatchingCount();
|
|
|
+ if (total > 0) {
|
|
|
+ BigDecimal finished = new BigDecimal(vo.getFinishedCount());
|
|
|
+ BigDecimal totalCount = new BigDecimal(total);
|
|
|
+ vo.setCompletionRate(finished.divide(totalCount, 4, RoundingMode.HALF_UP));
|
|
|
+ } else {
|
|
|
+ vo.setCompletionRate(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+ // 计算一下答题正确率
|
|
|
+ if (vo.getAnsweredCount() > 0) {
|
|
|
+ BigDecimal answered = new BigDecimal(vo.getAnsweredCount());
|
|
|
+ BigDecimal correct = new BigDecimal(vo.getCorrectCount());
|
|
|
+ vo.setCorrectRate(correct.divide(answered, 4, RoundingMode.HALF_UP));
|
|
|
+ } else {
|
|
|
+ vo.setCorrectRate(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
|
|
|
+ if (vo.getSalesName() == null) {
|
|
|
+ vo.setSalesName("");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vo.getCourseName() == null) {
|
|
|
+ vo.setCourseName("");
|
|
|
+ }
|
|
|
|
|
|
- return Collections.emptyList();
|
|
|
+ if (vo.getVideoTitle() == null) {
|
|
|
+ vo.setVideoTitle("");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 销售维度APP看课统计报表
|
|
|
*/
|