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