|
@@ -0,0 +1,262 @@
|
|
|
+package cn.newfeifan.mall.module.distri.service.consumptionerrorlog;
|
|
|
+
|
|
|
+import cn.newfeifan.mall.module.distri.controller.admin.consumptionerroruser.vo.ConsumptionErrorUserSaveReqVO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.applicationforwithdrawal.ApplicationForWithdrawalDO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.consumptionchangelog.ConsumptionChangeLogDO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.consumptiontopuplog.ConsumptionTopUpLogDO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.consumptiontransferlog.ConsumptionTransferLogDO;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.integral.IntegralDO;
|
|
|
+import cn.newfeifan.mall.module.distri.enums.ConsumptionEnum;
|
|
|
+import cn.newfeifan.mall.module.distri.service.applicationforwithdrawal.ApplicationForWithdrawalService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.consumptionchangelog.ConsumptionChangeLogService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.consumptionerroruser.ConsumptionErrorUserService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.consumptiontopuplog.ConsumptionTopUpLogService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.consumptiontransferlog.ConsumptionTransferLogService;
|
|
|
+import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
|
|
|
+import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
|
|
|
+import cn.newfeifan.mall.module.member.service.user.MemberUserService;
|
|
|
+import cn.newfeifan.mall.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
|
|
|
+import cn.newfeifan.mall.module.system.dal.dataobject.user.AdminUserDO;
|
|
|
+import cn.newfeifan.mall.module.system.enums.sms.SmsSceneEnum;
|
|
|
+import cn.newfeifan.mall.module.system.service.auth.AdminAuthService;
|
|
|
+import cn.newfeifan.mall.module.system.service.user.AdminUserService;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+
|
|
|
+import org.springframework.validation.annotation.Validated;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
+import java.util.concurrent.atomic.AtomicLong;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+import cn.newfeifan.mall.module.distri.controller.admin.consumptionerrorlog.vo.*;
|
|
|
+import cn.newfeifan.mall.module.distri.dal.dataobject.consumptionerrorlog.ConsumptionErrorLogDO;
|
|
|
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
|
|
|
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
|
|
|
+
|
|
|
+import cn.newfeifan.mall.module.distri.dal.mysql.consumptionerrorlog.ConsumptionErrorLogMapper;
|
|
|
+
|
|
|
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
+import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 消费分异动日志记录 Service 实现类
|
|
|
+ *
|
|
|
+ * @author 非繁人
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Validated
|
|
|
+public class ConsumptionErrorLogServiceImpl implements ConsumptionErrorLogService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ConsumptionErrorLogMapper consumptionErrorLogMapper;
|
|
|
+ @Resource
|
|
|
+ private ConsumptionErrorUserService consumptionErrorUserService;
|
|
|
+ @Resource
|
|
|
+ private ConsumptionTopUpLogService consumptionTopUpLogService;
|
|
|
+ @Resource
|
|
|
+ private ConsumptionChangeLogService consumptionChangeLogService;
|
|
|
+ @Resource
|
|
|
+ private ConsumptionTransferLogService consumptionTransferLogService;
|
|
|
+ @Resource
|
|
|
+ private ApplicationForWithdrawalService applicationForWithdrawalService;
|
|
|
+ @Resource
|
|
|
+ private IntegralService integralService;
|
|
|
+ @Resource
|
|
|
+ private MemberUserService memberUserService;
|
|
|
+ @Resource
|
|
|
+ private AdminUserService adminUserService;
|
|
|
+ @Resource
|
|
|
+ private AdminAuthService authService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Long createConsumptionErrorLog(ConsumptionErrorLogSaveReqVO createReqVO) {
|
|
|
+ // 插入
|
|
|
+ ConsumptionErrorLogDO consumptionErrorLog = BeanUtils.toBean(createReqVO, ConsumptionErrorLogDO.class);
|
|
|
+ consumptionErrorLogMapper.insert(consumptionErrorLog);
|
|
|
+ // 返回
|
|
|
+ return consumptionErrorLog.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateConsumptionErrorLog(ConsumptionErrorLogSaveReqVO updateReqVO) {
|
|
|
+ // 校验存在
|
|
|
+ validateConsumptionErrorLogExists(updateReqVO.getId());
|
|
|
+ // 更新
|
|
|
+ ConsumptionErrorLogDO updateObj = BeanUtils.toBean(updateReqVO, ConsumptionErrorLogDO.class);
|
|
|
+ consumptionErrorLogMapper.updateById(updateObj);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void deleteConsumptionErrorLog(Long id) {
|
|
|
+ // 校验存在
|
|
|
+ validateConsumptionErrorLogExists(id);
|
|
|
+ // 删除
|
|
|
+ consumptionErrorLogMapper.deleteById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateConsumptionErrorLogExists(Long id) {
|
|
|
+ if (consumptionErrorLogMapper.selectById(id) == null) {
|
|
|
+ throw exception(CONSUMPTION_ERROR_LOG_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ConsumptionErrorLogDO getConsumptionErrorLog(Long id) {
|
|
|
+ return consumptionErrorLogMapper.selectById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PageResult<ConsumptionErrorLogDO> getConsumptionErrorLogPage(ConsumptionErrorLogPageReqVO pageReqVO) {
|
|
|
+ return consumptionErrorLogMapper.selectPage(pageReqVO);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void calcEveryDayConsumptionPointsErrorLog() {
|
|
|
+ // 获取所有用户钱包
|
|
|
+ List<IntegralDO> integralDOS = integralService.selectAllUser();
|
|
|
+
|
|
|
+ // 每个用户的充值记录
|
|
|
+ Map<Long, Long> topUpLogMap = consumptionTopUpLogService.selectList().stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ ConsumptionTopUpLogDO::getUserId, // 按userid分组
|
|
|
+ Collectors.reducing(0L, // 初始化累加器
|
|
|
+ ConsumptionTopUpLogDO::getPracticalConsumptionPoints, // 获取每个对象的consumptionPoints
|
|
|
+ Long::sum // 累加函数
|
|
|
+ )
|
|
|
+ ));
|
|
|
+
|
|
|
+ // 用户的佣金转消费分记录
|
|
|
+ Map<Long, Long> changLogMap = consumptionChangeLogService.selectListByStatus(ConsumptionEnum.COMMISSION_TRANSITION.getType()).stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ ConsumptionChangeLogDO::getUserId, // 按userid分组
|
|
|
+ Collectors.reducing(0L, // 初始化累加器
|
|
|
+ ConsumptionChangeLogDO::getConsumptionPoints, // 获取每个对象的consumptionPoints
|
|
|
+ Long::sum // 累加函数
|
|
|
+ )
|
|
|
+ ));
|
|
|
+ // 用户的佣金转让记录(进账)
|
|
|
+ Map<Long, Long> recipientLogMap = consumptionTransferLogService.selectList().stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ ConsumptionTransferLogDO::getRecipientUserId, // 按userid分组
|
|
|
+ Collectors.reducing(0L, // 初始化累加器
|
|
|
+ ConsumptionTransferLogDO::getRecipientPoints, // 获取每个对象的consumptionPoints
|
|
|
+ Long::sum // 累加函数
|
|
|
+ )
|
|
|
+ ));
|
|
|
+
|
|
|
+ // 用户的提现记录
|
|
|
+ Map<Long, Long> withdrawalMap = applicationForWithdrawalService.selectList().stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ ApplicationForWithdrawalDO::getUserId, // 按userid分组
|
|
|
+ Collectors.reducing(0L, // 初始化累加器
|
|
|
+ ApplicationForWithdrawalDO::getWithdrawConsumption, // 获取每个对象的consumptionPoints
|
|
|
+ Long::sum // 累加函数
|
|
|
+ )
|
|
|
+ ));
|
|
|
+
|
|
|
+ Map<Long, Long> userTotalMap = integralDOS.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ IntegralDO::getUserId,
|
|
|
+ consumptionPoints -> 0L)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 遍历得到所有用户的应得消费分
|
|
|
+ topUpLogMap.forEach((userId, topUpPoints) -> userTotalMap.merge(userId, topUpPoints, Long::sum));
|
|
|
+ changLogMap.forEach((userId, topUpPoints) -> userTotalMap.merge(userId, topUpPoints, Long::sum));
|
|
|
+ recipientLogMap.forEach((userId, topUpPoints) -> userTotalMap.merge(userId, topUpPoints, Long::sum));
|
|
|
+ withdrawalMap.forEach((userId, topUpPoints) -> userTotalMap.merge(userId, topUpPoints, Long::sum));
|
|
|
+
|
|
|
+ // 用户可用消费分
|
|
|
+ Map<Long, Long> currentMap = integralDOS.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ IntegralDO::getUserId,
|
|
|
+ IntegralDO::getConsumptionPoints)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 用户已用(购买商品的)消费分
|
|
|
+ Map<Long, Long> uesdMap = consumptionChangeLogService.selectListByStatus(ConsumptionEnum.PAY_ORDER.getType()).stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ ConsumptionChangeLogDO::getUserId, // 按userid分组
|
|
|
+ Collectors.reducing(0L, // 初始化累加器
|
|
|
+ ConsumptionChangeLogDO::getConsumptionPoints, // 获取每个对象的consumptionPoints
|
|
|
+ Long::sum // 累加函数
|
|
|
+ )
|
|
|
+ ));
|
|
|
+ uesdMap.forEach((k, v) -> uesdMap.put(k, v * -1));
|
|
|
+
|
|
|
+ // 用户转让的消费分(出账)
|
|
|
+ Map<Long, Long> transferLogMap = consumptionTransferLogService.selectList().stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ ConsumptionTransferLogDO::getTransferUserId, // 按userid分组
|
|
|
+ Collectors.reducing(0L, // 初始化累加器
|
|
|
+ ConsumptionTransferLogDO::getConsumptionPoints, // 获取每个对象的consumptionPoints
|
|
|
+ Long::sum // 累加函数
|
|
|
+ )
|
|
|
+ ));
|
|
|
+ transferLogMap.forEach((k, v) -> transferLogMap.put(k, v * -1));
|
|
|
+
|
|
|
+ Map<Long, Long> nowConsumptionPointsMap = new HashMap<>();
|
|
|
+ currentMap.forEach((userId, topUpPoints) -> nowConsumptionPointsMap.merge(userId, topUpPoints, Long::sum));
|
|
|
+
|
|
|
+ uesdMap.forEach((userId, topUpPoints) -> nowConsumptionPointsMap.merge(userId, topUpPoints, Long::sum));
|
|
|
+
|
|
|
+ transferLogMap.forEach((userId, consumptionPoints) -> nowConsumptionPointsMap.merge(userId, consumptionPoints, Long::sum));
|
|
|
+
|
|
|
+ AtomicLong errorConsumptionPoints = new AtomicLong(0L); // 错误消费分
|
|
|
+ AtomicInteger errorUserCount = new AtomicInteger(0); // 错误用户数
|
|
|
+
|
|
|
+ Map<Long, Long> userMap = new HashMap<>();
|
|
|
+ // 遍历所有的用户,判断哪个用户的消费分有误
|
|
|
+ userTotalMap.forEach((userId, topUpPoints) -> {
|
|
|
+ // 如果实际消费分大于应得消费分,则视为异动用户
|
|
|
+ if (nowConsumptionPointsMap.get(userId) > topUpPoints) {
|
|
|
+ long points = nowConsumptionPointsMap.get(userId) - topUpPoints;
|
|
|
+ errorConsumptionPoints.addAndGet(points);
|
|
|
+ errorUserCount.addAndGet(1);
|
|
|
+
|
|
|
+ // 记录用户
|
|
|
+ userMap.put(userId, points);
|
|
|
+ System.out.println("用户id:" + userId + "应得消费分:" + topUpPoints + " 实际消费分:" + currentMap.get(userId));
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 插入异动日志
|
|
|
+ if (errorConsumptionPoints.get() > 0 && errorUserCount.get() > 0) {
|
|
|
+ ConsumptionErrorLogDO consumptionErrorLogDO = new ConsumptionErrorLogDO()
|
|
|
+ .setErrorConsumptionPointsTotal(errorConsumptionPoints.get())
|
|
|
+ .setErrorUsersCount(errorUserCount.get());
|
|
|
+ consumptionErrorLogMapper.insert(consumptionErrorLogDO);
|
|
|
+
|
|
|
+ userMap.forEach((userId, points) -> {
|
|
|
+ MemberUserDO user = memberUserService.getUser(userId);
|
|
|
+ ConsumptionErrorUserSaveReqVO consumptionErrorLogUserDO = ConsumptionErrorUserSaveReqVO.builder()
|
|
|
+ .consumptionErrorLogId(consumptionErrorLogDO.getId())
|
|
|
+ .userId(userId)
|
|
|
+ .userName(user.getUsername())
|
|
|
+ .consumptionPointsTotal(userTotalMap.get(userId))
|
|
|
+ .nowConsumptionPointsTotal(nowConsumptionPointsMap.get(userId))
|
|
|
+ .currentConsumptionPointsTotal(currentMap.get(userId))
|
|
|
+ .usedConsumptionPointsTotal(uesdMap.get(userId))
|
|
|
+ .transferConsumptionPointsTotal(transferLogMap.get(userId))
|
|
|
+ .errorConsumptionPointsTotal(points)
|
|
|
+ .build();
|
|
|
+ consumptionErrorUserService.createConsumptionErrorUser(consumptionErrorLogUserDO);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 短信通知系统管理员
|
|
|
+ for (AdminUserDO superAdminUser : adminUserService.getSuperAdminUsers()) {
|
|
|
+ System.out.println("系统管理员手机号:" + superAdminUser.getMobile());
|
|
|
+ authService.sendSmsCode(AuthSmsSendReqVO.builder()
|
|
|
+ .mobile(superAdminUser.getMobile())
|
|
|
+ .scene(SmsSceneEnum.CONSUMPTION_POINTS_ERROR_WARNING.getScene())
|
|
|
+ .build());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|