UserCompanyCreditBillSchedule.java 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package com.gree.mall.manager.schedule;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.core.date.DateTime;
  4. import cn.hutool.core.date.DateUtil;
  5. import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  6. import com.gree.mall.manager.commonmapper.LockQueryMapper;
  7. import com.gree.mall.manager.enums.TransactionTypeEnum;
  8. import com.gree.mall.manager.enums.workorder.OrderBaseStatusEnum;
  9. import com.gree.mall.manager.plus.entity.PgOrderBase;
  10. import com.gree.mall.manager.plus.entity.UserCompanyCredit;
  11. import com.gree.mall.manager.plus.entity.UserCompanyCreditBill;
  12. import com.gree.mall.manager.plus.entity.UserCompanyCreditBillItem;
  13. import com.gree.mall.manager.plus.service.UserCompanyCreditBillItemService;
  14. import com.gree.mall.manager.plus.service.UserCompanyCreditBillService;
  15. import com.gree.mall.manager.plus.service.UserCompanyCreditService;
  16. import lombok.extern.slf4j.Slf4j;
  17. import org.apache.commons.lang3.StringUtils;
  18. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  19. import org.springframework.scheduling.annotation.Scheduled;
  20. import org.springframework.stereotype.Component;
  21. import org.springframework.stereotype.Service;
  22. import org.springframework.transaction.annotation.Transactional;
  23. import javax.annotation.Resource;
  24. import java.math.BigDecimal;
  25. import java.util.Date;
  26. import java.util.List;
  27. import java.util.Objects;
  28. import java.util.stream.Collectors;
  29. /**
  30. * 用户商户授信账单相关定时任务
  31. * @author :fengcy
  32. * @description:TODO
  33. * @date :2025/10/21 17:30
  34. */
  35. @ConditionalOnProperty(name = "schedule.enable", havingValue = "true", matchIfMissing = true)
  36. @Component
  37. @Slf4j
  38. //@Service
  39. public class UserCompanyCreditBillSchedule {
  40. @Resource
  41. UserCompanyCreditBillService userCompanyCreditBillService;
  42. @Resource
  43. UserCompanyCreditBillItemService userCompanyCreditBillItemService;
  44. @Resource
  45. LockQueryMapper lockQueryMapper;
  46. /**
  47. * 每日凌晨1点执行,检查是否有用户需要在当天生成账单
  48. */
  49. @Transactional
  50. @Scheduled(cron = "0 0 1 * * ?")
  51. public void generateBillsOnBillingDay(String inDate){
  52. // DateTime curDate = DateUtil.parseDate(inDate);
  53. DateTime curDate = DateUtil.date();
  54. int currentDay = curDate.dayOfMonth();
  55. final int lastDayOfMonth = DateUtil.endOfMonth(curDate).dayOfMonth();
  56. // 直接判断:1-28号 或 实际月末(无论月末是28/29/30/31)
  57. if (currentDay >= 1 && currentDay <= 28 || currentDay == lastDayOfMonth) {
  58. // 处理月末特殊情况
  59. if (currentDay == lastDayOfMonth) {
  60. currentDay = 29;
  61. }
  62. // 获取账单日为今天的所有用户商户授信关系
  63. List<UserCompanyCredit> userCompanyCreditList = lockQueryMapper.findByBillingDay(currentDay);
  64. if (CollectionUtil.isNotEmpty(userCompanyCreditList)) {
  65. for (UserCompanyCredit credit : userCompanyCreditList) {
  66. generateBillForUserCompany(credit, curDate);
  67. }
  68. }
  69. }
  70. }
  71. private void generateBillForUserCompany(UserCompanyCredit credit, DateTime curDate) {
  72. final String userId = credit.getUserId();
  73. final String companyWechatId = credit.getCompanyWechatId();
  74. DateTime today = curDate;
  75. // DateTime today = DateUtil.date();
  76. // 获取授信记录明细开始时间
  77. Date startTime;
  78. // 获取授信记录明细结束时间
  79. Date endTime = DateUtil.endOfDay(DateUtil.offsetDay(today, -1));
  80. if (Objects.isNull(credit.getLastBillingDate())) {
  81. // 第一次一成账单开始时间取授信创建时间
  82. startTime = credit.getCreateTime();
  83. } else {
  84. // 取上次的结束时间(已加1秒,比如上次获取授信记录明细结束时间为2025-10-22 23:59:59, 再加1秒等于下次执行的开始时间2025-10-23 00:00:00)
  85. startTime = credit.getLastBillingDate();
  86. }
  87. if (startTime.getTime() > endTime.getTime()) {
  88. // 如果开始时间比结束时间大就返回
  89. return;
  90. }
  91. // 处理月末情况
  92. if (credit.getBillingDay() == 29) {
  93. endTime = DateUtil.endOfDay(DateUtil.offsetDay(DateUtil.endOfMonth(today), -1));
  94. }
  95. // 查询该周期内示对账的消费明细
  96. List<UserCompanyCreditBillItem> billItemList = userCompanyCreditBillItemService.lambdaQuery()
  97. .select(UserCompanyCreditBillItem::getId, UserCompanyCreditBillItem::getTransactionType, UserCompanyCreditBillItem::getAmount)
  98. .eq(UserCompanyCreditBillItem::getUserId, userId)
  99. .eq(UserCompanyCreditBillItem::getCompanyWechatId, companyWechatId)
  100. .between(UserCompanyCreditBillItem::getCreateTime, startTime, endTime)
  101. .isNull(UserCompanyCreditBillItem::getUserCompanyCreditBillId)
  102. .list();
  103. if (billItemList.isEmpty()) {
  104. // 没有需要对账的明细
  105. return;
  106. }
  107. // 计算总金额
  108. BigDecimal totalAmount = billItemList.stream()
  109. .map(item -> {
  110. if (item.getTransactionType().equals(TransactionTypeEnum.CONSUMPTION.getKey())) {
  111. return item.getAmount();
  112. } else if (item.getTransactionType().equals(TransactionTypeEnum.REFUND.getKey())) {
  113. return item.getAmount().negate();
  114. } else if (item.getTransactionType().equals(TransactionTypeEnum.REPAYMENT.getKey())) {
  115. return (StringUtils.isBlank(item.getRepaymentBillId())) ? item.getAmount().negate() : BigDecimal.ZERO;
  116. }
  117. return BigDecimal.ZERO;
  118. })
  119. .reduce(BigDecimal.ZERO, BigDecimal::add);
  120. // 检查总还款金额少于0的就等于0否则就是总金额
  121. totalAmount = totalAmount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : totalAmount;
  122. // 计算还款日(账单日+账期天数)
  123. Date dueDate = DateUtil.offsetDay(today, credit.getPaymentGracePeriod());
  124. // 创建账单
  125. UserCompanyCreditBill bill = new UserCompanyCreditBill();
  126. bill.setBillId(IdWorker.getIdStr())
  127. .setUserCompanyCreditId(credit.getId())
  128. .setUserId(credit.getUserId())
  129. .setCompanyWechatId(credit.getCompanyWechatId())
  130. .setCompanyWechatName(credit.getCompanyWechatName())
  131. .setAmount(totalAmount)
  132. .setRemainingAmount(totalAmount)
  133. .setCreateDate(DateUtil.parseDate(DateUtil.formatDate(today)))
  134. .setDueDate(dueDate)
  135. .setIsPaid(totalAmount.compareTo(BigDecimal.ZERO) <= 0)
  136. .setRemark(DateUtil.formatDateTime(startTime) + " - " + DateUtil.formatDateTime(endTime))
  137. .insert();
  138. userCompanyCreditBillItemService.lambdaUpdate()
  139. .set(UserCompanyCreditBillItem::getUserCompanyCreditBillId, bill.getBillId())
  140. .in(UserCompanyCreditBillItem::getId, billItemList.stream()
  141. .map(UserCompanyCreditBillItem::getId)
  142. .collect(Collectors.toList()))
  143. .update();
  144. // 更新用户商户授信记录
  145. DateTime offsetSecond = DateUtil.beginOfDay(DateUtil.offsetDay(endTime, 1));
  146. credit.setLastBillingDate(offsetSecond)
  147. .updateById();
  148. }
  149. }