订单列表重新计费优化
This commit is contained in:
@@ -43,6 +43,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.LocalRebillRequest;
|
||||
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
||||
import com.bms.price.domain.vo.UpdateChargeWeightRequest;
|
||||
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
||||
@@ -197,6 +198,30 @@ public class BillingController extends BaseController
|
||||
return success(orderBillProductCheckService.listOrdersByProduct(query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Order-list rebill from local prc_order_bill only (no Oracle TAB_ORDER).
|
||||
* Poll {@code GET /orderBill/rebill/task/{taskId}}.
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('price:orderBill:rebill')")
|
||||
@Log(title = "Order bill local rebill", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/orderBill/rebill")
|
||||
public AjaxResult submitLocalRebill(@RequestBody LocalRebillRequest request)
|
||||
{
|
||||
return successTask(prcOrderBillService.submitLocalRebill(request));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('price:orderBill:rebill')")
|
||||
@GetMapping("/orderBill/rebill/task/{taskId}")
|
||||
public AjaxResult getLocalRebillTask(@PathVariable("taskId") String taskId)
|
||||
{
|
||||
BatchAddIncomeBillFeeTask task = prcOrderBillService.getLocalRebillTask(taskId);
|
||||
if (task == null)
|
||||
{
|
||||
return error(MessageUtils.message("price.bill.recalc.taskNotExists"));
|
||||
}
|
||||
return success(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order no options for remote-search dropdown (bill list multi search).
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.bms.price.domain.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Order-list local rebill: use prc_order_bill only (no Oracle TAB_ORDER).
|
||||
* scopeMode SELECTED = billIds; ALL = filters (orderIdentifiers / customer / bizDate...).
|
||||
*/
|
||||
@Data
|
||||
public class LocalRebillRequest implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** ALL | SELECTED */
|
||||
private String scopeMode;
|
||||
private List<String> billIds;
|
||||
private List<String> orderNos;
|
||||
private List<String> trackingNos;
|
||||
private List<String> transferNos;
|
||||
private List<String> orderIdentifiers;
|
||||
private List<String> customerCodes;
|
||||
private List<String> productCodes;
|
||||
private String countryCode;
|
||||
private String creditArrearsStatus;
|
||||
private String beginBizDate;
|
||||
private String endBizDate;
|
||||
}
|
||||
@@ -21,6 +21,12 @@ public interface PrcOrderBillMapper
|
||||
|
||||
public List<PrcOrderBill> selectPrcOrderBillList(PrcOrderBill bill);
|
||||
|
||||
/** bill_id only (same filters / data-scope as list), for large local rebill. */
|
||||
List<String> selectPrcOrderBillIds(PrcOrderBill bill);
|
||||
|
||||
/** Count matching bills (same filters / data-scope as list). */
|
||||
int countPrcOrderBillIds(PrcOrderBill bill);
|
||||
|
||||
/** Distinct customer+product groups for product-check (order counts in filter window). */
|
||||
List<Map<String, Object>> selectDistinctProductGroups(PrcOrderBill bill);
|
||||
|
||||
|
||||
@@ -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.LocalRebillRequest;
|
||||
import com.bms.price.domain.vo.RecalcBillPriceRequest;
|
||||
import com.bms.price.domain.vo.UpdateIncomeBillFeeRequest;
|
||||
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
||||
@@ -135,4 +136,25 @@ public interface IPrcOrderBillService
|
||||
* Requires existing prc_order_bill; skips AR editable guard.
|
||||
*/
|
||||
void recalcBillPriceByBillId(String billId, String mode);
|
||||
|
||||
/**
|
||||
* Full rebill from local prc_order_bill only (no Oracle upstream).
|
||||
* Rebuilds TmsPriceBillRequest from the bill row then calls {@link #bill}.
|
||||
*/
|
||||
TmsPriceQuoteResult rebillLocalByBillId(String billId);
|
||||
|
||||
/**
|
||||
* Async local rebill by selected billIds or list filters. Returns taskId for progress poll.
|
||||
* Large sets: only bill_id loaded, then processed in pages of 500 with parallel workers.
|
||||
*/
|
||||
String submitLocalRebill(LocalRebillRequest request);
|
||||
|
||||
/** Poll Redis progress for local rebill task. */
|
||||
BatchAddIncomeBillFeeTask getLocalRebillTask(String taskId);
|
||||
|
||||
/** Data-scoped bill_id list for local rebill (same filters as order-bill list). */
|
||||
List<String> selectBillIdsForLocalRebill(PrcOrderBill query);
|
||||
|
||||
/** Data-scoped count for local rebill. */
|
||||
int countBillIdsForLocalRebill(PrcOrderBill query);
|
||||
}
|
||||
|
||||
+169
@@ -50,11 +50,13 @@ 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.LocalRebillRequest;
|
||||
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.PrcOrderBillLocalRebillAsyncRunner;
|
||||
import com.bms.price.task.PrcRecalcBillPriceAsyncRunner;
|
||||
import com.bms.price.domain.vo.TmsPriceBillRequest;
|
||||
import com.bms.price.domain.vo.TmsOrderBillStatusResult;
|
||||
@@ -143,6 +145,9 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
@Autowired
|
||||
private PrcRecalcBillPriceAsyncRunner recalcBillPriceAsyncRunner;
|
||||
|
||||
@Autowired
|
||||
private PrcOrderBillLocalRebillAsyncRunner localRebillAsyncRunner;
|
||||
|
||||
@Autowired
|
||||
private IBmsBizRuleService bizRuleService;
|
||||
|
||||
@@ -150,6 +155,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
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;
|
||||
/** Soft max for one local-rebill job (id-only load + paged parallel). */
|
||||
private static final int LOCAL_REBILL_MAX = 100000;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -694,6 +701,168 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
persistProductOrRedlineOnly(bill, result, productMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public TmsPriceQuoteResult rebillLocalByBillId(String billId)
|
||||
{
|
||||
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"));
|
||||
}
|
||||
if (StringUtils.isEmpty(bill.getOrderNo()))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.orderNoRequired"));
|
||||
}
|
||||
if (bill.getBizDate() == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.bizDateRequired"));
|
||||
}
|
||||
TmsPriceBillRequest req = buildBillRequestFromBill(bill);
|
||||
// Full bill() path: AR guard, weight rules, quote, persist (local snapshot only).
|
||||
return self.bill(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String submitLocalRebill(LocalRebillRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.filterRequired"));
|
||||
}
|
||||
PrcOrderBill query = buildLocalRebillQuery(request);
|
||||
int total = self.countBillIdsForLocalRebill(query);
|
||||
if (total <= 0)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.noMatch"));
|
||||
}
|
||||
if (total > LOCAL_REBILL_MAX)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.tooMany",
|
||||
Integer.valueOf(LOCAL_REBILL_MAX)));
|
||||
}
|
||||
// Id-only: avoid loading full prc_order_bill rows for large jobs.
|
||||
List<String> billIds = self.selectBillIdsForLocalRebill(query);
|
||||
if (billIds == null || billIds.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.noMatch"));
|
||||
}
|
||||
String taskId = IdUtils.fastSimpleUUID();
|
||||
localRebillAsyncRunner.put(taskId, BatchAddIncomeBillFeeTask.STATUS_PENDING, 0, "queued", null,
|
||||
billIds.size(), 0, 0);
|
||||
localRebillAsyncRunner.run(taskId, billIds);
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchAddIncomeBillFeeTask getLocalRebillTask(String taskId)
|
||||
{
|
||||
if (StringUtils.isEmpty(taskId) || localRebillAsyncRunner == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return localRebillAsyncRunner.get(taskId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataScope(deptAlias = "su", deptField = "dept_id", userAlias = "su", userField = "user_id", permission = "price:billing:bill")
|
||||
public List<String> selectBillIdsForLocalRebill(PrcOrderBill query)
|
||||
{
|
||||
if (query == null)
|
||||
{
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
normalizeLocalRebillQuery(query);
|
||||
List<String> ids = orderBillMapper.selectPrcOrderBillIds(query);
|
||||
return ids == null ? new ArrayList<String>() : ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataScope(deptAlias = "su", deptField = "dept_id", userAlias = "su", userField = "user_id", permission = "price:billing:bill")
|
||||
public int countBillIdsForLocalRebill(PrcOrderBill query)
|
||||
{
|
||||
if (query == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
normalizeLocalRebillQuery(query);
|
||||
return orderBillMapper.countPrcOrderBillIds(query);
|
||||
}
|
||||
|
||||
private PrcOrderBill buildLocalRebillQuery(LocalRebillRequest request)
|
||||
{
|
||||
String scopeMode = StringUtils.nvl(request.getScopeMode(), "").trim().toUpperCase();
|
||||
PrcOrderBill query = new PrcOrderBill();
|
||||
if ("SELECTED".equals(scopeMode))
|
||||
{
|
||||
List<String> billIds = normalizeCodeList(request.getBillIds());
|
||||
if (billIds == null || billIds.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.selectedRequired"));
|
||||
}
|
||||
query.setBillIds(billIds);
|
||||
return query;
|
||||
}
|
||||
List<String> orderNos = normalizeCodeList(request.getOrderNos());
|
||||
List<String> trackingNos = normalizeCodeList(request.getTrackingNos());
|
||||
List<String> transferNos = normalizeCodeList(request.getTransferNos());
|
||||
List<String> orderIdentifiers = normalizeCodeList(request.getOrderIdentifiers());
|
||||
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();
|
||||
boolean hasFilter = (orderNos != null && !orderNos.isEmpty())
|
||||
|| (trackingNos != null && !trackingNos.isEmpty())
|
||||
|| (transferNos != null && !transferNos.isEmpty())
|
||||
|| (orderIdentifiers != null && !orderIdentifiers.isEmpty())
|
||||
|| (customerCodes != null && !customerCodes.isEmpty())
|
||||
|| (productCodes != null && !productCodes.isEmpty())
|
||||
|| StringUtils.isNotEmpty(creditArrearsStatus)
|
||||
|| StringUtils.isNotEmpty(countryCode)
|
||||
|| StringUtils.isNotEmpty(beginBizDate)
|
||||
|| StringUtils.isNotEmpty(endBizDate);
|
||||
if (!hasFilter)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.recalc.filterRequired"));
|
||||
}
|
||||
query.setOrderNos(orderNos);
|
||||
query.setTrackingNos(trackingNos);
|
||||
query.setTransferNos(transferNos);
|
||||
query.setOrderIdentifiers(orderIdentifiers);
|
||||
query.setCustomerCodes(customerCodes);
|
||||
query.setProductCodes(productCodes);
|
||||
query.setCreditArrearsStatus(creditArrearsStatus);
|
||||
query.setCountryCode(countryCode);
|
||||
if (beginBizDate != null)
|
||||
{
|
||||
query.getParams().put("beginBizDate", beginBizDate);
|
||||
}
|
||||
if (endBizDate != null)
|
||||
{
|
||||
query.getParams().put("endBizDate", endBizDate);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private void normalizeLocalRebillQuery(PrcOrderBill query)
|
||||
{
|
||||
query.setOrderNos(normalizeCodeList(query.getOrderNos()));
|
||||
query.setCustomerCodes(normalizeCodeList(query.getCustomerCodes()));
|
||||
query.setProductCodes(normalizeCodeList(query.getProductCodes()));
|
||||
query.setTrackingNos(normalizeCodeList(query.getTrackingNos()));
|
||||
query.setTransferNos(normalizeCodeList(query.getTransferNos()));
|
||||
query.setOrderIdentifiers(normalizeCodeList(query.getOrderIdentifiers()));
|
||||
query.setBillIds(normalizeCodeList(query.getBillIds()));
|
||||
}
|
||||
|
||||
private static String normalizeRecalcMode(String mode)
|
||||
{
|
||||
String m = StringUtils.nvl(mode, "").trim().toUpperCase();
|
||||
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
package com.bms.price.task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
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.config.BillingProperties;
|
||||
import com.bms.price.domain.BatchAddIncomeBillFeeTask;
|
||||
import com.bms.price.service.IPrcOrderBillService;
|
||||
|
||||
/**
|
||||
* Async local rebill from prc_order_bill only (no Oracle / no MQ).
|
||||
* Large jobs: process in pages of {@link #PAGE_SIZE}; each page runs in a short-lived worker pool.
|
||||
*/
|
||||
@Component
|
||||
public class PrcOrderBillLocalRebillAsyncRunner
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PrcOrderBillLocalRebillAsyncRunner.class);
|
||||
|
||||
public static final String CACHE_KEY_PREFIX = "price:billing:localRebill:task:";
|
||||
public static final int TTL_MINUTES = 120;
|
||||
/** Bill this many, wait for page done, then next page. */
|
||||
public static final int PAGE_SIZE = 500;
|
||||
public static final int MIN_THREADS = 2;
|
||||
public static final int MAX_THREADS = 16;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private IPrcOrderBillService orderBillService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private BillingProperties billingProperties;
|
||||
|
||||
@Async("threadPoolTaskExecutor")
|
||||
public void run(String taskId, List<String> billIds)
|
||||
{
|
||||
int total = billIds == null ? 0 : billIds.size();
|
||||
AtomicInteger success = new AtomicInteger(0);
|
||||
AtomicInteger fail = new AtomicInteger(0);
|
||||
StringBuilder failTips = new StringBuilder();
|
||||
int threads = clampThreads(billingProperties == null ? null : billingProperties.getOrderSourceSyncThreads());
|
||||
ExecutorService pool = newWorkerPool(threads, "local-rebill");
|
||||
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;
|
||||
}
|
||||
int processed = 0;
|
||||
for (int from = 0; from < total; from += PAGE_SIZE)
|
||||
{
|
||||
int to = Math.min(from + PAGE_SIZE, total);
|
||||
List<String> page = billIds.subList(from, to);
|
||||
List<Callable<Boolean>> jobs = new ArrayList<Callable<Boolean>>(page.size());
|
||||
for (String billId : page)
|
||||
{
|
||||
final String one = billId;
|
||||
jobs.add(() -> {
|
||||
try
|
||||
{
|
||||
orderBillService.rebillLocalByBillId(one);
|
||||
success.incrementAndGet();
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
fail.incrementAndGet();
|
||||
appendFail(failTips, one, e);
|
||||
log.warn("local rebill failed taskId={} billId={}", taskId, one, e);
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
});
|
||||
}
|
||||
invokeAllQuiet(pool, jobs);
|
||||
processed = to;
|
||||
int percent = Math.min(99, (int) Math.floor(100.0 * processed / total));
|
||||
put(taskId, BatchAddIncomeBillFeeTask.STATUS_RUNNING, percent,
|
||||
"processing " + processed + "/" + total + " page=" + ((from / PAGE_SIZE) + 1),
|
||||
null, total, success.get(), fail.get());
|
||||
}
|
||||
String msg = "success=" + success.get() + ", fail=" + fail.get();
|
||||
put(taskId, BatchAddIncomeBillFeeTask.STATUS_SUCCESS, 100, msg,
|
||||
fail.get() > 0 && failTips.length() > 0 ? failTips.toString() : null,
|
||||
total, success.get(), fail.get());
|
||||
log.info("local rebill done taskId={} total={} success={} fail={} threads={} pageSize={}",
|
||||
taskId, total, success.get(), fail.get(), threads, PAGE_SIZE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("local rebill aborted taskId={}", taskId, e);
|
||||
put(taskId, BatchAddIncomeBillFeeTask.STATUS_FAIL, 100, "failed", errorMessage(e),
|
||||
total, success.get(), fail.get());
|
||||
}
|
||||
finally
|
||||
{
|
||||
shutdownPool(pool);
|
||||
}
|
||||
}
|
||||
|
||||
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 invokeAllQuiet(ExecutorService pool, List<Callable<Boolean>> jobs) throws InterruptedException
|
||||
{
|
||||
List<Future<Boolean>> futures = pool.invokeAll(jobs);
|
||||
for (Future<Boolean> f : futures)
|
||||
{
|
||||
try
|
||||
{
|
||||
f.get();
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
// counted in job body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ExecutorService newWorkerPool(int threads, String namePrefix)
|
||||
{
|
||||
AtomicInteger seq = new AtomicInteger(0);
|
||||
ThreadFactory factory = r -> {
|
||||
Thread t = new Thread(r);
|
||||
t.setName(namePrefix + "-" + seq.incrementAndGet());
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
};
|
||||
return Executors.newFixedThreadPool(Math.max(1, threads), factory);
|
||||
}
|
||||
|
||||
private static void shutdownPool(ExecutorService pool)
|
||||
{
|
||||
if (pool == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pool.shutdown();
|
||||
try
|
||||
{
|
||||
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
|
||||
{
|
||||
pool.shutdownNow();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Thread.currentThread().interrupt();
|
||||
pool.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
static int clampThreads(Integer n)
|
||||
{
|
||||
int v = n == null ? 8 : n.intValue();
|
||||
if (v < MIN_THREADS)
|
||||
{
|
||||
return MIN_THREADS;
|
||||
}
|
||||
if (v > MAX_THREADS)
|
||||
{
|
||||
return MAX_THREADS;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private static void appendFail(StringBuilder failTips, String billId, Exception e)
|
||||
{
|
||||
synchronized (failTips)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -409,9 +409,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
limit #{limit}
|
||||
</select>
|
||||
|
||||
<select id="selectPrcOrderBillList" parameterType="PrcOrderBill" resultMap="PrcOrderBillResult">
|
||||
<include refid="selectPrcOrderBillVo"/>
|
||||
<where>
|
||||
<!-- Shared list filters for full row / id-only / count queries. -->
|
||||
<sql id="prcOrderBillListWhere">
|
||||
<if test="billId != null and billId != ''">
|
||||
AND p.bill_id = #{billId}
|
||||
</if>
|
||||
@@ -540,10 +539,34 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
AND date_format(p.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
|
||||
</if>
|
||||
<include refid="orderBillDataScopeFilter"/>
|
||||
</sql>
|
||||
|
||||
<select id="selectPrcOrderBillList" parameterType="PrcOrderBill" resultMap="PrcOrderBillResult">
|
||||
<include refid="selectPrcOrderBillVo"/>
|
||||
<where>
|
||||
<include refid="prcOrderBillListWhere"/>
|
||||
</where>
|
||||
order by p.create_time desc, p.bill_id desc
|
||||
</select>
|
||||
|
||||
<!-- Id-only for large local rebill (avoid loading full rows into memory). -->
|
||||
<select id="selectPrcOrderBillIds" parameterType="PrcOrderBill" resultType="string">
|
||||
select p.bill_id
|
||||
from prc_order_bill p
|
||||
<where>
|
||||
<include refid="prcOrderBillListWhere"/>
|
||||
</where>
|
||||
order by p.bill_id asc
|
||||
</select>
|
||||
|
||||
<select id="countPrcOrderBillIds" parameterType="PrcOrderBill" resultType="int">
|
||||
select count(1)
|
||||
from prc_order_bill p
|
||||
<where>
|
||||
<include refid="prcOrderBillListWhere"/>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!-- rename_bill_tables.sql 已将需求文档中的 prc_bill 映射为本项目的 prc_order_bill。 -->
|
||||
<!-- 生成弹窗预览:按客户、截止日、币种和订单号/运单号/转单号 OR 条件分页查询未入账订单。 -->
|
||||
<sql id="orderIdentifierCondition">
|
||||
|
||||
Reference in New Issue
Block a user