增加产品价和红线价重计费功能
This commit is contained in:
@@ -41,6 +41,7 @@ import com.bms.price.domain.vo.BatchAddIncomeBillFeeRequest;
|
||||
import com.bms.price.domain.vo.BillingTaskSubmitRequest;
|
||||
import com.bms.price.domain.vo.ChargeWeightImportRow;
|
||||
import com.bms.price.domain.vo.ChargeWeightTemplateRequest;
|
||||
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
||||
import com.bms.price.domain.vo.UpdateChargeWeightRequest;
|
||||
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
||||
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
||||
@@ -303,6 +304,53 @@ public class BillingController extends BaseController
|
||||
return success(task);
|
||||
}
|
||||
|
||||
/** Async recalc product_amount only. Poll /bill/recalcPrice/task/{taskId}. */
|
||||
@PreAuthorize("@ss.hasPermi('price:billing:recalc')")
|
||||
@Log(title = "Billing recalc product amount", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/bill/recalcProduct")
|
||||
public AjaxResult submitRecalcProductAmount(@RequestBody RecalcBillPriceRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
request = new RecalcBillPriceRequest();
|
||||
}
|
||||
request.setMode("PRODUCT");
|
||||
return successTask(prcOrderBillService.submitRecalcBillPrice(request));
|
||||
}
|
||||
|
||||
/** Async recalc redline_amount only. Poll /bill/recalcPrice/task/{taskId}. */
|
||||
@PreAuthorize("@ss.hasPermi('price:billing:recalc')")
|
||||
@Log(title = "Billing recalc redline amount", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/bill/recalcRedline")
|
||||
public AjaxResult submitRecalcRedlineAmount(@RequestBody RecalcBillPriceRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
request = new RecalcBillPriceRequest();
|
||||
}
|
||||
request.setMode("REDLINE");
|
||||
return successTask(prcOrderBillService.submitRecalcBillPrice(request));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('price:billing:recalc')")
|
||||
@GetMapping("/bill/recalcPrice/task/{taskId}")
|
||||
public AjaxResult getRecalcBillPriceTask(@PathVariable String taskId)
|
||||
{
|
||||
BatchAddIncomeBillFeeTask task = prcOrderBillService.getRecalcBillPriceTask(taskId);
|
||||
if (task == null)
|
||||
{
|
||||
return error(MessageUtils.message("price.bill.recalc.taskNotExists"));
|
||||
}
|
||||
return success(task);
|
||||
}
|
||||
|
||||
private AjaxResult successTask(String taskId)
|
||||
{
|
||||
Map<String, Object> payload = new HashMap<String, Object>();
|
||||
payload.put("taskId", taskId);
|
||||
return success(payload);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('price:billing:feeEdit')")
|
||||
@Log(title = "Billing income fee", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/bill/fee")
|
||||
|
||||
@@ -187,6 +187,14 @@ price.bill.fee.batch.noMatch=未查询到匹配的计费订单,无法批量增
|
||||
price.bill.fee.batch.filterRequired=请先在计费列表设置查询条件
|
||||
price.bill.fee.batch.selectedRequired=请勾选要增加费用的订单
|
||||
price.bill.fee.batch.scopeRequired=请选择添加范围
|
||||
price.bill.recalc.taskNotExists=重算价格任务不存在或已过期
|
||||
price.bill.recalc.tooMany=匹配订单超过上限 {0} 条,请缩小筛选范围
|
||||
price.bill.recalc.noMatch=未查询到已计费订单,无法重算产品价/红线价
|
||||
price.bill.recalc.filterRequired=请先在计费列表设置查询条件
|
||||
price.bill.recalc.selectedRequired=请勾选要重算的订单
|
||||
price.bill.recalc.modeRequired=请指定重算类型(PRODUCT/产品价或 REDLINE/红线价)
|
||||
price.bill.recalc.scopeRequired=请选择重算范围
|
||||
price.bill.recalc.quoteEmpty=计价结果为空,无法更新产品价/红线价
|
||||
price.bill.fee.surchargeNotFound=附加费配置不存在或已停用
|
||||
price.bill.fee.notFound=费用明细不存在
|
||||
price.bill.fee.notManual=仅手动增加的费用可编辑或删除
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.bms.price.domain.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/** Batch recalc product_amount or redline_amount only (existing bills). */
|
||||
@Data
|
||||
public class RecalcBillPriceRequest implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** PRODUCT | REDLINE */
|
||||
private String mode;
|
||||
|
||||
/** ALL = filters; SELECTED = billIds. */
|
||||
private String scopeMode;
|
||||
private List<String> billIds;
|
||||
private List<String> orderNos;
|
||||
private List<String> trackingNos;
|
||||
private List<String> transferNos;
|
||||
private List<String> customerCodes;
|
||||
private List<String> productCodes;
|
||||
private String countryCode;
|
||||
private String creditArrearsStatus;
|
||||
private String beginBizDate;
|
||||
private String endBizDate;
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.bms.price.domain.vo.BatchAddIncomeBillFeePreview;
|
||||
import com.bms.price.domain.vo.BatchAddIncomeBillFeeRequest;
|
||||
import com.bms.price.domain.vo.ChargeWeightImportRow;
|
||||
import com.bms.price.domain.vo.ChargeWeightTemplateRequest;
|
||||
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
||||
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
||||
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
||||
import com.bms.price.domain.vo.TmsPriceQuoteResult;
|
||||
@@ -111,4 +112,21 @@ public interface IPrcOrderBillService
|
||||
* otherwise fill orderNo/customer from list filters (data-scoped).
|
||||
*/
|
||||
List<ChargeWeightImportRow> buildChargeWeightTemplateRows(ChargeWeightTemplateRequest request);
|
||||
|
||||
/**
|
||||
* Submit async recalc of product_amount or redline_amount (request.mode).
|
||||
* Existing bills only; no AR restriction; sales amounts untouched.
|
||||
*
|
||||
* @return taskId
|
||||
*/
|
||||
String submitRecalcBillPrice(RecalcBillPriceRequest request);
|
||||
|
||||
/** Poll Redis progress for product/redline recalc task. */
|
||||
BatchAddIncomeBillFeeTask getRecalcBillPriceTask(String taskId);
|
||||
|
||||
/**
|
||||
* Recalc and persist product_amount or redline_amount by mode (PRODUCT/REDLINE).
|
||||
* Requires existing prc_order_bill; skips AR editable guard.
|
||||
*/
|
||||
void recalcBillPriceByBillId(String billId, String mode);
|
||||
}
|
||||
|
||||
+202
-23
@@ -49,10 +49,12 @@ import com.bms.price.domain.vo.BatchAddIncomeBillFeePreview;
|
||||
import com.bms.price.domain.vo.BatchAddIncomeBillFeeRequest;
|
||||
import com.bms.price.domain.vo.ChargeWeightImportRow;
|
||||
import com.bms.price.domain.vo.ChargeWeightTemplateRequest;
|
||||
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
||||
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
||||
import com.bms.price.task.PrcBatchAddIncomeFeeAsyncRunner;
|
||||
import com.bms.price.task.PrcChargeWeightImportAsyncRunner;
|
||||
import com.bms.price.task.PrcChargeWeightImportAsyncRunner.ChargeWeightImportWorkItem;
|
||||
import com.bms.price.task.PrcRecalcBillPriceAsyncRunner;
|
||||
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
||||
import com.bms.price.domain.vo.TmsOrderBillStatusResult;
|
||||
import com.bms.price.domain.vo.TmsPriceQuoteFeeLine;
|
||||
@@ -137,9 +139,13 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
@Autowired
|
||||
private PrcChargeWeightImportAsyncRunner chargeWeightImportAsyncRunner;
|
||||
|
||||
@Autowired
|
||||
private PrcRecalcBillPriceAsyncRunner recalcBillPriceAsyncRunner;
|
||||
|
||||
private static final int BATCH_ADD_FEE_MAX = 5000;
|
||||
private static final int BATCH_ADD_FEE_PREVIEW_LIMIT = 20;
|
||||
private static final int CHARGE_WEIGHT_IMPORT_MAX = 5000;
|
||||
private static final int RECALC_PRICE_MAX = 5000;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -591,34 +597,208 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
return batchAddIncomeFeeAsyncRunner.get(taskId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve matched bills with data scope.
|
||||
* scopeMode required: SELECTED uses billIds; ALL uses list filters (at least one required).
|
||||
*/
|
||||
@Override
|
||||
public String submitRecalcBillPrice(RecalcBillPriceRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.filterRequired"));
|
||||
}
|
||||
String mode = normalizeRecalcMode(request.getMode());
|
||||
List<PrcOrderBill> bills = resolveListScopedBills(request.getScopeMode(), request.getBillIds(),
|
||||
request.getOrderNos(), request.getTrackingNos(), request.getTransferNos(),
|
||||
request.getCustomerCodes(), request.getProductCodes(), request.getCountryCode(),
|
||||
request.getCreditArrearsStatus(), request.getBeginBizDate(), request.getEndBizDate(),
|
||||
"price.bill.recalc.filterRequired", "price.bill.recalc.scopeRequired",
|
||||
"price.bill.recalc.selectedRequired");
|
||||
if (bills.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.noMatch"));
|
||||
}
|
||||
if (bills.size() > RECALC_PRICE_MAX)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.tooMany",
|
||||
Integer.valueOf(RECALC_PRICE_MAX)));
|
||||
}
|
||||
List<String> billIds = new ArrayList<String>();
|
||||
for (PrcOrderBill bill : bills)
|
||||
{
|
||||
if (bill != null && StringUtils.isNotEmpty(bill.getBillId()))
|
||||
{
|
||||
billIds.add(bill.getBillId());
|
||||
}
|
||||
}
|
||||
if (billIds.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.noMatch"));
|
||||
}
|
||||
String taskId = IdUtils.fastSimpleUUID();
|
||||
recalcBillPriceAsyncRunner.put(taskId, BatchAddIncomeBillFeeTask.STATUS_PENDING, 0, "queued", null,
|
||||
billIds.size(), 0, 0);
|
||||
recalcBillPriceAsyncRunner.run(taskId, mode, billIds);
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchAddIncomeBillFeeTask getRecalcBillPriceTask(String taskId)
|
||||
{
|
||||
if (StringUtils.isEmpty(taskId) || recalcBillPriceAsyncRunner == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return recalcBillPriceAsyncRunner.get(taskId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void recalcBillPriceByBillId(String billId, String mode)
|
||||
{
|
||||
boolean productMode = "PRODUCT".equals(normalizeRecalcMode(mode));
|
||||
if (StringUtils.isEmpty(billId))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.billIdRequired"));
|
||||
}
|
||||
PrcOrderBill bill = orderBillMapper.selectPrcOrderBillById(billId.trim());
|
||||
if (bill == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.notFound"));
|
||||
}
|
||||
TmsPriceBillRequest req = buildBillRequestFromBill(bill);
|
||||
if (StringUtils.isEmpty(req.getBizDate()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.bizDateRequired"));
|
||||
}
|
||||
TmsPriceQuoteResult result = tmsPriceQuoteService.calculate(req);
|
||||
if (result == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.quoteEmpty"));
|
||||
}
|
||||
persistProductOrRedlineOnly(bill, result, productMode);
|
||||
}
|
||||
|
||||
private static String normalizeRecalcMode(String mode)
|
||||
{
|
||||
String m = StringUtils.nvl(mode, "").trim().toUpperCase();
|
||||
if (!"PRODUCT".equals(m) && !"REDLINE".equals(m))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.modeRequired"));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Update income header + fee snapshots for product or redline only. */
|
||||
private void persistProductOrRedlineOnly(PrcOrderBill bill, TmsPriceQuoteResult result, boolean productMode)
|
||||
{
|
||||
PrcIncomeBill incomeBill = incomeBillMapper.selectByBillId(bill.getBillId());
|
||||
boolean insert = incomeBill == null;
|
||||
if (insert)
|
||||
{
|
||||
incomeBill = new PrcIncomeBill();
|
||||
incomeBill.setIncomeBillId(UUID.randomUUID().toString());
|
||||
incomeBill.setBillId(bill.getBillId());
|
||||
incomeBill.setCurrency(StringUtils.isEmpty(bill.getCurrency()) ? "CNY" : bill.getCurrency());
|
||||
incomeBill.setSalesAmount(nz(bill.getIncomeTotal()));
|
||||
incomeBill.setIncomeTotal(nz(bill.getIncomeTotal()));
|
||||
incomeBill.setBelongSaler(bill.getBelongSaler());
|
||||
incomeBill.setBelongSalerCode(bill.getBelongSalerCode());
|
||||
incomeBill.setSettlementMan(bill.getSettlementMan());
|
||||
incomeBill.setSettlementManCode(bill.getSettlementManCode());
|
||||
incomeBill.setCreateBy(bill.getCreateBy());
|
||||
}
|
||||
if (productMode)
|
||||
{
|
||||
incomeBill.setProductAmount(result.getProductAmount());
|
||||
}
|
||||
else
|
||||
{
|
||||
incomeBill.setRedlineAmount(result.getRedlineAmount());
|
||||
}
|
||||
if (insert)
|
||||
{
|
||||
incomeBillMapper.insertPrcIncomeBill(incomeBill);
|
||||
}
|
||||
else
|
||||
{
|
||||
incomeBill.setUpdateBy(bill.getUpdateBy());
|
||||
incomeBillMapper.updatePrcIncomeBill(incomeBill);
|
||||
}
|
||||
|
||||
List<PrcIncomeBillFee> fees = incomeBillFeeMapper.selectByBillId(bill.getBillId());
|
||||
if (fees == null || fees.isEmpty() || result.getFeeDetails() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
java.util.Map<String, TmsPriceQuoteFeeLine> quoteByKey = new java.util.HashMap<String, TmsPriceQuoteFeeLine>();
|
||||
for (TmsPriceQuoteFeeLine line : result.getFeeDetails())
|
||||
{
|
||||
if (line != null && StringUtils.isNotEmpty(line.getFeeType()))
|
||||
{
|
||||
quoteByKey.put(feeUniqueKey(line.getFeeType(), line.getScId()), line);
|
||||
}
|
||||
}
|
||||
for (PrcIncomeBillFee fee : fees)
|
||||
{
|
||||
if (fee == null || StringUtils.isEmpty(fee.getFeeType()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TmsPriceQuoteFeeLine line = quoteByKey.get(feeUniqueKey(fee.getFeeType(), fee.getScId()));
|
||||
if (line == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (productMode)
|
||||
{
|
||||
fee.setProductAmount(line.getProductAmount());
|
||||
}
|
||||
else
|
||||
{
|
||||
fee.setRedlineAmount(line.getRedlineAmount());
|
||||
}
|
||||
incomeBillFeeMapper.updatePrcIncomeBillFee(fee);
|
||||
}
|
||||
}
|
||||
|
||||
private List<PrcOrderBill> resolveBatchAddFeeBills(BatchAddIncomeBillFeeRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.fee.batch.filterRequired"));
|
||||
}
|
||||
String scopeMode = StringUtils.nvl(request.getScopeMode(), "").trim().toUpperCase();
|
||||
return resolveListScopedBills(request.getScopeMode(), request.getBillIds(),
|
||||
request.getOrderNos(), request.getTrackingNos(), request.getTransferNos(),
|
||||
request.getCustomerCodes(), request.getProductCodes(), request.getCountryCode(),
|
||||
request.getCreditArrearsStatus(), request.getBeginBizDate(), request.getEndBizDate(),
|
||||
"price.bill.fee.batch.filterRequired", "price.bill.fee.batch.scopeRequired",
|
||||
"price.bill.fee.batch.selectedRequired");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared list-scope resolve for batch fee / recalc price.
|
||||
* scopeMode: SELECTED uses billIds; ALL uses filters (at least one required).
|
||||
*/
|
||||
private List<PrcOrderBill> resolveListScopedBills(String scopeModeRaw, List<String> billIdsRaw,
|
||||
List<String> orderNosRaw, List<String> trackingNosRaw, List<String> transferNosRaw,
|
||||
List<String> customerCodesRaw, List<String> productCodesRaw, String countryCodeRaw,
|
||||
String creditArrearsStatusRaw, String beginBizDateRaw, String endBizDateRaw,
|
||||
String msgFilter, String msgScope, String msgSelected)
|
||||
{
|
||||
String scopeMode = StringUtils.nvl(scopeModeRaw, "").trim().toUpperCase();
|
||||
if (!"ALL".equals(scopeMode) && !"SELECTED".equals(scopeMode))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.fee.batch.scopeRequired"));
|
||||
throw new ServiceException(MessageUtils.message(msgScope));
|
||||
}
|
||||
List<String> orderNos = normalizeCodeList(request.getOrderNos());
|
||||
List<String> trackingNos = normalizeCodeList(request.getTrackingNos());
|
||||
List<String> transferNos = normalizeCodeList(request.getTransferNos());
|
||||
List<String> customerCodes = normalizeCodeList(request.getCustomerCodes());
|
||||
List<String> productCodes = normalizeCodeList(request.getProductCodes());
|
||||
String creditArrearsStatus = StringUtils.isEmpty(request.getCreditArrearsStatus()) ? null
|
||||
: request.getCreditArrearsStatus().trim();
|
||||
String countryCode = StringUtils.isEmpty(request.getCountryCode()) ? null
|
||||
: request.getCountryCode().trim().toUpperCase();
|
||||
String beginBizDate = StringUtils.isEmpty(request.getBeginBizDate()) ? null
|
||||
: request.getBeginBizDate().trim();
|
||||
String endBizDate = StringUtils.isEmpty(request.getEndBizDate()) ? null
|
||||
: request.getEndBizDate().trim();
|
||||
List<String> orderNos = normalizeCodeList(orderNosRaw);
|
||||
List<String> trackingNos = normalizeCodeList(trackingNosRaw);
|
||||
List<String> transferNos = normalizeCodeList(transferNosRaw);
|
||||
List<String> customerCodes = normalizeCodeList(customerCodesRaw);
|
||||
List<String> productCodes = normalizeCodeList(productCodesRaw);
|
||||
String creditArrearsStatus = StringUtils.isEmpty(creditArrearsStatusRaw) ? null
|
||||
: creditArrearsStatusRaw.trim();
|
||||
String countryCode = StringUtils.isEmpty(countryCodeRaw) ? null
|
||||
: countryCodeRaw.trim().toUpperCase();
|
||||
String beginBizDate = StringUtils.isEmpty(beginBizDateRaw) ? null : beginBizDateRaw.trim();
|
||||
String endBizDate = StringUtils.isEmpty(endBizDateRaw) ? null : endBizDateRaw.trim();
|
||||
boolean hasFilter = (orderNos != null && !orderNos.isEmpty())
|
||||
|| (trackingNos != null && !trackingNos.isEmpty())
|
||||
|| (transferNos != null && !transferNos.isEmpty())
|
||||
@@ -630,15 +810,15 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
|| StringUtils.isNotEmpty(endBizDate);
|
||||
if (!hasFilter)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.fee.batch.filterRequired"));
|
||||
throw new ServiceException(MessageUtils.message(msgFilter));
|
||||
}
|
||||
PrcOrderBill query = new PrcOrderBill();
|
||||
if ("SELECTED".equals(scopeMode))
|
||||
{
|
||||
List<String> billIds = normalizeCodeList(request.getBillIds());
|
||||
List<String> billIds = normalizeCodeList(billIdsRaw);
|
||||
if (billIds == null || billIds.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.fee.batch.selectedRequired"));
|
||||
throw new ServiceException(MessageUtils.message(msgSelected));
|
||||
}
|
||||
query.setBillIds(billIds);
|
||||
}
|
||||
@@ -660,7 +840,6 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
query.getParams().put("endBizDate", endBizDate);
|
||||
}
|
||||
}
|
||||
// Use self proxy so @DataScope applies
|
||||
List<PrcOrderBill> list = self.selectBillList(query);
|
||||
return list == null ? new ArrayList<PrcOrderBill>() : list;
|
||||
}
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
package com.bms.price.task;
|
||||
|
||||
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.service.IPrcOrderBillService;
|
||||
|
||||
/** Async: recalc product_amount or redline_amount only (no AR guard). */
|
||||
@Component
|
||||
public class PrcRecalcBillPriceAsyncRunner
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PrcRecalcBillPriceAsyncRunner.class);
|
||||
public static final String CACHE_KEY_PREFIX = "price:billing:recalcPrice:task:";
|
||||
public static final int TTL_MINUTES = 120;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private IPrcOrderBillService orderBillService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Async("threadPoolTaskExecutor")
|
||||
public void run(String taskId, String mode, List<String> billIds)
|
||||
{
|
||||
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
|
||||
{
|
||||
orderBillService.recalcBillPriceByBillId(billId, mode);
|
||||
success++;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
fail++;
|
||||
appendFail(failTips, billId, e);
|
||||
log.warn("recalc price failed taskId={} mode={} billId={}", taskId, mode, 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;
|
||||
put(taskId, BatchAddIncomeBillFeeTask.STATUS_SUCCESS, 100, msg,
|
||||
fail > 0 && failTips.length() > 0 ? failTips.toString() : null, total, success, fail);
|
||||
log.info("recalc price done taskId={} mode={} total={} success={} fail={}",
|
||||
taskId, mode, total, success, fail);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("recalc price aborted taskId={} mode={}", taskId, mode, 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 void appendFail(StringBuilder failTips, String billId, Exception e)
|
||||
{
|
||||
if (failTips.length() >= 800)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (failTips.length() > 0)
|
||||
{
|
||||
failTips.append("; ");
|
||||
}
|
||||
failTips.append(billId).append(":").append(errorMessage(e));
|
||||
}
|
||||
|
||||
private static String errorMessage(Exception e)
|
||||
{
|
||||
return StringUtils.isEmpty(e.getMessage()) ? e.getClass().getSimpleName() : e.getMessage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
-- billing list: recalc product/redline amount (async; no AR restriction)
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2332, N'重计费', m.menu_id, 22, '', NULL, 1, 0, 'F', '0', '0', 'price:billing:recalc', '#', 'admin', sysdate(), N'计费列表异步重算产品价/红线价(已出账也可)'
|
||||
FROM (
|
||||
SELECT menu_id FROM sys_menu
|
||||
WHERE perms = 'price:billing:bill' AND menu_type = 'C'
|
||||
UNION ALL
|
||||
SELECT menu_id FROM sys_menu
|
||||
WHERE component = 'price/billing/bill' AND menu_type = 'C'
|
||||
) m
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_menu x WHERE x.menu_id = 2332 OR x.perms = 'price:billing:recalc')
|
||||
LIMIT 1;
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, 2332
|
||||
FROM DUAL
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2332)
|
||||
AND NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = 1 AND rm.menu_id = 2332);
|
||||
|
||||
-- cleanup old split permissions if previously inserted
|
||||
DELETE FROM sys_role_menu WHERE menu_id = 2333;
|
||||
DELETE FROM sys_menu WHERE menu_id = 2333 OR perms = 'price:billing:recalcRedline';
|
||||
UPDATE sys_menu SET menu_name = N'重计费', perms = 'price:billing:recalc',
|
||||
remark = N'计费列表异步重算产品价/红线价(已出账也可)'
|
||||
WHERE menu_id = 2332 OR perms IN ('price:billing:recalcProduct', 'price:billing:recalc');
|
||||
Reference in New Issue
Block a user