修改同步计费

This commit is contained in:
wuweihua
2026-09-23 15:08:21 +08:00
parent b02af14179
commit 9b537c7a27
3 changed files with 110 additions and 122 deletions
@@ -50,14 +50,5 @@ public interface IPrcOrderBillService
*/
void clearCreditArrearsByAmount(String customerCode, BigDecimal amount);
/**
* 异步执行体:实际清欠并写 ES日志(供异步 Runner 调用)。
*
* @return 已更新为 NORMAL 的订单数
*/
int processClearCreditArrearsByAmount(String customerCode, BigDecimal amount);
/** 异步清欠失败时写 ES 摘要日志 */
void logClearCreditArrearsFail(String customerCode, BigDecimal amount, String errorMessage);
}
@@ -530,113 +530,6 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
}
}
/**
* 异步执行:按下单时间升序 FIFO 清欠,逐单与摘要日志写入 ES。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int processClearCreditArrearsByAmount(String customerCode, BigDecimal amount)
{
String code = StringUtils.trim(customerCode);
if (StringUtils.isEmpty(code))
{
throw new ServiceException("客户代码不能为空");
}
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0)
{
throw new ServiceException("入账金额必须大于0");
}
BigDecimal remaining = amount;
List<PrcOrderBill> bills = orderBillMapper.selectArrearsByCustomerCode(code,
BillCreditArrearsStatus.ARREARS.getCode());
if (bills == null || bills.isEmpty())
{
saveArrearsClearSummaryEsLog(code, amount, 0, remaining, true, "no arrears orders");
return 0;
}
String normal = BillCreditArrearsStatus.NORMAL.getCode();
int updated = 0;
for (PrcOrderBill bill : bills)
{
BigDecimal orderAmt = nz(bill.getIncomeTotal());
// 当前订单额度大于剩余金额:停止更新
if (orderAmt.compareTo(remaining) > 0)
{
break;
}
orderBillMapper.updateCreditArrearsStatus(bill.getBillId(), normal, "receipt");
remaining = remaining.subtract(orderAmt);
updated++;
saveArrearsClearOrderEsLog(bill, amount, orderAmt, remaining, true, null);
if (remaining.compareTo(BigDecimal.ZERO) <= 0)
{
break;
}
}
saveArrearsClearSummaryEsLog(code, amount, updated, remaining, true, null);
return updated;
}
@Override
public void logClearCreditArrearsFail(String customerCode, BigDecimal amount, String errorMessage)
{
saveArrearsClearSummaryEsLog(StringUtils.trim(customerCode), amount, 0, amount, false, errorMessage);
}
private void saveArrearsClearSummaryEsLog(String customerCode, BigDecimal amount, int updated,
BigDecimal remaining, boolean success, String note)
{
if (billSearchStore == null || StringUtils.isEmpty(customerCode))
{
return;
}
JSONObject req = new JSONObject();
req.put("action", "CLEAR_ARREARS");
req.put("scope", "SUMMARY");
req.put("customerCode", customerCode);
req.put("amount", amount);
JSONObject resp = new JSONObject();
resp.put("success", Boolean.valueOf(success));
resp.put("updatedCount", Integer.valueOf(updated));
resp.put("remainingAmount", remaining);
if (StringUtils.isNotEmpty(note))
{
resp.put("msg", note);
}
String status = success ? EsBizLogSupport.STATUS_SUCCESS : EsBizLogSupport.STATUS_FAIL;
String err = success ? null : EsBizLogSupport.cut(note);
billSearchStore.save(EsLogType.ARREARS, customerCode, req.toJSONString(), resp.toJSONString(), status, err);
}
private void saveArrearsClearOrderEsLog(PrcOrderBill bill, BigDecimal batchAmount, BigDecimal orderAmt,
BigDecimal remaining, boolean success, String errorMessage)
{
if (billSearchStore == null || bill == null || StringUtils.isEmpty(bill.getOrderNo()))
{
return;
}
JSONObject req = new JSONObject();
req.put("action", "CLEAR_ARREARS");
req.put("scope", "ORDER");
req.put("orderNo", bill.getOrderNo());
req.put("billId", bill.getBillId());
req.put("customerCode", bill.getCustomerCode());
req.put("batchAmount", batchAmount);
req.put("orderIncomeTotal", orderAmt);
req.put("fromStatus", BillCreditArrearsStatus.ARREARS.getCode());
req.put("toStatus", BillCreditArrearsStatus.NORMAL.getCode());
JSONObject resp = new JSONObject();
resp.put("success", Boolean.valueOf(success));
resp.put("remainingAmount", remaining);
if (StringUtils.isNotEmpty(errorMessage))
{
resp.put("msg", errorMessage);
}
String status = success ? EsBizLogSupport.STATUS_SUCCESS : EsBizLogSupport.STATUS_FAIL;
String err = success ? null : EsBizLogSupport.cut(errorMessage);
billSearchStore.save(EsLogType.ARREARS, bill.getOrderNo(), req.toJSONString(), resp.toJSONString(), status, err);
}
private TmsOrderBillMatchType resolveTmsMatchType(String identifier, PrcOrderBill bill)
{
if (identifier.equalsIgnoreCase(StringUtils.trim(bill.getOrderNo())))
@@ -1,16 +1,25 @@
package com.ruoyi.price.task;
import java.math.BigDecimal;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.price.service.IPrcOrderBillService;
import com.ruoyi.price.domain.PrcOrderBill;
import com.ruoyi.price.enums.BillCreditArrearsStatus;
import com.ruoyi.price.mapper.PrcOrderBillMapper;
import com.ruoyi.price.search.EsBizLogSupport;
import com.ruoyi.price.search.EsLogType;
import com.ruoyi.price.search.IBillSearchStore;
/**
* 异步清除订单额度欠费状态(余额充值等审核入账后)。
* 自行注入 Mapper / ES,避免与 IPrcOrderBillService 循环依赖。
*/
@Component
public class PrcCreditArrearsClearAsyncRunner
@@ -18,27 +27,122 @@ public class PrcCreditArrearsClearAsyncRunner
private static final Logger log = LoggerFactory.getLogger(PrcCreditArrearsClearAsyncRunner.class);
@Autowired
private IPrcOrderBillService orderBillService;
private PrcOrderBillMapper orderBillMapper;
@Autowired(required = false)
private IBillSearchStore billSearchStore;
@Async("threadPoolTaskExecutor")
@Transactional(rollbackFor = Exception.class)
public void run(String customerCode, BigDecimal amount)
{
String code = StringUtils.trim(customerCode);
try
{
int updated = orderBillService.processClearCreditArrearsByAmount(customerCode, amount);
if (StringUtils.isEmpty(code) || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0)
{
return;
}
BigDecimal remaining = amount;
List<PrcOrderBill> bills = orderBillMapper.selectArrearsByCustomerCode(code,
BillCreditArrearsStatus.ARREARS.getCode());
if (bills == null || bills.isEmpty())
{
saveSummaryEsLog(code, amount, 0, remaining, true, "no arrears orders");
return;
}
String normal = BillCreditArrearsStatus.NORMAL.getCode();
int updated = 0;
for (PrcOrderBill bill : bills)
{
BigDecimal orderAmt = nz(bill.getIncomeTotal());
if (orderAmt.compareTo(remaining) > 0)
{
break;
}
orderBillMapper.updateCreditArrearsStatus(bill.getBillId(), normal, "receipt");
remaining = remaining.subtract(orderAmt);
updated++;
saveOrderEsLog(bill, amount, orderAmt, remaining, true, null);
if (remaining.compareTo(BigDecimal.ZERO) <= 0)
{
break;
}
}
saveSummaryEsLog(code, amount, updated, remaining, true, null);
log.info("async clear credit arrears done, customerCode={}, amount={}, updated={}",
customerCode, amount, Integer.valueOf(updated));
code, amount, Integer.valueOf(updated));
}
catch (Exception e)
{
log.error("async clear credit arrears failed, customerCode={}, amount={}",
customerCode, amount, e);
code, amount, e);
String msg = e.getMessage();
if (StringUtils.isEmpty(msg))
{
msg = e.getClass().getSimpleName();
}
orderBillService.logClearCreditArrearsFail(customerCode, amount, msg);
saveSummaryEsLog(code, amount, 0, amount, false, msg);
throw e;
}
}
private void saveSummaryEsLog(String customerCode, BigDecimal amount, int updated,
BigDecimal remaining, boolean success, String note)
{
if (billSearchStore == null || StringUtils.isEmpty(customerCode))
{
return;
}
JSONObject req = new JSONObject();
req.put("action", "CLEAR_ARREARS");
req.put("scope", "SUMMARY");
req.put("customerCode", customerCode);
req.put("amount", amount);
JSONObject resp = new JSONObject();
resp.put("success", Boolean.valueOf(success));
resp.put("updatedCount", Integer.valueOf(updated));
resp.put("remainingAmount", remaining);
if (StringUtils.isNotEmpty(note))
{
resp.put("msg", note);
}
String status = success ? EsBizLogSupport.STATUS_SUCCESS : EsBizLogSupport.STATUS_FAIL;
String err = success ? null : EsBizLogSupport.cut(note);
billSearchStore.save(EsLogType.ARREARS, customerCode, req.toJSONString(), resp.toJSONString(), status, err);
}
private void saveOrderEsLog(PrcOrderBill bill, BigDecimal batchAmount, BigDecimal orderAmt,
BigDecimal remaining, boolean success, String errorMessage)
{
if (billSearchStore == null || bill == null || StringUtils.isEmpty(bill.getOrderNo()))
{
return;
}
JSONObject req = new JSONObject();
req.put("action", "CLEAR_ARREARS");
req.put("scope", "ORDER");
req.put("orderNo", bill.getOrderNo());
req.put("billId", bill.getBillId());
req.put("customerCode", bill.getCustomerCode());
req.put("batchAmount", batchAmount);
req.put("orderIncomeTotal", orderAmt);
req.put("fromStatus", BillCreditArrearsStatus.ARREARS.getCode());
req.put("toStatus", BillCreditArrearsStatus.NORMAL.getCode());
JSONObject resp = new JSONObject();
resp.put("success", Boolean.valueOf(success));
resp.put("remainingAmount", remaining);
if (StringUtils.isNotEmpty(errorMessage))
{
resp.put("msg", errorMessage);
}
String status = success ? EsBizLogSupport.STATUS_SUCCESS : EsBizLogSupport.STATUS_FAIL;
String err = success ? null : EsBizLogSupport.cut(errorMessage);
billSearchStore.save(EsLogType.ARREARS, bill.getOrderNo(), req.toJSONString(), resp.toJSONString(), status, err);
}
private static BigDecimal nz(BigDecimal v)
{
return v == null ? BigDecimal.ZERO : v;
}
}