修改订单列表重新计费
This commit is contained in:
@@ -151,7 +151,9 @@ public interface IPrcOrderBillService
|
||||
|
||||
/**
|
||||
* Full rebill from local prc_order_bill only (no Oracle upstream).
|
||||
* Rebuilds TmsPriceBillRequest from the bill row then calls {@link #bill}.
|
||||
* Refund-like local status (order_status 9/10 or refund_status=REFUNDED):
|
||||
* skip when prc_income_bill_fee already has fee_type=REFUND; otherwise {@link #refund}.
|
||||
* Else rebuilds request from the bill row then {@link #bill}.
|
||||
*/
|
||||
TmsPriceQuoteResult rebillLocalByBillId(String billId);
|
||||
|
||||
|
||||
+88
-6
@@ -255,11 +255,7 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
}
|
||||
failReq.setTransferNo(bill.getTransferNo());
|
||||
assertOrderBillEditable(bill);
|
||||
if (BillRefundStatus.REFUNDED.getCode().equalsIgnoreCase(bill.getRefundStatus()))
|
||||
{
|
||||
throw new ServiceException("\u8ba2\u5355\u5df2\u9000\u8d39\uff0c\u4e0d\u53ef\u91cd\u590d\u9000\u8d39");
|
||||
}
|
||||
|
||||
// Duplicate guard is fee_type=REFUND on prc_income_bill_fee (refund_status alone may be stale).
|
||||
List<PrcIncomeBillFee> fees = incomeBillFeeMapper.selectByBillId(bill.getBillId());
|
||||
if (fees == null)
|
||||
{
|
||||
@@ -752,8 +748,11 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
private static final long LOCAL_REBILL_DB_RETRY_BASE_MS = 80L;
|
||||
|
||||
/**
|
||||
* Local rebill without outer txn: each {@link #bill} starts its own transaction so
|
||||
* Local rebill without outer txn: each {@link #bill}/{@link #refund} starts its own transaction so
|
||||
* MySQL deadlock can be retried cleanly (same idea as billing-task billWithDbRetry).
|
||||
* <p>If local order is refund-like (order_status 9/10 or refund_status=REFUNDED):
|
||||
* skip when prc_income_bill_fee already has fee_type=REFUND; otherwise call {@link #refund}.
|
||||
* Otherwise normal {@link #bill}.
|
||||
*/
|
||||
@Override
|
||||
public TmsPriceQuoteResult rebillLocalByBillId(String billId)
|
||||
@@ -775,10 +774,57 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.bill.bizDateRequired"));
|
||||
}
|
||||
if (isLocalRefundCandidate(bill))
|
||||
{
|
||||
if (hasRefundFeeLine(bill.getBillId()))
|
||||
{
|
||||
log.info("local rebill skip refund, REFUND fee exists billId={} orderNo={} orderStatus={} refundStatus={}",
|
||||
billId, bill.getOrderNo(), bill.getOrderStatus(), bill.getRefundStatus());
|
||||
return toResult(bill.getBillId());
|
||||
}
|
||||
log.info("local rebill -> refund path billId={} orderNo={} orderStatus={} refundStatus={}",
|
||||
billId, bill.getOrderNo(), bill.getOrderStatus(), bill.getRefundStatus());
|
||||
return refundLocalWithDbRetry(bill.getOrderNo().trim());
|
||||
}
|
||||
TmsPriceBillRequest req = buildBillRequestFromBill(bill);
|
||||
return billLocalWithDbRetry(billId.trim(), req);
|
||||
}
|
||||
|
||||
/** order_status 9/10 or refund_status=REFUNDED. */
|
||||
private static boolean isLocalRefundCandidate(PrcOrderBill bill)
|
||||
{
|
||||
if (bill == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (BillOrderStatus.requiresFeeRefund(bill.getOrderStatus()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return BillRefundStatus.REFUNDED.getCode().equalsIgnoreCase(bill.getRefundStatus());
|
||||
}
|
||||
|
||||
private boolean hasRefundFeeLine(String billId)
|
||||
{
|
||||
if (StringUtils.isEmpty(billId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<PrcIncomeBillFee> fees = incomeBillFeeMapper.selectByBillId(billId);
|
||||
if (fees == null || fees.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (PrcIncomeBillFee row : fees)
|
||||
{
|
||||
if (row != null && FEE_TYPE_REFUND.equalsIgnoreCase(row.getFeeType()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private TmsPriceQuoteResult billLocalWithDbRetry(String billId, TmsPriceBillRequest billReq)
|
||||
{
|
||||
RuntimeException last = null;
|
||||
@@ -815,6 +861,42 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
throw last != null ? last : new ServiceException("local rebill retry exhausted");
|
||||
}
|
||||
|
||||
private TmsPriceQuoteResult refundLocalWithDbRetry(String orderNo)
|
||||
{
|
||||
RuntimeException last = null;
|
||||
for (int attempt = 1; attempt <= LOCAL_REBILL_DB_RETRY_MAX; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return self.refund(orderNo);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
last = e;
|
||||
if (attempt < LOCAL_REBILL_DB_RETRY_MAX && isRetryableDbConflict(e))
|
||||
{
|
||||
long sleepMs = LOCAL_REBILL_DB_RETRY_BASE_MS * attempt
|
||||
+ (long) (Math.random() * LOCAL_REBILL_DB_RETRY_BASE_MS);
|
||||
log.warn("local rebill refund db conflict, retry orderNo={} attempt={}/{} sleepMs={} msg={}",
|
||||
orderNo, Integer.valueOf(attempt), Integer.valueOf(LOCAL_REBILL_DB_RETRY_MAX),
|
||||
Long.valueOf(sleepMs), StringUtils.substring(e.getMessage(), 0, 200));
|
||||
try
|
||||
{
|
||||
Thread.sleep(sleepMs);
|
||||
}
|
||||
catch (InterruptedException ie)
|
||||
{
|
||||
Thread.currentThread().interrupt();
|
||||
throw e;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
throw last != null ? last : new ServiceException("local rebill refund retry exhausted");
|
||||
}
|
||||
|
||||
/** Deadlock / lock wait — safe to retry whole bill txn (parallel local rebill). */
|
||||
private static boolean isRetryableDbConflict(Throwable e)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user