diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/TabOrderMonitorController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/TabOrderMonitorController.java index 64ae8328..e4e7f63c 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/TabOrderMonitorController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/TabOrderMonitorController.java @@ -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 data = new HashMap(); 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") diff --git a/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderCompareTask.java b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderCompareTask.java index e86ed137..23305cc4 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderCompareTask.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderCompareTask.java @@ -7,8 +7,8 @@ import java.util.Map; /** * 订单比对异步任务进度(Redis)。 - * missing = 上游有转单号、本地无; - * statusMismatch = 本地有转单号但 order_status 与上游不一致。 + * missing = 上游有转单号、本地在指定状态集合中无对应单; + * statusMismatch 已废弃(恒为 0,不再比对状态)。 */ public class TabOrderCompareTask implements Serializable { diff --git a/bms-back/bms-system/src/main/java/com/bms/price/enums/BillOrderStatus.java b/bms-back/bms-system/src/main/java/com/bms/price/enums/BillOrderStatus.java index 8395fc5f..c51946db 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/enums/BillOrderStatus.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/enums/BillOrderStatus.java @@ -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 { diff --git a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java index a2dc5094..a915a576 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcOrderBillMapper.java @@ -39,14 +39,16 @@ public interface PrcOrderBillMapper List selectExistingOrderIdentifiers(@Param("identifiers") List identifiers, @Param("customerCodes") List customerCodes); - /** 订单比对:仅按转单号批量查本地已存在。 */ + /** 订单比对:仅按转单号批量查本地已存在(可选 order_status 过滤)。 */ List selectExistingTransferNos(@Param("transferNos") List transferNos, - @Param("customerCodes") List customerCodes); + @Param("customerCodes") List customerCodes, + @Param("orderStatuses") List orderStatuses); /** 订单比对:按转单号批量查本地 transfer_no + order_status。 */ List> selectTransferOrderStatuses( @Param("transferNos") List transferNos, - @Param("customerCodes") List customerCodes); + @Param("customerCodes") List customerCodes, + @Param("orderStatuses") List orderStatuses); /** 订单号下拉搜索(带数据权限) */ public List selectOrderNoOptions(@Param("query") PrcOrderBill query, @Param("limit") int limit); diff --git a/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java index aa441b01..dc287772 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/oracle/OracleOrderBillMapper.java @@ -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); diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/IPrcOrderBillService.java b/bms-back/bms-system/src/main/java/com/bms/price/service/IPrcOrderBillService.java index 34dc6f15..20091b13 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/IPrcOrderBillService.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/IPrcOrderBillService.java @@ -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 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. diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcBillingTaskServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcBillingTaskServiceImpl.java index 71fd3884..69f4249a 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcBillingTaskServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcBillingTaskServiceImpl.java @@ -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) diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java index fc41577c..f4899dda 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcOrderBillServiceImpl.java @@ -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 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 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 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()); } diff --git a/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderCompareAsyncRunner.java b/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderCompareAsyncRunner.java index 45db04e9..293e2460 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderCompareAsyncRunner.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderCompareAsyncRunner.java @@ -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 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 compareStatuses = resolveCompareStatuses(query); + if (query != null) + { + query.setOrderStatuses(new ArrayList(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 missingSample = new ArrayList(); - List> statusMismatchSample = new ArrayList>(); int pageNum = 1; while (true) { @@ -96,8 +108,8 @@ public class TabOrderCompareAsyncRunner transferNos.add(String.valueOf(tn).trim()); } } - Map localStatusByTn = - findLocalStatuses(transferNos, query == null ? null : query.getCustomerCodes()); + Set localTns = findLocalTransferNos( + transferNos, query == null ? null : query.getCustomerCodes(), compareStatuses); for (Map 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 one = new LinkedHashMap(); - 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 mismatchTns = new ArrayList(); - for (Map 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 findLocalStatuses(List transferNos, List 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 resolveCompareStatuses(TabOrderMonitorQuery query) { - Map found = new HashMap(); + List cleaned = new ArrayList(); + if (query != null && query.getOrderStatuses() != null) + { + for (Integer s : query.getOrderStatuses()) + { + if (s != null) + { + cleaned.add(s); + } + } + } + return cleaned.isEmpty() ? new ArrayList(COMPARE_LOCAL_ORDER_STATUSES) : cleaned; + } + + /** transferNo(upper) present locally with the given order_status filter. */ + private Set findLocalTransferNos(List transferNos, List customerCodes, + List orderStatuses) + { + Set found = new HashSet(); if (transferNos == null || transferNos.isEmpty()) { return found; } - List> rows = - prcOrderBillMapper.selectTransferOrderStatuses(transferNos, cleanCodes(customerCodes)); + List rows = prcOrderBillMapper.selectExistingTransferNos( + transferNos, cleanCodes(customerCodes), orderStatuses); if (rows == null) { return found; } - for (Map 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 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 cleanCodes(List 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 missingSample, List> statusMismatchSample) + int scanned, int matched, int missing, String error, List 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(missingSample)); } - if (statusMismatchSample != null) - { - task.setStatusMismatchSamples(new ArrayList>(statusMismatchSample)); - List tnList = new ArrayList(); - for (Map 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>()); + task.setStatusMismatchTransferNos(new ArrayList()); redisCache.setCacheObject(CACHE_KEY_PREFIX + taskId, task, TTL_MINUTES, TimeUnit.MINUTES); } diff --git a/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java b/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java index 44766201..fbca00d9 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/task/TabOrderSyncAsyncRunner.java @@ -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 syncRowsParallel(List 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 syncRowsParallelRows(List 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 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> failDetails, TabOrderMonitorVo row, - PrcBillingTask task, String exceptionMessage) + String exceptionMessage) { if (failDetails == null) { @@ -348,22 +347,7 @@ public class TabOrderSyncAsyncRunner Map item = new LinkedHashMap(); 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; - } } diff --git a/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml b/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml index 854a5594..32b9ada4 100644 --- a/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/price/PrcOrderBillMapper.xml @@ -216,11 +216,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{ccode} + + + AND p.order_status IN + + #{st} + AND p.transfer_no IS NOT NULL AND p.transfer_no != '' - + diff --git a/bms-front/src/views/monitor/orderSource/components/OrderSourceCompareDrawer.vue b/bms-front/src/views/monitor/orderSource/components/OrderSourceCompareDrawer.vue index 6be90e92..f629516a 100644 --- a/bms-front/src/views/monitor/orderSource/components/OrderSourceCompareDrawer.vue +++ b/bms-front/src/views/monitor/orderSource/components/OrderSourceCompareDrawer.vue @@ -31,7 +31,6 @@ 已扫描 {{ progress.scanned || 0 }} / 本地已有 {{ progress.matched || 0 }} / 本地缺失 {{ progress.missing || 0 }} - / 状态不一致 {{ progress.statusMismatch || 0 }}
{{ progress.message }}
{{ progress.error }}
@@ -41,34 +40,7 @@ type="info" :closable="false" show-icon - title="比对转单号 + 订单状态:1) 上游有转单号、本地没有;2) 两端都有但 order_status 不一致。异步分页扫描,结果已写入操作记录。" - /> - -
- 状态不一致(样本 {{ statusMismatchCount }}) - 回填到单号搜索 -
- - - - - - -
@@ -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(() => { diff --git a/bms-front/src/views/monitor/orderSource/components/OrderSourceSyncDialog.vue b/bms-front/src/views/monitor/orderSource/components/OrderSourceSyncDialog.vue index d393b902..d9d32455 100644 --- a/bms-front/src/views/monitor/orderSource/components/OrderSourceSyncDialog.vue +++ b/bms-front/src/views/monitor/orderSource/components/OrderSourceSyncDialog.vue @@ -24,7 +24,7 @@ type="info" :closable="false" show-icon - title="按当前筛选分页查询上游订单并逐单同步计费,避免一次性加载全量。" + title="按当前筛选分页查询上游订单并逐单覆盖本地字段(不计费;计费请到订单列表重新计费)。" /> @@ -44,13 +44,13 @@ / 失败 {{ progress.fail || 0 }}
{{ progress.error }}
-

请勿关闭页面,大量订单同步计费可能需要一些时间

+

请勿关闭页面,大量订单同步落库可能需要一些时间