Merge branch 'test' of https://git.lionquexpress.com/wuweihua/BMS
# Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit.
This commit is contained in:
+3
-2
@@ -170,7 +170,7 @@ public class TabOrderMonitorController extends BaseController
|
||||
customerKeywordResolver.resolve(query);
|
||||
String asyncTaskId = UUID.randomUUID().toString().replace("-", "");
|
||||
tabOrderCompareAsyncRunner.put(asyncTaskId, TabOrderCompareTask.STATUS_PENDING, 0, "queued",
|
||||
0, 0, 0, 0, null, null, null);
|
||||
0, 0, 0, null, null);
|
||||
tabOrderCompareAsyncRunner.run(asyncTaskId, query);
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("asyncTaskId", asyncTaskId);
|
||||
@@ -224,7 +224,7 @@ public class TabOrderMonitorController extends BaseController
|
||||
@PostMapping("/syncByFilter")
|
||||
public AjaxResult syncByFilter(@RequestBody TabOrderMonitorQuery query)
|
||||
{
|
||||
// 与列表查询同口径:有单号即可同步;无单号时必须客户 + 提货时间
|
||||
// Upstream field overwrite only (no billing). Same filters as list query.
|
||||
if (!hasListFilters(query))
|
||||
{
|
||||
return error("orderIdentifiers or (customer and pickup time) required");
|
||||
@@ -257,6 +257,7 @@ public class TabOrderMonitorController extends BaseController
|
||||
return success(task);
|
||||
}
|
||||
|
||||
/** Selected rows: overwrite local bill fields from Oracle; does not quote/rebill. */
|
||||
@PreAuthorize("@ss.hasPermi('monitor:orderSource:sync') or @ss.hasPermi('price:orderBill:rebill')")
|
||||
@Log(title = "order source sync selected", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/sync")
|
||||
|
||||
@@ -7,8 +7,8 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* 订单比对异步任务进度(Redis)。
|
||||
* missing = 上游有转单号、本地无;
|
||||
* statusMismatch = 本地有转单号但 order_status 与上游不一致。
|
||||
* missing = 上游有转单号、本地在指定状态集合中无对应单;
|
||||
* statusMismatch 已废弃(恒为 0,不再比对状态)。
|
||||
*/
|
||||
public class TabOrderCompareTask implements Serializable
|
||||
{
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.bms.price.enums;
|
||||
|
||||
/**
|
||||
* Snapshot of prc_order_bill.order_status (aligned with upstream TAB_ORDER).
|
||||
* Fee refund sets {@link #REFUNDED} (9 / 已退件).
|
||||
* Upstream 9/10 trigger billType=REFUND when billing pulls Oracle.
|
||||
* Fee refund sets {@link #REFUNDED} (9 / 已退件); rebill/bill follows Oracle and does not pin 9/10.
|
||||
* Upstream 9/10 trigger billType=REFUND when billing-task pulls Oracle.
|
||||
*/
|
||||
public enum BillOrderStatus
|
||||
{
|
||||
|
||||
@@ -39,14 +39,16 @@ public interface PrcOrderBillMapper
|
||||
List<String> selectExistingOrderIdentifiers(@Param("identifiers") List<String> identifiers,
|
||||
@Param("customerCodes") List<String> customerCodes);
|
||||
|
||||
/** 订单比对:仅按转单号批量查本地已存在。 */
|
||||
/** 订单比对:仅按转单号批量查本地已存在(可选 order_status 过滤)。 */
|
||||
List<String> selectExistingTransferNos(@Param("transferNos") List<String> transferNos,
|
||||
@Param("customerCodes") List<String> customerCodes);
|
||||
@Param("customerCodes") List<String> customerCodes,
|
||||
@Param("orderStatuses") List<Integer> orderStatuses);
|
||||
|
||||
/** 订单比对:按转单号批量查本地 transfer_no + order_status。 */
|
||||
List<java.util.Map<String, Object>> selectTransferOrderStatuses(
|
||||
@Param("transferNos") List<String> transferNos,
|
||||
@Param("customerCodes") List<String> customerCodes);
|
||||
@Param("customerCodes") List<String> customerCodes,
|
||||
@Param("orderStatuses") List<Integer> orderStatuses);
|
||||
|
||||
/** 订单号下拉搜索(带数据权限) */
|
||||
public List<String> selectOrderNoOptions(@Param("query") PrcOrderBill query, @Param("limit") int limit);
|
||||
|
||||
@@ -35,14 +35,15 @@ public class OracleOrderBillMapper
|
||||
req.setUpstreamRow(row);
|
||||
req.setCustomerCode(firstStr(row, "CUSTOMER_CODE"));
|
||||
req.setCustomerName(firstStr(row, "CUSTOMER_NAME"));
|
||||
// Map LINE_CODE/LINE_NAME to product_code/product_name; fallback PRODUCT_*.
|
||||
String product = firstStr(row, "LINE_CODE", "PRODUCT_CODE");
|
||||
// Upstream product identity: TAB_ORDER.LINE_CODE / LINE_NAME only
|
||||
// (BMS product_code_mapping applied later in quote / persist).
|
||||
String product = firstStr(row, "LINE_CODE");
|
||||
if (StringUtils.isEmpty(product))
|
||||
{
|
||||
product = defaultProductCode;
|
||||
}
|
||||
req.setProductCode(product);
|
||||
req.setProductName(firstStr(row, "LINE_NAME", "PRODUCT_NAME"));
|
||||
req.setProductName(firstStr(row, "LINE_NAME"));
|
||||
req.setCountryCode(firstStr(row, "COUNTRY"));
|
||||
String countryName = firstStr(row, "COUNTRY_NAME", "COUNTRY_EINGTH_NAME", "COUNTRY");
|
||||
req.setCountryName(countryName);
|
||||
|
||||
@@ -24,6 +24,16 @@ public interface IPrcOrderBillService
|
||||
{
|
||||
TmsPriceQuoteResult bill(TmsPriceBillRequest request);
|
||||
|
||||
/**
|
||||
* Order-source sync only: overwrite local {@code prc_order_bill} + {@code prc_order_bill_ext}
|
||||
* from an Oracle TAB_ORDER row. No quote / credit / fee / refund / AR validation.
|
||||
* Rebilling remains on the order-list local-rebill path.
|
||||
*
|
||||
* @param upstreamRow Oracle TAB_ORDER full row
|
||||
* @return billId
|
||||
*/
|
||||
String syncUpstreamOverwrite(java.util.Map<String, Object> upstreamRow);
|
||||
|
||||
/**
|
||||
* Persist prc_order_bill and ext when billing cannot produce a quote.
|
||||
* Status outside 0/1/2/3 does not write prc_income_bill.
|
||||
|
||||
+13
-12
@@ -290,6 +290,19 @@ public class PrcBillingTaskServiceImpl implements IPrcBillingTaskService
|
||||
task.setCustomerCode(billReq.getCustomerCode());
|
||||
try
|
||||
{
|
||||
// No hard validate on customer/product/weight: always try bill (or soft-fail snapshot)
|
||||
// so upstream fields still overwrite. Quote failures land in persistFailedSnapshot.
|
||||
if (StringUtils.isEmpty(billReq.getOrderNo()))
|
||||
{
|
||||
if (StringUtils.isNotEmpty(billReq.getTransferNo()))
|
||||
{
|
||||
billReq.setOrderNo(billReq.getTransferNo().trim());
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(billReq.getTrackingNo()))
|
||||
{
|
||||
billReq.setOrderNo(billReq.getTrackingNo().trim());
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(billReq.getOrderNo()) && StringUtils.isEmpty(billReq.getTransferNo()))
|
||||
{
|
||||
throw new ServiceException("Oracle order mapped orderNo empty");
|
||||
@@ -308,18 +321,6 @@ public class PrcBillingTaskServiceImpl implements IPrcBillingTaskService
|
||||
deleteTaskAfterBillSaved(task);
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(billReq.getCustomerCode()))
|
||||
{
|
||||
throw new ServiceException("Oracle order mapped customerCode empty");
|
||||
}
|
||||
if (StringUtils.isEmpty(billReq.getProductCode()))
|
||||
{
|
||||
throw new ServiceException("Oracle order mapped productCode empty");
|
||||
}
|
||||
if (billReq.getWeight() == null || billReq.getWeight().signum() <= 0)
|
||||
{
|
||||
throw new ServiceException("Oracle order mapped weight invalid");
|
||||
}
|
||||
billWithDbRetry(taskId, billReq);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
|
||||
+280
-83
@@ -46,6 +46,7 @@ import com.bms.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.bms.customer.customerinfo.mapper.BmsCustomerMapper;
|
||||
import com.bms.system.mapper.SysUserMapper;
|
||||
import com.bms.system.service.IBmsBizRuleService;
|
||||
import com.bms.system.service.IBmsProductCodeMappingService;
|
||||
import com.bms.price.domain.PrcIncomeBill;
|
||||
import com.bms.price.domain.PrcIncomeBillFee;
|
||||
import com.bms.price.domain.PrcOrderBill;
|
||||
@@ -88,6 +89,7 @@ import com.bms.price.mapper.PrcOrderBillMapper;
|
||||
import com.bms.price.mapper.PrcPayBillFeeMapper;
|
||||
import com.bms.price.mapper.PrcPayBillMapper;
|
||||
import com.bms.price.oracle.OracleOrderBillExtFiller;
|
||||
import com.bms.price.oracle.OracleOrderBillMapper;
|
||||
import com.bms.price.search.EsBizLogSupport;
|
||||
import com.bms.price.search.EsLogType;
|
||||
import com.bms.price.search.IBillSearchStore;
|
||||
@@ -129,6 +131,9 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
@Autowired
|
||||
private PrcOrderBillExtMapper orderBillExtMapper;
|
||||
|
||||
@Autowired
|
||||
private OracleOrderBillMapper oracleOrderBillMapper;
|
||||
|
||||
@Autowired
|
||||
private PrcIncomeBillFeeMapper incomeBillFeeMapper;
|
||||
|
||||
@@ -171,6 +176,9 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
@Autowired
|
||||
private IBmsBizRuleService bizRuleService;
|
||||
|
||||
@Autowired
|
||||
private IBmsProductCodeMappingService productCodeMappingService;
|
||||
|
||||
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;
|
||||
@@ -1322,12 +1330,14 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
bill.setSurchargeAmount(surchargeTotal);
|
||||
bill.setIncomeTotal(incomeTotal);
|
||||
|
||||
String refundStatus = resolveRefundStatus(fees);
|
||||
PrcIncomeBill incomeBill = incomeBillMapper.selectByBillId(bill.getBillId());
|
||||
if (incomeBill != null)
|
||||
{
|
||||
incomeBill.setSalesAmount(incomeTotal);
|
||||
incomeBill.setIncomeTotal(incomeTotal);
|
||||
incomeBill.setCurrency(StringUtils.isEmpty(bill.getCurrency()) ? "CNY" : bill.getCurrency());
|
||||
incomeBill.setRefundStatus(refundStatus);
|
||||
incomeBillMapper.updatePrcIncomeBill(incomeBill);
|
||||
}
|
||||
|
||||
@@ -1335,7 +1345,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
StringUtils.isEmpty(bill.getCustomerActiveStatus())
|
||||
? BillCustomerActiveStatus.ACTIVE.getCode() : bill.getCustomerActiveStatus());
|
||||
bill.setCreditArrearsStatus(creditArrearsStatus);
|
||||
bill.setRefundStatus(resolveRefundStatus(fees));
|
||||
bill.setRefundStatus(refundStatus);
|
||||
orderBillMapper.updatePrcOrderBill(bill);
|
||||
orderBillMapper.refreshArBillStatusByBillIds(Arrays.asList(bill.getBillId()));
|
||||
return toResult(bill, fees, payBillFeeMapper.selectByBillId(bill.getBillId()));
|
||||
@@ -1660,54 +1670,49 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
}
|
||||
bill.setBillKey(billKey);
|
||||
bill.setOrderNo(orderNo);
|
||||
// Upstream header overwrite (no validate); charge_weight kept via resolvePersistChargeWeight below.
|
||||
applyUpstreamBillHeaderFields(bill, request);
|
||||
Long customerId = request.getCustomerId();
|
||||
if (customerId == null && result != null)
|
||||
{
|
||||
customerId = result.getCustomerId();
|
||||
}
|
||||
bill.setCustomerId(customerId == null ? Long.valueOf(0L) : customerId);
|
||||
String customerCode = request.getCustomerCode();
|
||||
if (StringUtils.isEmpty(customerCode) && result != null)
|
||||
if (customerId == null || customerId.longValue() <= 0L)
|
||||
{
|
||||
customerCode = result.getCustomerCode();
|
||||
customerId = resolveCustomerIdByCode(request.getCustomerCode(), bill.getCustomerId());
|
||||
}
|
||||
bill.setCustomerId(customerId == null ? Long.valueOf(0L) : customerId);
|
||||
if (StringUtils.isEmpty(bill.getCustomerCode()) && result != null)
|
||||
{
|
||||
bill.setCustomerCode(result.getCustomerCode());
|
||||
}
|
||||
bill.setCustomerCode(customerCode);
|
||||
bill.setCustomerName(request.getCustomerName());
|
||||
bill.setTrackingNo(request.getTrackingNo());
|
||||
bill.setTransferNo(request.getTransferNo());
|
||||
// Oracle 中文人员名 -> sys_user.nick_name,*_code 写 user_name(数据权限)
|
||||
resolveOrderStaffFromSysUser(request);
|
||||
bill.setBelongSaler(request.getBelongSaler());
|
||||
bill.setBelongSalerCode(request.getBelongSalerCode());
|
||||
bill.setSettlementMan(request.getSettlementMan());
|
||||
bill.setSettlementManCode(request.getSettlementManCode());
|
||||
bill.setServiceMan(request.getServiceMan());
|
||||
bill.setServiceManCode(request.getServiceManCode());
|
||||
String customerActiveStatus = result == null ? null : result.getCustomerActiveStatus();
|
||||
if (StringUtils.isEmpty(customerActiveStatus))
|
||||
{
|
||||
customerActiveStatus = BillCustomerActiveStatus.ACTIVE.getCode();
|
||||
}
|
||||
bill.setCustomerActiveStatus(customerActiveStatus);
|
||||
bill.setPieces(request.getPieces());
|
||||
bill.setActualWeight(request.getActualWeight());
|
||||
bill.setReceiveWeight(request.getReceiveWeight());
|
||||
bill.setVolume(request.getVolume());
|
||||
bill.setVolumeWeight(request.getVolumeWeight());
|
||||
bill.setPkgLength(request.getPkgLength());
|
||||
bill.setPkgWidth(request.getPkgWidth());
|
||||
bill.setPkgHeight(request.getPkgHeight());
|
||||
bill.setShipperName(request.getShipperName());
|
||||
bill.setConsigneeName(request.getConsigneeName());
|
||||
bill.setDestPostcode(request.getDestPostcode());
|
||||
bill.setWarehouseCode(request.getWarehouseCode());
|
||||
bill.setOrderTime(request.getOrderTime());
|
||||
applyUpstreamOrderStatus(bill, request);
|
||||
bill.setOrderRemark(request.getOrderRemark());
|
||||
bill.setProductCode(result.getProductCode());
|
||||
bill.setProductName(result.getProductName());
|
||||
bill.setCountryCode(result.getCountryCode());
|
||||
bill.setCountryName(result.getCountryName());
|
||||
// Product: quote result already resolved LINE_CODE via product_code_mapping.
|
||||
if (result != null && StringUtils.isNotEmpty(result.getProductCode()))
|
||||
{
|
||||
bill.setProductCode(result.getProductCode());
|
||||
}
|
||||
else
|
||||
{
|
||||
applyProductCodeMapping(bill, request);
|
||||
}
|
||||
if (result != null && StringUtils.isNotEmpty(result.getProductName()))
|
||||
{
|
||||
bill.setProductName(result.getProductName());
|
||||
}
|
||||
if (StringUtils.isEmpty(bill.getCountryCode()) && result != null)
|
||||
{
|
||||
bill.setCountryCode(result.getCountryCode());
|
||||
}
|
||||
if (StringUtils.isEmpty(bill.getCountryName()) && result != null)
|
||||
{
|
||||
bill.setCountryName(result.getCountryName());
|
||||
}
|
||||
// weight = system/original; charge_weight = effective (may be manual override)
|
||||
bill.setWeight(weight);
|
||||
bill.setBizDate(bizDate);
|
||||
@@ -2803,6 +2808,151 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order-source sync: full upstream field overwrite onto local bill + ext.
|
||||
* Does not quote, occupy credit, touch fees, or validate AR / refund.
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String syncUpstreamOverwrite(java.util.Map<String, Object> upstreamRow)
|
||||
{
|
||||
if (upstreamRow == null || upstreamRow.isEmpty())
|
||||
{
|
||||
throw new ServiceException("Oracle order row empty");
|
||||
}
|
||||
TmsPriceBillRequest request = oracleOrderBillMapper.toBillRequest(upstreamRow, null);
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceException("Oracle order mapped empty");
|
||||
}
|
||||
request.setUpstreamRow(upstreamRow);
|
||||
|
||||
String orderNo = StringUtils.trim(request.getOrderNo());
|
||||
String transferNo = StringUtils.trim(request.getTransferNo());
|
||||
String trackingNo = StringUtils.trim(request.getTrackingNo());
|
||||
if (StringUtils.isEmpty(orderNo))
|
||||
{
|
||||
orderNo = transferNo;
|
||||
}
|
||||
if (StringUtils.isEmpty(orderNo))
|
||||
{
|
||||
orderNo = trackingNo;
|
||||
}
|
||||
if (StringUtils.isEmpty(orderNo))
|
||||
{
|
||||
throw new ServiceException("Oracle order mapped orderNo empty");
|
||||
}
|
||||
request.setOrderNo(orderNo);
|
||||
|
||||
PrcOrderBill existed = orderBillMapper.selectPrcOrderBillByOrderNo(orderNo);
|
||||
if (existed == null && StringUtils.isNotEmpty(transferNo))
|
||||
{
|
||||
existed = orderBillMapper.selectPrcOrderBillByTransferNo(transferNo);
|
||||
}
|
||||
if (existed == null && StringUtils.isNotEmpty(trackingNo))
|
||||
{
|
||||
List<PrcOrderBill> byTrack = orderBillMapper.selectPrcOrderBillByTmsIdentifier(trackingNo);
|
||||
if (byTrack != null && !byTrack.isEmpty())
|
||||
{
|
||||
existed = byTrack.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
boolean creating = existed == null;
|
||||
PrcOrderBill bill = creating ? new PrcOrderBill() : existed;
|
||||
if (creating)
|
||||
{
|
||||
bill.setBillId(UUID.randomUUID().toString());
|
||||
bill.setArBillStatus(ArOrderBillStatus.UNBILLED.getCode());
|
||||
bill.setRefundStatus(BillRefundStatus.NONE.getCode());
|
||||
bill.setBillingFailStatus(Integer.valueOf(BillBillingFailStatus.SUCCESS.getCode()));
|
||||
bill.setFreightRate(BigDecimal.ZERO);
|
||||
bill.setBaseFreightRate(BigDecimal.ZERO);
|
||||
bill.setRegistrationFee(BigDecimal.ZERO);
|
||||
bill.setFreightAmount(BigDecimal.ZERO);
|
||||
bill.setSurchargeAmount(BigDecimal.ZERO);
|
||||
bill.setIncomeTotal(BigDecimal.ZERO);
|
||||
bill.setPayTotal(BigDecimal.ZERO);
|
||||
bill.setCurrency("CNY");
|
||||
bill.setRoundMode("HALF_UP");
|
||||
bill.setCustomerActiveStatus(BillCustomerActiveStatus.ACTIVE.getCode());
|
||||
bill.setCreditArrearsStatus(BillCreditArrearsStatus.NORMAL.getCode());
|
||||
}
|
||||
|
||||
bill.setBillKey(Md5Utils.hash(orderNo));
|
||||
bill.setOrderNo(orderNo);
|
||||
applyUpstreamBillHeaderFields(bill, request);
|
||||
applyProductCodeMapping(bill, request);
|
||||
Long customerId = resolveCustomerIdByCode(request.getCustomerCode(), bill.getCustomerId());
|
||||
bill.setCustomerId(customerId == null ? Long.valueOf(0L) : customerId);
|
||||
// System weight overwrite; charge_weight keeps existing manual override when present.
|
||||
if (request.getWeight() != null)
|
||||
{
|
||||
bill.setWeight(request.getWeight());
|
||||
if (creating || bill.getChargeWeight() == null)
|
||||
{
|
||||
bill.setChargeWeight(request.getWeight());
|
||||
}
|
||||
}
|
||||
if (creating)
|
||||
{
|
||||
Date bizDate = request.getPickupDate() != null ? request.getPickupDate() : new Date();
|
||||
bill.setBizDate(bizDate);
|
||||
}
|
||||
|
||||
if (creating)
|
||||
{
|
||||
orderBillMapper.insertPrcOrderBill(bill);
|
||||
}
|
||||
else
|
||||
{
|
||||
orderBillMapper.updatePrcOrderBill(bill);
|
||||
}
|
||||
persistBillExt(bill, upstreamRow);
|
||||
|
||||
JSONObject req = new JSONObject();
|
||||
req.put("action", "UPSTREAM_SYNC");
|
||||
req.put("orderNo", orderNo);
|
||||
req.put("transferNo", bill.getTransferNo());
|
||||
req.put("billId", bill.getBillId());
|
||||
req.put("orderStatus", bill.getOrderStatus());
|
||||
req.put("creating", Boolean.valueOf(creating));
|
||||
billSearchStore.save(EsLogType.BILL, bill.getBillId(), req.toJSONString(),
|
||||
"{\"ok\":true,\"action\":\"UPSTREAM_SYNC\"}");
|
||||
return bill.getBillId();
|
||||
}
|
||||
|
||||
/** Best-effort customer id by code; keep previous id when lookup misses. */
|
||||
private Long resolveCustomerIdByCode(String customerCode, Long previousId)
|
||||
{
|
||||
if (StringUtils.isEmpty(customerCode))
|
||||
{
|
||||
return previousId;
|
||||
}
|
||||
try
|
||||
{
|
||||
BmsCustomer query = new BmsCustomer();
|
||||
query.setCustomerCode(customerCode.trim());
|
||||
List<BmsCustomer> list = bmsCustomerMapper.selectBmsCustomerList(query);
|
||||
if (list != null)
|
||||
{
|
||||
for (BmsCustomer row : list)
|
||||
{
|
||||
if (row != null && row.getCustomerId() != null
|
||||
&& customerCode.trim().equalsIgnoreCase(StringUtils.trim(row.getCustomerCode())))
|
||||
{
|
||||
return row.getCustomerId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
log.warn("resolveCustomerIdByCode skip code={} msg={}", customerCode, e.getMessage());
|
||||
}
|
||||
return previousId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void persistFailedSnapshot(TmsPriceBillRequest request, int billingFailStatus, String errorMessage)
|
||||
@@ -2839,41 +2989,19 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
}
|
||||
bill.setBillKey(Md5Utils.hash(orderNo));
|
||||
bill.setOrderNo(orderNo);
|
||||
bill.setCustomerId(request.getCustomerId() == null ? Long.valueOf(0L) : request.getCustomerId());
|
||||
bill.setCustomerCode(request.getCustomerCode());
|
||||
bill.setCustomerName(request.getCustomerName());
|
||||
bill.setTrackingNo(request.getTrackingNo());
|
||||
bill.setTransferNo(request.getTransferNo());
|
||||
resolveOrderStaffFromSysUser(request);
|
||||
bill.setBelongSaler(request.getBelongSaler());
|
||||
bill.setBelongSalerCode(request.getBelongSalerCode());
|
||||
bill.setSettlementMan(request.getSettlementMan());
|
||||
bill.setSettlementManCode(request.getSettlementManCode());
|
||||
bill.setServiceMan(request.getServiceMan());
|
||||
bill.setServiceManCode(request.getServiceManCode());
|
||||
applyUpstreamBillHeaderFields(bill, request);
|
||||
applyProductCodeMapping(bill, request);
|
||||
Long customerId = request.getCustomerId();
|
||||
if (customerId == null || customerId.longValue() <= 0L)
|
||||
{
|
||||
customerId = resolveCustomerIdByCode(request.getCustomerCode(), bill.getCustomerId());
|
||||
}
|
||||
bill.setCustomerId(customerId == null ? Long.valueOf(0L) : customerId);
|
||||
if (StringUtils.isEmpty(bill.getCustomerActiveStatus()))
|
||||
{
|
||||
bill.setCustomerActiveStatus(BillCustomerActiveStatus.ACTIVE.getCode());
|
||||
}
|
||||
bill.setPieces(request.getPieces());
|
||||
bill.setActualWeight(request.getActualWeight());
|
||||
bill.setReceiveWeight(request.getReceiveWeight());
|
||||
bill.setVolume(request.getVolume());
|
||||
bill.setVolumeWeight(request.getVolumeWeight());
|
||||
bill.setPkgLength(request.getPkgLength());
|
||||
bill.setPkgWidth(request.getPkgWidth());
|
||||
bill.setPkgHeight(request.getPkgHeight());
|
||||
bill.setShipperName(request.getShipperName());
|
||||
bill.setConsigneeName(request.getConsigneeName());
|
||||
bill.setDestPostcode(request.getDestPostcode());
|
||||
bill.setWarehouseCode(request.getWarehouseCode());
|
||||
bill.setOrderTime(request.getOrderTime());
|
||||
applyUpstreamOrderStatus(bill, request);
|
||||
bill.setOrderRemark(request.getOrderRemark());
|
||||
bill.setProductCode(request.getProductCode());
|
||||
bill.setProductName(request.getProductName());
|
||||
bill.setCountryCode(request.getCountryCode());
|
||||
bill.setCountryName(request.getCountryName());
|
||||
// Soft-fail snapshot: overwrite system weight; do not touch charge_weight (keep current logic).
|
||||
bill.setWeight(request.getWeight());
|
||||
Date bizDate = StringUtils.isEmpty(request.getBizDate()) ? new Date() : resolveBizDate(request.getBizDate());
|
||||
bill.setBizDate(bizDate);
|
||||
@@ -2920,22 +3048,18 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
}
|
||||
|
||||
/**
|
||||
* Locked by AR bill: write fail status + upstream ORDER_STATUS only.
|
||||
* Amounts / income fees stay untouched.
|
||||
* Locked by AR bill: overwrite upstream header + ext; keep amounts / fees / charge_weight.
|
||||
*/
|
||||
private void persistFailedSnapshotWhenLocked(PrcOrderBill bill, TmsPriceBillRequest request,
|
||||
int billingFailStatus, String errorMessage)
|
||||
{
|
||||
applyUpstreamOrderStatus(bill, request);
|
||||
if (request != null)
|
||||
{
|
||||
if (StringUtils.isNotEmpty(request.getTrackingNo()))
|
||||
applyUpstreamBillHeaderFields(bill, request);
|
||||
applyProductCodeMapping(bill, request);
|
||||
if (request.getWeight() != null)
|
||||
{
|
||||
bill.setTrackingNo(request.getTrackingNo());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(request.getTransferNo()))
|
||||
{
|
||||
bill.setTransferNo(request.getTransferNo());
|
||||
bill.setWeight(request.getWeight());
|
||||
}
|
||||
}
|
||||
applyBillingFailText(bill, billingFailStatus, errorMessage);
|
||||
@@ -2946,19 +3070,92 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer request status fields; never clear existing order_status with null. */
|
||||
/**
|
||||
* Overwrite local bill header fields from upstream request (no validation).
|
||||
* Does not set weight / charge_weight / bizDate / amounts / customerId.
|
||||
*/
|
||||
private void applyUpstreamBillHeaderFields(PrcOrderBill bill, TmsPriceBillRequest request)
|
||||
{
|
||||
if (bill == null || request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
resolveOrderStaffFromSysUser(request);
|
||||
bill.setCustomerCode(request.getCustomerCode());
|
||||
bill.setCustomerName(request.getCustomerName());
|
||||
bill.setTrackingNo(request.getTrackingNo());
|
||||
bill.setTransferNo(request.getTransferNo());
|
||||
bill.setBelongSaler(request.getBelongSaler());
|
||||
bill.setBelongSalerCode(request.getBelongSalerCode());
|
||||
bill.setSettlementMan(request.getSettlementMan());
|
||||
bill.setSettlementManCode(request.getSettlementManCode());
|
||||
bill.setServiceMan(request.getServiceMan());
|
||||
bill.setServiceManCode(request.getServiceManCode());
|
||||
bill.setPieces(request.getPieces());
|
||||
bill.setActualWeight(request.getActualWeight());
|
||||
bill.setReceiveWeight(request.getReceiveWeight());
|
||||
bill.setVolume(request.getVolume());
|
||||
bill.setVolumeWeight(request.getVolumeWeight());
|
||||
bill.setPkgLength(request.getPkgLength());
|
||||
bill.setPkgWidth(request.getPkgWidth());
|
||||
bill.setPkgHeight(request.getPkgHeight());
|
||||
bill.setShipperName(request.getShipperName());
|
||||
bill.setConsigneeName(request.getConsigneeName());
|
||||
bill.setDestPostcode(request.getDestPostcode());
|
||||
bill.setWarehouseCode(request.getWarehouseCode());
|
||||
bill.setOrderTime(request.getOrderTime());
|
||||
applyUpstreamOrderStatus(bill, request);
|
||||
bill.setOrderRemark(request.getOrderRemark());
|
||||
// Source = TAB_ORDER.LINE_CODE / LINE_NAME (mapping applied by caller after quote / sync).
|
||||
bill.setProductCode(request.getProductCode());
|
||||
bill.setProductName(request.getProductName());
|
||||
bill.setCountryCode(request.getCountryCode());
|
||||
bill.setCountryName(request.getCountryName());
|
||||
}
|
||||
|
||||
/**
|
||||
* LINE_CODE (on request/bill) -> BMS product via product_code_mapping when configured.
|
||||
*/
|
||||
private void applyProductCodeMapping(PrcOrderBill bill, TmsPriceBillRequest request)
|
||||
{
|
||||
if (bill == null || productCodeMappingService == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String upstream = bill.getProductCode();
|
||||
if (StringUtils.isEmpty(upstream) && request != null)
|
||||
{
|
||||
upstream = request.getProductCode();
|
||||
}
|
||||
if (StringUtils.isEmpty(upstream))
|
||||
{
|
||||
return;
|
||||
}
|
||||
String mapped = productCodeMappingService.resolveBmsProductCode(upstream.trim());
|
||||
if (StringUtils.isEmpty(mapped))
|
||||
{
|
||||
return;
|
||||
}
|
||||
mapped = mapped.trim();
|
||||
bill.setProductCode(mapped);
|
||||
if (request != null)
|
||||
{
|
||||
request.setProductCode(mapped);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer request status fields; never clear existing order_status with null.
|
||||
* Do not pin order_status to 9/10 when refundStatus=REFUNDED — rebill / upstream
|
||||
* bill must follow Oracle ORDER_STATUS. Actual fee refund still sets 9 in {@link #refund}.
|
||||
*/
|
||||
private static void applyUpstreamOrderStatus(PrcOrderBill bill, TmsPriceBillRequest request)
|
||||
{
|
||||
if (bill == null || request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Fee refund marks order_status=9 (已退件); do not let Oracle sync overwrite it.
|
||||
if (BillRefundStatus.REFUNDED.getCode().equalsIgnoreCase(bill.getRefundStatus()))
|
||||
{
|
||||
bill.setOrderStatus(BillOrderStatus.REFUNDED.getCodeBoxed());
|
||||
}
|
||||
else if (request.getOrderStatus() != null)
|
||||
if (request.getOrderStatus() != null)
|
||||
{
|
||||
bill.setOrderStatus(request.getOrderStatus());
|
||||
}
|
||||
|
||||
+66
-138
@@ -1,11 +1,14 @@
|
||||
package com.bms.price.task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -22,7 +25,8 @@ import com.bms.price.search.IBillSearchStore;
|
||||
import com.bms.price.search.TabOrderSyncEsLog;
|
||||
|
||||
/**
|
||||
* 订单比对异步任务:分页拉上游转单号+状态,与本地 transfer_no / order_status 比对。
|
||||
* 订单比对异步任务:分页拉上游转单号,与本地 transfer_no 比对是否缺失。
|
||||
* 上游扫描与本地匹配均使用列表「订单状态」筛选;不再比对/列出状态不一致。
|
||||
*/
|
||||
@Component
|
||||
public class TabOrderCompareAsyncRunner
|
||||
@@ -36,8 +40,12 @@ public class TabOrderCompareAsyncRunner
|
||||
public static final int SCAN_HARD_LIMIT = 50000;
|
||||
/** 进度/抽屉中保留的缺失转单号上限 */
|
||||
public static final int MISSING_SAMPLE_LIMIT = 5000;
|
||||
/** 状态不一致样本上限 */
|
||||
public static final int STATUS_MISMATCH_SAMPLE_LIMIT = 5000;
|
||||
|
||||
/** Fallback when search orderStatuses empty (same as order-source list default). */
|
||||
public static final List<Integer> COMPARE_LOCAL_ORDER_STATUSES =
|
||||
Collections.unmodifiableList(Arrays.asList(
|
||||
Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6),
|
||||
Integer.valueOf(7), Integer.valueOf(8), Integer.valueOf(11)));
|
||||
|
||||
@Autowired
|
||||
private TabOrderMonitorService tabOrderMonitorService;
|
||||
@@ -63,14 +71,18 @@ public class TabOrderCompareAsyncRunner
|
||||
query.setOrgOrderId(null);
|
||||
query.setTransferOrderId(null);
|
||||
}
|
||||
// Use list filter orderStatuses for both upstream scan and local match (no hardcode).
|
||||
List<Integer> compareStatuses = resolveCompareStatuses(query);
|
||||
if (query != null)
|
||||
{
|
||||
query.setOrderStatuses(new ArrayList<Integer>(compareStatuses));
|
||||
}
|
||||
put(asyncTaskId, TabOrderCompareTask.STATUS_RUNNING, 0, "starting",
|
||||
0, 0, 0, 0, null, null, null);
|
||||
0, 0, 0, null, null);
|
||||
int scanned = 0;
|
||||
int matched = 0;
|
||||
int missing = 0;
|
||||
int statusMismatch = 0;
|
||||
List<String> missingSample = new ArrayList<String>();
|
||||
List<Map<String, Object>> statusMismatchSample = new ArrayList<Map<String, Object>>();
|
||||
int pageNum = 1;
|
||||
while (true)
|
||||
{
|
||||
@@ -96,8 +108,8 @@ public class TabOrderCompareAsyncRunner
|
||||
transferNos.add(String.valueOf(tn).trim());
|
||||
}
|
||||
}
|
||||
Map<String, Integer> localStatusByTn =
|
||||
findLocalStatuses(transferNos, query == null ? null : query.getCustomerCodes());
|
||||
Set<String> localTns = findLocalTransferNos(
|
||||
transferNos, query == null ? null : query.getCustomerCodes(), compareStatuses);
|
||||
for (Map<String, Object> row : pageRows)
|
||||
{
|
||||
if (row == null)
|
||||
@@ -112,8 +124,7 @@ public class TabOrderCompareAsyncRunner
|
||||
String tn = String.valueOf(tnObj).trim();
|
||||
scanned++;
|
||||
String key = tn.toUpperCase(Locale.ROOT);
|
||||
Integer upstreamStatus = toInteger(row.get("orderStatus"));
|
||||
if (!localStatusByTn.containsKey(key))
|
||||
if (!localTns.contains(key))
|
||||
{
|
||||
missing++;
|
||||
if (missingSample.size() < MISSING_SAMPLE_LIMIT)
|
||||
@@ -123,19 +134,6 @@ public class TabOrderCompareAsyncRunner
|
||||
continue;
|
||||
}
|
||||
matched++;
|
||||
Integer localStatus = localStatusByTn.get(key);
|
||||
if (!statusEquals(upstreamStatus, localStatus))
|
||||
{
|
||||
statusMismatch++;
|
||||
if (statusMismatchSample.size() < STATUS_MISMATCH_SAMPLE_LIMIT)
|
||||
{
|
||||
Map<String, Object> one = new LinkedHashMap<String, Object>();
|
||||
one.put("transferNo", tn);
|
||||
one.put("upstreamStatus", upstreamStatus);
|
||||
one.put("localStatus", localStatus);
|
||||
statusMismatchSample.add(one);
|
||||
}
|
||||
}
|
||||
}
|
||||
int percent = Math.min(99, (int) ((scanned * 100L) / Math.max(scanned + pageSize, 1)));
|
||||
if (pageRows.size() < pageSize)
|
||||
@@ -143,9 +141,8 @@ public class TabOrderCompareAsyncRunner
|
||||
percent = 99;
|
||||
}
|
||||
put(asyncTaskId, TabOrderCompareTask.STATUS_RUNNING, percent,
|
||||
"scanning page=" + pageNum + " scanned=" + scanned
|
||||
+ " missing=" + missing + " statusMismatch=" + statusMismatch,
|
||||
scanned, matched, missing, statusMismatch, null, missingSample, statusMismatchSample);
|
||||
"scanning page=" + pageNum + " scanned=" + scanned + " missing=" + missing,
|
||||
scanned, matched, missing, null, missingSample);
|
||||
if (pageRows.size() < pageSize)
|
||||
{
|
||||
break;
|
||||
@@ -157,30 +154,19 @@ public class TabOrderCompareAsyncRunner
|
||||
resp.put("scanned", Integer.valueOf(scanned));
|
||||
resp.put("matched", Integer.valueOf(matched));
|
||||
resp.put("missing", Integer.valueOf(missing));
|
||||
resp.put("statusMismatch", Integer.valueOf(statusMismatch));
|
||||
resp.put("statusMismatch", Integer.valueOf(0));
|
||||
resp.put("missingTransferNos", missingSample);
|
||||
resp.put("statusMismatchSamples", statusMismatchSample);
|
||||
List<String> mismatchTns = new ArrayList<String>();
|
||||
for (Map<String, Object> one : statusMismatchSample)
|
||||
{
|
||||
if (one == null) { continue; }
|
||||
Object tn = one.get("transferNo");
|
||||
if (tn != null && StringUtils.isNotEmpty(String.valueOf(tn).trim()))
|
||||
{
|
||||
mismatchTns.add(String.valueOf(tn).trim());
|
||||
}
|
||||
}
|
||||
resp.put("statusMismatchTransferNos", mismatchTns);
|
||||
resp.put("statusMismatchSamples", Collections.emptyList());
|
||||
resp.put("statusMismatchTransferNos", Collections.emptyList());
|
||||
resp.put("missingTruncated", Boolean.valueOf(missing > missingSample.size()));
|
||||
resp.put("statusMismatchTruncated",
|
||||
Boolean.valueOf(statusMismatch > statusMismatchSample.size()));
|
||||
resp.put("statusMismatchTruncated", Boolean.FALSE);
|
||||
put(asyncTaskId, TabOrderCompareTask.STATUS_SUCCESS, 100,
|
||||
"done scanned=" + scanned + " missing=" + missing + " statusMismatch=" + statusMismatch,
|
||||
scanned, matched, missing, statusMismatch, null, missingSample, statusMismatchSample);
|
||||
"done scanned=" + scanned + " missing=" + missing,
|
||||
scanned, matched, missing, null, missingSample);
|
||||
TabOrderSyncEsLog.save(billSearchStore, asyncTaskId, "COMPARE_DONE", query, resp, "SUCCESS", null);
|
||||
log.info("orderSource compare done asyncTaskId={} scanned={} matched={} missing={} statusMismatch={}",
|
||||
log.info("orderSource compare done asyncTaskId={} scanned={} matched={} missing={}",
|
||||
asyncTaskId, Integer.valueOf(scanned), Integer.valueOf(matched),
|
||||
Integer.valueOf(missing), Integer.valueOf(statusMismatch));
|
||||
Integer.valueOf(missing));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -191,100 +177,56 @@ public class TabOrderCompareAsyncRunner
|
||||
msg = e.getClass().getSimpleName();
|
||||
}
|
||||
put(asyncTaskId, TabOrderCompareTask.STATUS_FAIL, 100, "failed",
|
||||
0, 0, 0, 0, msg, null, null);
|
||||
0, 0, 0, msg, null);
|
||||
TabOrderSyncEsLog.save(billSearchStore, asyncTaskId, "COMPARE_DONE", query, null, "FAIL", msg);
|
||||
}
|
||||
}
|
||||
|
||||
/** transferNo(upper) -> local order_status (null value means local row exists with null status). */
|
||||
private Map<String, Integer> findLocalStatuses(List<String> transferNos, List<String> customerCodes)
|
||||
/**
|
||||
* Prefer search filter orderStatuses; if empty, same default as order-source list
|
||||
* (3/4/5/6/7/8/11) so SQL still has an IN list.
|
||||
*/
|
||||
private static List<Integer> resolveCompareStatuses(TabOrderMonitorQuery query)
|
||||
{
|
||||
Map<String, Integer> found = new HashMap<String, Integer>();
|
||||
List<Integer> cleaned = new ArrayList<Integer>();
|
||||
if (query != null && query.getOrderStatuses() != null)
|
||||
{
|
||||
for (Integer s : query.getOrderStatuses())
|
||||
{
|
||||
if (s != null)
|
||||
{
|
||||
cleaned.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cleaned.isEmpty() ? new ArrayList<Integer>(COMPARE_LOCAL_ORDER_STATUSES) : cleaned;
|
||||
}
|
||||
|
||||
/** transferNo(upper) present locally with the given order_status filter. */
|
||||
private Set<String> findLocalTransferNos(List<String> transferNos, List<String> customerCodes,
|
||||
List<Integer> orderStatuses)
|
||||
{
|
||||
Set<String> found = new HashSet<String>();
|
||||
if (transferNos == null || transferNos.isEmpty())
|
||||
{
|
||||
return found;
|
||||
}
|
||||
List<Map<String, Object>> rows =
|
||||
prcOrderBillMapper.selectTransferOrderStatuses(transferNos, cleanCodes(customerCodes));
|
||||
List<String> rows = prcOrderBillMapper.selectExistingTransferNos(
|
||||
transferNos, cleanCodes(customerCodes), orderStatuses);
|
||||
if (rows == null)
|
||||
{
|
||||
return found;
|
||||
}
|
||||
for (Map<String, Object> row : rows)
|
||||
for (String tn : rows)
|
||||
{
|
||||
if (row == null)
|
||||
if (StringUtils.isNotEmpty(tn))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Object tn = first(row, "transferNo", "TRANSFERNO", "transfer_no");
|
||||
if (tn == null || StringUtils.isEmpty(String.valueOf(tn).trim()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String key = String.valueOf(tn).trim().toUpperCase(Locale.ROOT);
|
||||
Integer st = toInteger(first(row, "orderStatus", "ORDERSTATUS", "order_status"));
|
||||
// Keep first hit; duplicate transfer_no rare.
|
||||
if (!found.containsKey(key))
|
||||
{
|
||||
found.put(key, st);
|
||||
found.add(tn.trim().toUpperCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private static Object first(Map<String, Object> row, String... keys)
|
||||
{
|
||||
if (row == null || keys == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for (String k : keys)
|
||||
{
|
||||
if (row.containsKey(k) && row.get(k) != null)
|
||||
{
|
||||
return row.get(k);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Integer toInteger(Object v)
|
||||
{
|
||||
if (v == null || "".equals(String.valueOf(v).trim()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (v instanceof Integer)
|
||||
{
|
||||
return (Integer) v;
|
||||
}
|
||||
if (v instanceof Number)
|
||||
{
|
||||
return Integer.valueOf(((Number) v).intValue());
|
||||
}
|
||||
try
|
||||
{
|
||||
return Integer.valueOf(String.valueOf(v).trim());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean statusEquals(Integer a, Integer b)
|
||||
{
|
||||
if (a == null && b == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (a == null || b == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return a.intValue() == b.intValue();
|
||||
}
|
||||
|
||||
private static List<String> cleanCodes(List<String> codes)
|
||||
{
|
||||
if (codes == null || codes.isEmpty())
|
||||
@@ -303,8 +245,7 @@ public class TabOrderCompareAsyncRunner
|
||||
}
|
||||
|
||||
public void put(String taskId, String status, int percent, String message,
|
||||
int scanned, int matched, int missing, int statusMismatch, String error,
|
||||
List<String> missingSample, List<Map<String, Object>> statusMismatchSample)
|
||||
int scanned, int matched, int missing, String error, List<String> missingSample)
|
||||
{
|
||||
TabOrderCompareTask task = new TabOrderCompareTask();
|
||||
task.setTaskId(taskId);
|
||||
@@ -314,27 +255,14 @@ public class TabOrderCompareAsyncRunner
|
||||
task.setScanned(scanned);
|
||||
task.setMatched(matched);
|
||||
task.setMissing(missing);
|
||||
task.setStatusMismatch(statusMismatch);
|
||||
task.setStatusMismatch(0);
|
||||
task.setError(error);
|
||||
if (missingSample != null)
|
||||
{
|
||||
task.setMissingTransferNos(new ArrayList<String>(missingSample));
|
||||
}
|
||||
if (statusMismatchSample != null)
|
||||
{
|
||||
task.setStatusMismatchSamples(new ArrayList<Map<String, Object>>(statusMismatchSample));
|
||||
List<String> tnList = new ArrayList<String>();
|
||||
for (Map<String, Object> one : statusMismatchSample)
|
||||
{
|
||||
if (one == null) { continue; }
|
||||
Object tn = one.get("transferNo");
|
||||
if (tn != null && StringUtils.isNotEmpty(String.valueOf(tn).trim()))
|
||||
{
|
||||
tnList.add(String.valueOf(tn).trim());
|
||||
}
|
||||
}
|
||||
task.setStatusMismatchTransferNos(tnList);
|
||||
}
|
||||
task.setStatusMismatchSamples(new ArrayList<Map<String, Object>>());
|
||||
task.setStatusMismatchTransferNos(new ArrayList<String>());
|
||||
redisCache.setCacheObject(CACHE_KEY_PREFIX + taskId, task, TTL_MINUTES, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,21 +22,17 @@ 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.PrcBillingTask;
|
||||
import com.bms.price.domain.PrcBillingTaskRetryTask;
|
||||
import com.bms.price.domain.vo.BillingTaskSubmitRequest;
|
||||
import com.bms.price.domain.vo.TabOrderMonitorQuery;
|
||||
import com.bms.price.domain.vo.TabOrderMonitorVo;
|
||||
import com.bms.price.enums.BillOrderStatus;
|
||||
import com.bms.price.enums.BillTaskSuccessStatus;
|
||||
import com.bms.price.enums.BillTaskType;
|
||||
import com.bms.price.oracle.OracleUpstreamOrderService;
|
||||
import com.bms.price.oracle.TabOrderMonitorService;
|
||||
import com.bms.price.search.IBillSearchStore;
|
||||
import com.bms.price.search.TabOrderSyncEsLog;
|
||||
import com.bms.price.service.IPrcBillingTaskService;
|
||||
import com.bms.price.service.IPrcOrderBillService;
|
||||
|
||||
/**
|
||||
* Page Oracle TAB_ORDER then multi-thread submitAndProcess each row.
|
||||
* Page Oracle TAB_ORDER then multi-thread overwrite local bill fields (no billing).
|
||||
*/
|
||||
@Component
|
||||
public class TabOrderSyncAsyncRunner
|
||||
@@ -59,7 +55,10 @@ public class TabOrderSyncAsyncRunner
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private IPrcBillingTaskService billingTaskService;
|
||||
private IPrcOrderBillService prcOrderBillService;
|
||||
|
||||
@Autowired
|
||||
private OracleUpstreamOrderService oracleUpstreamOrderService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
@@ -201,8 +200,7 @@ public class TabOrderSyncAsyncRunner
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync or refund selected rows.
|
||||
* @param billType optional PENDING/REBILL/REFUND; null = auto by orderStatus / bill existence
|
||||
* Sync selected rows (upstream field overwrite only; billType ignored).
|
||||
*/
|
||||
public Map<String, Object> syncRowsParallel(List<TabOrderMonitorVo> rows, String billType)
|
||||
{
|
||||
@@ -220,8 +218,8 @@ public class TabOrderSyncAsyncRunner
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync or refund selected rows carrying the upstream Oracle full row (skip re-query).
|
||||
* @param billType optional PENDING/REBILL/REFUND; null = auto by orderStatus / bill existence
|
||||
* Sync selected rows carrying the upstream Oracle full row when present (skip re-query).
|
||||
* Overwrites local bill fields only; does not bill / refund.
|
||||
*/
|
||||
public Map<String, Object> syncRowsParallelRows(List<com.bms.price.oracle.TabOrderRow> rows, String billType)
|
||||
{
|
||||
@@ -234,7 +232,6 @@ public class TabOrderSyncAsyncRunner
|
||||
data.put("details", details);
|
||||
return data;
|
||||
}
|
||||
final String fixedBillType = StringUtils.isEmpty(billType) ? null : billType.trim();
|
||||
int threads = Math.min(clampThreads(billingProperties == null ? null : billingProperties.getOrderSourceSyncThreads()),
|
||||
Math.max(1, rows.size()));
|
||||
ExecutorService pool = newWorkerPool(threads, "order-source-sel");
|
||||
@@ -253,26 +250,16 @@ public class TabOrderSyncAsyncRunner
|
||||
item.put("transferOrderId", vo == null ? null : vo.getTransferOrderId());
|
||||
try
|
||||
{
|
||||
PrcBillingTask task = billingTaskService.submitAndProcess(
|
||||
toSubmit(vo, fixedBillType), one == null ? null : one.getRaw());
|
||||
item.put("successStatus", task == null ? null : task.getSuccessStatus());
|
||||
item.put("errorMessage", task == null ? null : task.getErrorMessage());
|
||||
item.put("billType", task == null ? fixedBillType : task.getBillType());
|
||||
if (task != null && BillTaskSuccessStatus.SUCCESS.getCode().equals(task.getSuccessStatus()))
|
||||
{
|
||||
ok.incrementAndGet();
|
||||
}
|
||||
else
|
||||
{
|
||||
fail.incrementAndGet();
|
||||
}
|
||||
String billId = overwriteOne(one);
|
||||
item.put("successStatus", "SUCCESS");
|
||||
item.put("billId", billId);
|
||||
ok.incrementAndGet();
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
fail.incrementAndGet();
|
||||
item.put("successStatus", "ERROR");
|
||||
item.put("errorMessage", e.getMessage());
|
||||
item.put("billType", fixedBillType);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
@@ -315,15 +302,8 @@ public class TabOrderSyncAsyncRunner
|
||||
TabOrderMonitorVo vo = row == null ? null : row.getVo();
|
||||
try
|
||||
{
|
||||
PrcBillingTask task = billingTaskService.submitAndProcess(
|
||||
toSubmit(vo), row == null ? null : row.getRaw());
|
||||
boolean success = task != null
|
||||
&& BillTaskSuccessStatus.SUCCESS.getCode().equals(task.getSuccessStatus());
|
||||
if (!success)
|
||||
{
|
||||
collectFailDetail(failDetails, vo, task, null);
|
||||
}
|
||||
return success;
|
||||
overwriteOne(row);
|
||||
return true;
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
@@ -331,15 +311,34 @@ public class TabOrderSyncAsyncRunner
|
||||
vo == null ? null : vo.getOrderId(),
|
||||
vo == null ? null : vo.getTransferOrderId(),
|
||||
e.getMessage());
|
||||
collectFailDetail(failDetails, vo, null, e.getMessage());
|
||||
collectFailDetail(failDetails, vo, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve Oracle row then overwrite local bill + ext (no billing). */
|
||||
private String overwriteOne(com.bms.price.oracle.TabOrderRow row)
|
||||
{
|
||||
Map<String, Object> raw = row == null ? null : row.getRaw();
|
||||
TabOrderMonitorVo vo = row == null ? null : row.getVo();
|
||||
if (raw == null || raw.isEmpty())
|
||||
{
|
||||
String transferNo = vo == null ? null : vo.getTransferOrderId();
|
||||
String orderNo = vo == null ? null : vo.getOrderId();
|
||||
String trackingNo = vo == null ? null : vo.getOrgOrderId();
|
||||
raw = oracleUpstreamOrderService.findMainOrder(transferNo, orderNo, trackingNo);
|
||||
}
|
||||
if (raw == null || raw.isEmpty())
|
||||
{
|
||||
throw new com.bms.common.exception.ServiceException("Oracle main order not found");
|
||||
}
|
||||
return prcOrderBillService.syncUpstreamOverwrite(raw);
|
||||
}
|
||||
|
||||
private static final int FAIL_DETAIL_MAX = 200;
|
||||
|
||||
private static void collectFailDetail(List<Map<String, Object>> failDetails, TabOrderMonitorVo row,
|
||||
PrcBillingTask task, String exceptionMessage)
|
||||
String exceptionMessage)
|
||||
{
|
||||
if (failDetails == null)
|
||||
{
|
||||
@@ -348,22 +347,7 @@ public class TabOrderSyncAsyncRunner
|
||||
Map<String, Object> item = new LinkedHashMap<String, Object>();
|
||||
item.put("orderId", row == null ? null : row.getOrderId());
|
||||
item.put("transferOrderId", row == null ? null : row.getTransferOrderId());
|
||||
String err = exceptionMessage;
|
||||
if (task != null)
|
||||
{
|
||||
item.put("successStatus", task.getSuccessStatus());
|
||||
item.put("billType", task.getBillType());
|
||||
item.put("taskId", task.getTaskId());
|
||||
if (StringUtils.isEmpty(err))
|
||||
{
|
||||
err = task.getErrorMessage();
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(err))
|
||||
{
|
||||
err = "sync failed";
|
||||
}
|
||||
item.put("errorMessage", err);
|
||||
item.put("errorMessage", StringUtils.isEmpty(exceptionMessage) ? "sync failed" : exceptionMessage);
|
||||
synchronized (failDetails)
|
||||
{
|
||||
if (failDetails.size() >= FAIL_DETAIL_MAX)
|
||||
@@ -490,32 +474,4 @@ public class TabOrderSyncAsyncRunner
|
||||
return n;
|
||||
}
|
||||
|
||||
public static BillingTaskSubmitRequest toSubmit(TabOrderMonitorVo row)
|
||||
{
|
||||
return toSubmit(row, null);
|
||||
}
|
||||
|
||||
public static BillingTaskSubmitRequest toSubmit(TabOrderMonitorVo row, String billType)
|
||||
{
|
||||
if (row == null)
|
||||
{
|
||||
throw new com.bms.common.exception.ServiceException("order row required");
|
||||
}
|
||||
BillingTaskSubmitRequest req = new BillingTaskSubmitRequest();
|
||||
req.setTransferNo(row.getTransferOrderId());
|
||||
req.setTrackingNo(row.getOrgOrderId());
|
||||
req.setOrderNo(row.getOrderId());
|
||||
req.setCustomerCode(row.getCustomerCode());
|
||||
req.setBillTime(row.getPickupDate());
|
||||
if (StringUtils.isNotEmpty(billType))
|
||||
{
|
||||
req.setBillType(billType.trim());
|
||||
}
|
||||
else if (BillOrderStatus.requiresFeeRefund(row.getOrderStatus()))
|
||||
{
|
||||
// Upstream 已退件(9) / 已取消(10) -> fee refund task
|
||||
req.setBillType(BillTaskType.REFUND.getCode());
|
||||
}
|
||||
return req;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,11 +216,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<foreach collection="customerCodes" item="ccode" open="(" separator="," close=")">
|
||||
#{ccode}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="orderStatuses != null and orderStatuses.size() > 0">
|
||||
AND p.order_status IN
|
||||
<foreach collection="orderStatuses" item="st" open="(" separator="," close=")">
|
||||
#{st}
|
||||
</foreach>
|
||||
</if>
|
||||
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
|
||||
</select>
|
||||
|
||||
<!-- 订单比对:本地转单号 + 订单状态(用于状态一致性比对) -->
|
||||
<!-- 订单比对:本地转单号 + 订单状态 -->
|
||||
<select id="selectTransferOrderStatuses" resultType="java.util.HashMap">
|
||||
SELECT p.transfer_no AS transferNo, p.order_status AS orderStatus
|
||||
FROM prc_order_bill p
|
||||
@@ -233,6 +239,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<foreach collection="customerCodes" item="ccode" open="(" separator="," close=")">
|
||||
#{ccode}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="orderStatuses != null and orderStatuses.size() > 0">
|
||||
AND p.order_status IN
|
||||
<foreach collection="orderStatuses" item="st" open="(" separator="," close=")">
|
||||
#{st}
|
||||
</foreach>
|
||||
</if>
|
||||
AND p.transfer_no IS NOT NULL AND p.transfer_no != ''
|
||||
</select>
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
已扫描 {{ progress.scanned || 0 }}
|
||||
/ 本地已有 {{ progress.matched || 0 }}
|
||||
/ 本地缺失 {{ progress.missing || 0 }}
|
||||
/ 状态不一致 {{ progress.statusMismatch || 0 }}
|
||||
</div>
|
||||
<div v-if="progress.message" class="msg-line">{{ progress.message }}</div>
|
||||
<div v-if="progress.error" class="err-line">{{ progress.error }}</div>
|
||||
@@ -41,34 +40,7 @@
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
title="比对转单号 + 订单状态:1) 上游有转单号、本地没有;2) 两端都有但 order_status 不一致。异步分页扫描,结果已写入操作记录。"
|
||||
/>
|
||||
|
||||
<div class="json-panel__head">
|
||||
<span>状态不一致(样本 {{ statusMismatchCount }})</span>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
:disabled="!canFillMismatch"
|
||||
@click="fillMismatchToSearch"
|
||||
>回填到单号搜索</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="statusMismatchRows.length"
|
||||
:data="statusMismatchRows"
|
||||
border
|
||||
size="small"
|
||||
max-height="320"
|
||||
class="mb12"
|
||||
>
|
||||
<el-table-column type="index" width="55" label="#" />
|
||||
<el-table-column prop="transferNo" label="转单号" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="upstreamStatusLabel" label="上游状态" width="110" />
|
||||
<el-table-column prop="localStatusLabel" label="本地状态" width="110" />
|
||||
</el-table>
|
||||
<el-empty
|
||||
v-else-if="!running"
|
||||
description="暂无状态不一致"
|
||||
title="仅比对转单号是否已落库:上游有、本地在当前「订单状态」筛选范围内没有。不再比对状态一致性。"
|
||||
/>
|
||||
|
||||
<div class="json-panel__head">
|
||||
@@ -159,65 +131,6 @@ const progressStatus = computed(() => {
|
||||
return undefined
|
||||
})
|
||||
|
||||
const orderStatusMap = {
|
||||
'0': '待提货',
|
||||
'1': '已提货',
|
||||
'2': '已收货',
|
||||
'3': '运输中',
|
||||
'4': '派送中',
|
||||
'5': '已签收',
|
||||
'6': '已完成',
|
||||
'7': '已取消',
|
||||
'8': '异常',
|
||||
'9': '退件中',
|
||||
'10': '已退件'
|
||||
}
|
||||
|
||||
function labelStatus(v) {
|
||||
const k = v == null ? '' : String(v).trim()
|
||||
if (!k) return '-'
|
||||
return orderStatusMap[k] || k
|
||||
}
|
||||
|
||||
function normalizeMismatchList(raw) {
|
||||
if (!Array.isArray(raw)) return []
|
||||
return raw.map(row => {
|
||||
if (row == null) return null
|
||||
if (typeof row === 'string') {
|
||||
return { transferNo: row, upstreamStatus: null, localStatus: null }
|
||||
}
|
||||
return {
|
||||
transferNo: row.transferNo || row.transfer_no || '',
|
||||
upstreamStatus: row.upstreamStatus ?? row.upstream_status ?? null,
|
||||
localStatus: row.localStatus ?? row.local_status ?? null
|
||||
}
|
||||
}).filter(Boolean)
|
||||
}
|
||||
|
||||
const statusMismatchRows = computed(() => {
|
||||
const samples = normalizeMismatchList(progress.value?.statusMismatchSamples)
|
||||
if (samples.length) {
|
||||
return samples.map(row => ({
|
||||
transferNo: row.transferNo,
|
||||
upstreamStatusLabel: labelStatus(row.upstreamStatus),
|
||||
localStatusLabel: labelStatus(row.localStatus)
|
||||
}))
|
||||
}
|
||||
// fallback: flat transfer_no list when map samples missing
|
||||
const flat = progress.value?.statusMismatchTransferNos || []
|
||||
return (Array.isArray(flat) ? flat : []).map(tn => ({
|
||||
transferNo: tn,
|
||||
upstreamStatusLabel: '-',
|
||||
localStatusLabel: '-'
|
||||
}))
|
||||
})
|
||||
|
||||
const statusMismatchCount = computed(() => {
|
||||
const n = Number(progress.value?.statusMismatch)
|
||||
if (!Number.isNaN(n) && n > 0) return n
|
||||
return statusMismatchRows.value.length
|
||||
})
|
||||
|
||||
const missingRows = computed(() => {
|
||||
const list = progress.value?.missingTransferNos || []
|
||||
return (Array.isArray(list) ? list : []).map(tn => ({ transferNo: tn }))
|
||||
@@ -233,9 +146,6 @@ const canFillSearch = computed(() => {
|
||||
return !running.value && missingRows.value.length > 0
|
||||
})
|
||||
|
||||
const canFillMismatch = computed(() => {
|
||||
return !running.value && statusMismatchRows.value.length > 0
|
||||
})
|
||||
|
||||
function fillToSearch() {
|
||||
const list = missingRows.value.map(r => String(r.transferNo || '').trim()).filter(Boolean)
|
||||
@@ -248,17 +158,6 @@ function fillToSearch() {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
function fillMismatchToSearch() {
|
||||
const list = statusMismatchRows.value.map(r => String(r.transferNo || '').trim()).filter(Boolean)
|
||||
if (!list.length) {
|
||||
ElMessage.warning('暂无可回填的状态不一致转单号')
|
||||
return
|
||||
}
|
||||
const truncated = !!(progress.value?.statusMismatchTruncated)
|
||||
|| (Number(progress.value?.statusMismatch || 0) > list.length)
|
||||
emit('fill-search', { transferNos: list, truncated })
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
function clearTimer() {
|
||||
if (timer) {
|
||||
@@ -291,7 +190,7 @@ function open(q) {
|
||||
ElMessage.error('启动比对任务失败')
|
||||
return
|
||||
}
|
||||
progress.value = { status: 'PENDING', percent: 0, message: 'queued', scanned: 0, matched: 0, missing: 0, statusMismatch: 0 }
|
||||
progress.value = { status: 'PENDING', percent: 0, message: 'queued', scanned: 0, matched: 0, missing: 0 }
|
||||
poll()
|
||||
timer = setInterval(poll, 1500)
|
||||
}).catch(() => {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
type="info"
|
||||
:closable="false"
|
||||
show-icon
|
||||
title="按当前筛选分页查询上游订单并逐单同步计费,避免一次性加载全量。"
|
||||
title="按当前筛选分页查询上游订单并逐单覆盖本地字段(不计费;计费请到订单列表重新计费)。"
|
||||
/>
|
||||
</el-form>
|
||||
|
||||
@@ -44,13 +44,13 @@
|
||||
/ 失败 {{ progress.fail || 0 }}
|
||||
</div>
|
||||
<div v-if="progress.error" class="filter-retry-progress__error">{{ progress.error }}</div>
|
||||
<p v-if="loading" class="filter-retry-progress__hint">请勿关闭页面,大量订单同步计费可能需要一些时间</p>
|
||||
<p v-if="loading" class="filter-retry-progress__hint">请勿关闭页面,大量订单同步落库可能需要一些时间</p>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<template v-if="!loading && !finished">
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submit">开始同步计费</el-button>
|
||||
<el-button type="primary" @click="submit">开始同步落库</el-button>
|
||||
</template>
|
||||
<template v-else-if="finished">
|
||||
<el-button type="primary" @click="visible = false">关闭</el-button>
|
||||
@@ -101,9 +101,9 @@ const filterText = computed(() => {
|
||||
})
|
||||
|
||||
const dialogTitle = computed(() => {
|
||||
if (loading.value) return '异步同步计费进行中'
|
||||
if (finished.value) return '异步同步计费完成'
|
||||
return '条件批量同步计费'
|
||||
if (loading.value) return '异步同步落库进行中'
|
||||
if (finished.value) return '异步同步落库完成'
|
||||
return '条件批量同步落库'
|
||||
})
|
||||
|
||||
const progressPercent = computed(() => Math.min(100, Math.max(0, Number(progress.value?.percent) || 0)))
|
||||
@@ -124,7 +124,7 @@ function mapProgressMessage(message, data) {
|
||||
if (m === 'no tasks') return '无匹配订单'
|
||||
if (m === 'failed') return '执行失败'
|
||||
if (m.startsWith('processing ')) {
|
||||
return '正在同步计费 ' + m.slice('processing '.length)
|
||||
return '正在同步落库 ' + m.slice('processing '.length)
|
||||
}
|
||||
if (m.startsWith('done ')) {
|
||||
return '完成:成功 ' + (data?.ok || 0) + ' / 失败 ' + (data?.fail || 0)
|
||||
@@ -236,7 +236,7 @@ function submit(skipConfirm) {
|
||||
status: 'FAIL',
|
||||
percent: 100,
|
||||
message: 'failed',
|
||||
error: progress.value?.error || '批量同步计费失败'
|
||||
error: progress.value?.error || '批量同步落库失败'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,7 +250,7 @@ function submit(skipConfirm) {
|
||||
return
|
||||
}
|
||||
proxy.$modal.confirm(
|
||||
'确认按当前筛选分页查询并异步同步计费?',
|
||||
'确认按当前筛选分页查询并异步同步落库?',
|
||||
'二次确认'
|
||||
).then(() => start()).catch(() => {})
|
||||
}
|
||||
@@ -278,7 +278,7 @@ function poll(asyncTaskId) {
|
||||
return
|
||||
}
|
||||
if (st === 'FAIL') {
|
||||
proxy.$modal.msgError(data.error || data.message || '批量同步计费失败')
|
||||
proxy.$modal.msgError(data.error || data.message || '批量同步落库失败')
|
||||
reject(new Error(data.error || 'fail'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
icon="Refresh"
|
||||
v-hasPermi="['monitor:orderSource:sync']"
|
||||
@click="openFilterSync()"
|
||||
>同步计费</el-button>
|
||||
>同步落库</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
@@ -128,7 +128,7 @@
|
||||
:loading="syncingKey === rowKey(row)"
|
||||
v-hasPermi="['monitor:orderSource:sync']"
|
||||
@click="handleSyncOne(row)"
|
||||
>同步计费</el-button>
|
||||
>同步落库</el-button>
|
||||
</template> -->
|
||||
</basic-table>
|
||||
|
||||
@@ -273,10 +273,10 @@ const syncProgressDegree = computed(() => Math.round(((syncFloat.value?.percent
|
||||
const syncProgressText = computed(() => (syncFloat.value?.percent || 0) + '%')
|
||||
const syncFloatTitle = computed(() => {
|
||||
const st = (syncFloat.value?.status || '').toUpperCase()
|
||||
if (syncFloat.value?.loading) return '异步同步计费中'
|
||||
if (st === 'SUCCESS') return '同步计费完成'
|
||||
if (st === 'FAIL') return '同步计费失败'
|
||||
return '异步同步计费'
|
||||
if (syncFloat.value?.loading) return '异步同步落库中'
|
||||
if (st === 'SUCCESS') return '同步落库完成'
|
||||
if (st === 'FAIL') return '同步落库失败'
|
||||
return '异步同步落库'
|
||||
})
|
||||
const syncFloatSummary = computed(() => {
|
||||
const p = syncFloat.value || {}
|
||||
@@ -421,7 +421,7 @@ function openOrderCompare() {
|
||||
return
|
||||
}
|
||||
proxy.$modal.confirm(
|
||||
'将按当前客户与提货时间,异步分页比对上游转单号与订单状态(缺失转单号 + 状态不一致),确认继续?',
|
||||
'将按当前客户、提货时间与订单状态筛选,异步分页比对上游转单号是否已落库,确认继续?',
|
||||
'二次确认'
|
||||
).then(() => {
|
||||
// 比对只按客户+时间;不带单号框内容(回填后可能有数千转单号,带上会把比对拖死)
|
||||
@@ -466,7 +466,7 @@ function openFilterSync() {
|
||||
const hasTime = !!q.beginTime && !!q.endTime
|
||||
// 与查询同口径:有单号即可同步;无单号时必须客户+提货时间
|
||||
if (!hasIdentifier && !(hasCustomer && hasTime)) {
|
||||
ElMessage.warning('请输入单号,或选择客户和提货时间后再同步计费')
|
||||
ElMessage.warning('请输入单号,或选择客户和提货时间后再同步落库')
|
||||
return
|
||||
}
|
||||
if (identifierCount > MAX_ORDER_IDENTIFIERS) {
|
||||
@@ -474,8 +474,8 @@ function openFilterSync() {
|
||||
return
|
||||
}
|
||||
const tip = hasIdentifier && !(hasCustomer && hasTime)
|
||||
? `将按 ${identifierCount} 个单号查询匹配订单并异步同步计费,确认继续?`
|
||||
: '确认按当前筛选分页查询并异步同步计费?'
|
||||
? `将按 ${identifierCount} 个单号查询匹配订单并异步覆盖上游字段(不计费),确认继续?`
|
||||
: '确认按当前筛选分页查询并异步覆盖上游字段(不计费)?'
|
||||
proxy.$modal.confirm(tip, '二次确认').then(() => {
|
||||
syncDialogRef.value?.open(q, true)
|
||||
}).catch(() => {})
|
||||
@@ -509,7 +509,7 @@ function toSyncRow(row) {
|
||||
|
||||
|
||||
function handleSyncOne(row) {
|
||||
proxy.$modal.confirm('确认同步计费该订单?', '二次确认').then(() => {
|
||||
proxy.$modal.confirm('确认同步落库该订单(仅覆盖上游字段,不计费)?', '二次确认').then(() => {
|
||||
syncingKey.value = rowKey(row)
|
||||
return syncOrderSourceSelected([toSyncRow(row)])
|
||||
}).then(res => {
|
||||
@@ -544,7 +544,7 @@ function handleCheckProducts() {
|
||||
|
||||
function handleBatchSync(selection) {
|
||||
if (!selection || !selection.length) return
|
||||
proxy.$modal.confirm('确认同步选中的 ' + selection.length + ' 条订单?', '二次确认').then(() => {
|
||||
proxy.$modal.confirm('确认同步选中的 ' + selection.length + ' 条订单(仅覆盖上游字段,不计费)?', '二次确认').then(() => {
|
||||
batchLoading.value = true
|
||||
return syncOrderSourceSelected(selection.map(toSyncRow))
|
||||
}).then(res => {
|
||||
|
||||
Reference in New Issue
Block a user