| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- package com.gree.mall.manager.schedule;
- import cn.hutool.core.collection.CollectionUtil;
- import cn.hutool.core.date.DateTime;
- import cn.hutool.core.date.DateUtil;
- import com.baomidou.mybatisplus.core.toolkit.IdWorker;
- import com.gree.mall.manager.commonmapper.LockQueryMapper;
- import com.gree.mall.manager.enums.TransactionTypeEnum;
- import com.gree.mall.manager.enums.workorder.OrderBaseStatusEnum;
- import com.gree.mall.manager.plus.entity.PgOrderBase;
- import com.gree.mall.manager.plus.entity.UserCompanyCredit;
- import com.gree.mall.manager.plus.entity.UserCompanyCreditBill;
- import com.gree.mall.manager.plus.entity.UserCompanyCreditBillItem;
- import com.gree.mall.manager.plus.service.UserCompanyCreditBillItemService;
- import com.gree.mall.manager.plus.service.UserCompanyCreditBillService;
- import com.gree.mall.manager.plus.service.UserCompanyCreditService;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.util.CollectionUtils;
- import javax.annotation.Resource;
- import java.math.BigDecimal;
- import java.util.Date;
- import java.util.List;
- import java.util.Objects;
- import java.util.stream.Collectors;
- /**
- * 用户商户授信账单相关定时任务
- * @author :fengcy
- * @description:TODO
- * @date :2025/10/21 17:30
- */
- @ConditionalOnProperty(name = "schedule.enable", havingValue = "true", matchIfMissing = true)
- @Component
- @Slf4j
- //@Service
- public class UserCompanyCreditBillSchedule {
- @Resource
- UserCompanyCreditBillService userCompanyCreditBillService;
- @Resource
- UserCompanyCreditBillItemService userCompanyCreditBillItemService;
- @Resource
- LockQueryMapper lockQueryMapper;
- /**
- * 每日凌晨1点执行,检查是否有用户需要在当天生成账单
- */
- @Transactional
- @Scheduled(cron = "0 0 1 * * ?")
- public void generateBillsOnBillingDay(String inDate){
- // DateTime curDate = DateUtil.parseDate(inDate);
- DateTime curDate = DateUtil.date();
- int currentDay = curDate.dayOfMonth();
- final int lastDayOfMonth = DateUtil.endOfMonth(curDate).dayOfMonth();
- // 直接判断:1-28号 或 实际月末(无论月末是28/29/30/31)
- if (currentDay >= 1 && currentDay <= 28 || currentDay == lastDayOfMonth) {
- // 处理月末特殊情况
- if (currentDay == lastDayOfMonth) {
- currentDay = 29;
- }
- // 获取账单日为今天的所有用户商户授信关系
- List<UserCompanyCredit> userCompanyCreditList = lockQueryMapper.findByBillingDay(currentDay);
- if (CollectionUtil.isNotEmpty(userCompanyCreditList)) {
- for (UserCompanyCredit credit : userCompanyCreditList) {
- generateBillForUserCompany(credit, curDate);
- }
- }
- }
- }
- private void generateBillForUserCompany(UserCompanyCredit credit, DateTime curDate) {
- final String userId = credit.getUserId();
- final String companyWechatId = credit.getCompanyWechatId();
- DateTime today = curDate;
- // DateTime today = DateUtil.date();
- // 获取授信记录明细开始时间
- Date startTime;
- // 获取授信记录明细结束时间
- Date endTime = DateUtil.endOfDay(DateUtil.offsetDay(today, -1));
- if (Objects.isNull(credit.getLastBillingDate())) {
- // 第一次一成账单开始时间取授信创建时间
- startTime = credit.getCreateTime();
- } else {
- // 取上次的结束时间(已加1秒,比如上次获取授信记录明细结束时间为2025-10-22 23:59:59, 再加1秒等于下次执行的开始时间2025-10-23 00:00:00)
- startTime = credit.getLastBillingDate();
- }
- if (startTime.getTime() > endTime.getTime()) {
- // 如果开始时间比结束时间大就返回
- return;
- }
- // 处理月末情况
- if (credit.getBillingDay() == 29) {
- endTime = DateUtil.endOfDay(DateUtil.offsetDay(DateUtil.endOfMonth(today), -1));
- }
- // 查询该周期内示对账的消费明细
- List<UserCompanyCreditBillItem> billItemList = userCompanyCreditBillItemService.lambdaQuery()
- .select(UserCompanyCreditBillItem::getId, UserCompanyCreditBillItem::getTransactionType, UserCompanyCreditBillItem::getAmount)
- .eq(UserCompanyCreditBillItem::getUserId, userId)
- .eq(UserCompanyCreditBillItem::getCompanyWechatId, companyWechatId)
- .between(UserCompanyCreditBillItem::getCreateTime, startTime, endTime)
- .isNull(UserCompanyCreditBillItem::getUserCompanyCreditBillId)
- .list();
- if (billItemList.isEmpty()) {
- // 没有需要对账的明细
- return;
- }
- // 计算总金额
- BigDecimal totalAmount = billItemList.stream()
- .map(item -> {
- if (item.getTransactionType().equals(TransactionTypeEnum.CONSUMPTION.getKey())) {
- return item.getAmount();
- } else if (item.getTransactionType().equals(TransactionTypeEnum.REFUND.getKey())) {
- return item.getAmount().negate();
- } else if (item.getTransactionType().equals(TransactionTypeEnum.REPAYMENT.getKey())) {
- return (StringUtils.isBlank(item.getRepaymentBillId())) ? item.getAmount().negate() : BigDecimal.ZERO;
- }
- return BigDecimal.ZERO;
- })
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- // 检查总还款金额少于0的就等于0否则就是总金额
- totalAmount = totalAmount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : totalAmount;
- // 计算还款日(账单日+账期天数)
- Date dueDate = DateUtil.offsetDay(today, credit.getPaymentGracePeriod());
- // 创建账单
- UserCompanyCreditBill bill = new UserCompanyCreditBill();
- bill.setBillId(IdWorker.getIdStr())
- .setUserCompanyCreditId(credit.getId())
- .setUserId(credit.getUserId())
- .setCompanyWechatId(credit.getCompanyWechatId())
- .setCompanyWechatName(credit.getCompanyWechatName())
- .setAmount(totalAmount)
- .setRemainingAmount(totalAmount)
- .setCreateDate(DateUtil.parseDate(DateUtil.formatDate(today)))
- .setDueDate(dueDate)
- .setIsPaid(totalAmount.compareTo(BigDecimal.ZERO) <= 0)
- .setRemark(DateUtil.formatDateTime(startTime) + " - " + DateUtil.formatDateTime(endTime))
- .insert();
- userCompanyCreditBillItemService.lambdaUpdate()
- .set(UserCompanyCreditBillItem::getUserCompanyCreditBillId, bill.getBillId())
- .in(UserCompanyCreditBillItem::getId, billItemList.stream()
- .map(UserCompanyCreditBillItem::getId)
- .collect(Collectors.toList()))
- .update();
- // 更新用户商户授信记录
- DateTime offsetSecond = DateUtil.beginOfDay(DateUtil.offsetDay(endTime, 1));
- credit.setLastBillingDate(offsetSecond)
- .updateById();
- }
- }
|