[WLOS-030] 设计并落地统一的白名单订单完成补偿方法

This commit is contained in:
Guoqs
2026-01-28 15:27:25 +08:00
parent 600a879456
commit c7e06907d2
4 changed files with 163 additions and 1 deletions

View File

@@ -1617,6 +1617,64 @@ public class OrderService {
personalChargingRecordService.insertOrUpdateSelective(record);
}
/**
* 白名单订单完成补偿:仅在白名单支付(payMode=3)且订单状态为异常/待结算时,修正为订单完成。
* <p>
* 该方法为幂等:重复调用不会产生额外副作用(已完成或不符合条件将直接返回)。
*
* @param orderCode 订单号
* @return 是否发生了落库更新
*/
@Transactional(rollbackFor = Exception.class)
public boolean completeWhitelistOrderIfNeeded(String orderCode) {
if (StringUtils.isBlank(orderCode)) {
log.warn("completeWhitelistOrderIfNeeded ignored, orderCode is blank");
return false;
}
OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
if (orderBasicInfo == null) {
log.warn("completeWhitelistOrderIfNeeded ignored, order not found, orderCode:{}", orderCode);
return false;
}
if (!StringUtils.equals(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue(), orderBasicInfo.getPayMode())) {
log.info("completeWhitelistOrderIfNeeded skipped, not whitelist payMode, orderCode:{}, payMode:{}",
orderCode, orderBasicInfo.getPayMode());
return false;
}
String beforeStatus = orderBasicInfo.getOrderStatus();
if (StringUtils.equals(OrderStatusEnum.ORDER_COMPLETE.getValue(), beforeStatus)) {
log.info("completeWhitelistOrderIfNeeded skipped, already complete, orderCode:{}", orderCode);
return false;
}
boolean eligibleStatus = StringUtils.equals(OrderStatusEnum.ABNORMAL.getValue(), beforeStatus)
|| StringUtils.equals(OrderStatusEnum.STAY_SETTLEMENT.getValue(), beforeStatus);
if (!eligibleStatus) {
log.info("completeWhitelistOrderIfNeeded skipped, not eligible status, orderCode:{}, status:{}",
orderCode, beforeStatus);
return false;
}
if (orderBasicInfo.getSettlementTime() == null) {
orderBasicInfo.setSettlementTime(DateUtils.getNowDate());
}
WhitelistOrderCompletionDefaults.apply(orderBasicInfo, orderBasicInfo.getSettlementTime());
int updated = orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo);
try {
orderBasicInfoService.cleanCacheByOrderCode(orderCode, orderBasicInfo.getTransactionCode());
} catch (Exception e) {
log.warn("completeWhitelistOrderIfNeeded clean cache failed, orderCode:{}", orderCode, e);
}
log.info("completeWhitelistOrderIfNeeded updated orderCode:{}, {} -> {}",
orderCode, beforeStatus, orderBasicInfo.getOrderStatus());
return updated > 0;
}
public static void main(String[] args) {
}

View File

@@ -0,0 +1,51 @@
package com.jsowell.service;
import com.jsowell.common.enums.ykc.OrderPayStatusEnum;
import com.jsowell.common.enums.ykc.OrderStatusEnum;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.OrderBasicInfo;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
final class WhitelistOrderCompletionDefaults {
private WhitelistOrderCompletionDefaults() {
}
static void apply(OrderBasicInfo orderBasicInfo, Date now) {
Objects.requireNonNull(orderBasicInfo, "orderBasicInfo");
BigDecimal payAmount = orderBasicInfo.getPayAmount() != null ? orderBasicInfo.getPayAmount() : BigDecimal.ZERO;
BigDecimal orderAmount = orderBasicInfo.getOrderAmount() != null ? orderBasicInfo.getOrderAmount() : payAmount;
if (orderAmount.compareTo(payAmount) > 0) {
orderAmount = payAmount;
}
orderBasicInfo.setOrderAmount(orderAmount);
orderBasicInfo.setVirtualAmount(orderAmount);
orderBasicInfo.setSettleAmount(BigDecimal.ZERO);
orderBasicInfo.setActualReceivedAmount(BigDecimal.ZERO);
if (orderBasicInfo.getRefundAmount() == null) {
BigDecimal refundAmount = payAmount.subtract(orderAmount);
if (refundAmount.compareTo(BigDecimal.ZERO) < 0) {
refundAmount = BigDecimal.ZERO;
}
orderBasicInfo.setRefundAmount(refundAmount);
}
if (StringUtils.isBlank(orderBasicInfo.getPayStatus())) {
orderBasicInfo.setPayStatus(OrderPayStatusEnum.pay_nothing.getValue());
}
if (orderBasicInfo.getSettlementTime() == null && now != null) {
orderBasicInfo.setSettlementTime(now);
}
orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
}
}

View File

@@ -0,0 +1,53 @@
package com.jsowell.service;
import com.jsowell.common.enums.ykc.OrderPayStatusEnum;
import com.jsowell.common.enums.ykc.OrderStatusEnum;
import com.jsowell.pile.domain.OrderBasicInfo;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.util.Date;
import static org.junit.jupiter.api.Assertions.assertEquals;
class WhitelistOrderCompletionDefaultsTest {
@Test
void apply_shouldFillDefaults_whenAmountsAndStatusMissing() {
OrderBasicInfo orderBasicInfo = new OrderBasicInfo();
Date now = new Date();
WhitelistOrderCompletionDefaults.apply(orderBasicInfo, now);
assertEquals(OrderStatusEnum.ORDER_COMPLETE.getValue(), orderBasicInfo.getOrderStatus());
assertEquals(BigDecimal.ZERO, orderBasicInfo.getOrderAmount());
assertEquals(BigDecimal.ZERO, orderBasicInfo.getVirtualAmount());
assertEquals(BigDecimal.ZERO, orderBasicInfo.getSettleAmount());
assertEquals(BigDecimal.ZERO, orderBasicInfo.getActualReceivedAmount());
assertEquals(BigDecimal.ZERO, orderBasicInfo.getRefundAmount());
assertEquals(OrderPayStatusEnum.pay_nothing.getValue(), orderBasicInfo.getPayStatus());
assertEquals(now, orderBasicInfo.getSettlementTime());
}
@Test
void apply_shouldNotOverrideExistingSettlementTimeOrPayStatus() {
Date settlementTime = new Date(123456789L);
OrderBasicInfo orderBasicInfo = new OrderBasicInfo();
orderBasicInfo.setSettlementTime(settlementTime);
orderBasicInfo.setPayStatus(OrderPayStatusEnum.paid.getValue());
orderBasicInfo.setPayAmount(new BigDecimal("10"));
orderBasicInfo.setOrderAmount(new BigDecimal("5"));
WhitelistOrderCompletionDefaults.apply(orderBasicInfo, new Date());
assertEquals(settlementTime, orderBasicInfo.getSettlementTime());
assertEquals(OrderPayStatusEnum.paid.getValue(), orderBasicInfo.getPayStatus());
assertEquals(new BigDecimal("5"), orderBasicInfo.getOrderAmount());
assertEquals(new BigDecimal("5"), orderBasicInfo.getVirtualAmount());
assertEquals(BigDecimal.ZERO, orderBasicInfo.getSettleAmount());
assertEquals(BigDecimal.ZERO, orderBasicInfo.getActualReceivedAmount());
assertEquals(new BigDecimal("5"), orderBasicInfo.getRefundAmount());
assertEquals(OrderStatusEnum.ORDER_COMPLETE.getValue(), orderBasicInfo.getOrderStatus());
}
}