Implement batch fee management features in BillingController, including preview, submission, and task retrieval. Update related services and mappers to support batch processing. Add necessary error messages in properties file and enhance front-end API for batch operations.

This commit is contained in:
wuweihua
2026-10-09 10:28:29 +08:00
parent 95df65b4f6
commit 5b4cbaffd6
15 changed files with 1014 additions and 23 deletions
@@ -0,0 +1,137 @@
package com.bms.price.task;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import com.bms.common.core.redis.RedisCache;
import com.bms.common.utils.StringUtils;
import com.bms.price.domain.BatchAddIncomeBillFeeTask;
import com.bms.price.domain.vo.AddIncomeBillFeeRequest;
import com.bms.price.service.IPrcOrderBillService;
/**
* Async runner: add the same manual income fee to many order bills.
*/
@Component
public class PrcBatchAddIncomeFeeAsyncRunner
{
private static final Logger log = LoggerFactory.getLogger(PrcBatchAddIncomeFeeAsyncRunner.class);
public static final String CACHE_KEY_PREFIX = "price:billing:fee:batch:task:";
public static final int TTL_MINUTES = 60;
@Autowired
@Lazy
private IPrcOrderBillService orderBillService;
@Autowired
private RedisCache redisCache;
@Async("threadPoolTaskExecutor")
public void run(String taskId, List<String> billIds, Long scId, String feeType, BigDecimal amount,
String currency, String remark)
{
int total = billIds == null ? 0 : billIds.size();
int success = 0;
int fail = 0;
StringBuilder failTips = new StringBuilder();
try
{
put(taskId, BatchAddIncomeBillFeeTask.STATUS_RUNNING, 1, "running", null, total, 0, 0);
if (total == 0)
{
put(taskId, BatchAddIncomeBillFeeTask.STATUS_FAIL, 100, "failed", "no bills", 0, 0, 0);
return;
}
for (int i = 0; i < total; i++)
{
String billId = billIds.get(i);
try
{
AddIncomeBillFeeRequest req = new AddIncomeBillFeeRequest();
req.setBillId(billId);
req.setScId(scId);
req.setFeeType(feeType);
req.setAmount(amount);
req.setCurrency(currency);
req.setRemark(remark);
orderBillService.addIncomeFee(req);
success++;
}
catch (Exception e)
{
fail++;
if (failTips.length() < 800)
{
String tip = e.getMessage();
if (StringUtils.isEmpty(tip))
{
tip = e.getClass().getSimpleName();
}
if (failTips.length() > 0)
{
failTips.append("; ");
}
failTips.append(billId).append(":").append(tip);
}
log.warn("batch add fee failed taskId={} billId={}", taskId, billId, e);
}
int percent = Math.min(99, (int) Math.floor(100.0 * (i + 1) / total));
put(taskId, BatchAddIncomeBillFeeTask.STATUS_RUNNING, percent,
"processing " + (i + 1) + "/" + total, null, total, success, fail);
}
String msg = "success=" + success + ", fail=" + fail;
if (fail > 0 && failTips.length() > 0)
{
put(taskId, BatchAddIncomeBillFeeTask.STATUS_SUCCESS, 100, msg, failTips.toString(),
total, success, fail);
}
else
{
put(taskId, BatchAddIncomeBillFeeTask.STATUS_SUCCESS, 100, msg, null, total, success, fail);
}
log.info("batch add fee done taskId={} total={} success={} fail={}", taskId, total, success, fail);
}
catch (Exception e)
{
log.error("batch add fee aborted taskId={}", taskId, e);
put(taskId, BatchAddIncomeBillFeeTask.STATUS_FAIL, 100, "failed", errorMessage(e), total, success, fail);
}
}
public void put(String taskId, String status, int percent, String message, String error,
int total, int success, int fail)
{
BatchAddIncomeBillFeeTask task = new BatchAddIncomeBillFeeTask();
task.setTaskId(taskId);
task.setStatus(status);
task.setPercent(percent);
task.setMessage(message);
task.setError(error);
task.setTotal(total);
task.setSuccess(success);
task.setFail(fail);
redisCache.setCacheObject(CACHE_KEY_PREFIX + taskId, task, TTL_MINUTES, TimeUnit.MINUTES);
}
public BatchAddIncomeBillFeeTask get(String taskId)
{
return redisCache.getCacheObject(CACHE_KEY_PREFIX + taskId);
}
private static String errorMessage(Exception e)
{
String msg = e.getMessage();
if (StringUtils.isEmpty(msg))
{
msg = e.getClass().getSimpleName();
}
return msg;
}
}