|
|
@@ -22,6 +22,8 @@ import org.junit.jupiter.api.AfterEach;
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
import org.mockito.MockedStatic;
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
+import org.springframework.data.redis.core.script.RedisScript;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.List;
|
|
|
@@ -31,6 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
|
import static org.mockito.ArgumentMatchers.anyString;
|
|
|
+import static org.mockito.ArgumentMatchers.anyList;
|
|
|
import static org.mockito.Mockito.doAnswer;
|
|
|
import static org.mockito.Mockito.mock;
|
|
|
import static org.mockito.Mockito.mockStatic;
|
|
|
@@ -48,11 +51,16 @@ class MultiStoreCheckoutBatchServiceTest {
|
|
|
private final InfoAddressMapper addresses = mock(InfoAddressMapper.class);
|
|
|
private final PosStoreMapper stores = mock(PosStoreMapper.class);
|
|
|
private final OrderPromotionHelper promotions = mock(OrderPromotionHelper.class);
|
|
|
+ private final StringRedisTemplate orderNumbers = mock(StringRedisTemplate.class);
|
|
|
+ private final OrderNumberReservationService numberReservations = mock(OrderNumberReservationService.class);
|
|
|
|
|
|
@BeforeEach
|
|
|
void setUp() {
|
|
|
messages = mockStatic(MessageUtils.class);
|
|
|
messages.when(() -> MessageUtils.message(anyString())).thenAnswer(call -> call.getArgument(0));
|
|
|
+ when(orderNumbers.execute(org.mockito.ArgumentMatchers.<RedisScript<Long>>any(), anyList(), anyString()))
|
|
|
+ .thenReturn(1789716730512L);
|
|
|
+ when(numberReservations.reserveIfUnused(anyString(), anyString())).thenReturn(true);
|
|
|
}
|
|
|
|
|
|
@AfterEach
|
|
|
@@ -62,7 +70,7 @@ class MultiStoreCheckoutBatchServiceTest {
|
|
|
|
|
|
private MultiStoreCheckoutBatchService subject() {
|
|
|
return new MultiStoreCheckoutBatchService(quotes, config, checkout, parents, orders,
|
|
|
- addresses, stores, promotions);
|
|
|
+ addresses, stores, promotions, orderNumbers, numberReservations);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
@@ -76,8 +84,15 @@ class MultiStoreCheckoutBatchServiceTest {
|
|
|
verify(parents, never()).insert(any(OrderParent.class));
|
|
|
}
|
|
|
|
|
|
- @Test
|
|
|
- void createsPendingBatchWithServerPricesNoDefaultCodAndFrozenAddress() {
|
|
|
+ @org.junit.jupiter.params.ParameterizedTest
|
|
|
+ @org.junit.jupiter.params.provider.ValueSource(booleans = {false, true})
|
|
|
+ void createsPendingBatchWithServerPricesNoDefaultCodAndFrozenAddress(boolean firstNumberOccupied) {
|
|
|
+ if (firstNumberOccupied) {
|
|
|
+ when(orderNumbers.execute(org.mockito.ArgumentMatchers.<RedisScript<Long>>any(), anyList(), anyString()))
|
|
|
+ .thenReturn(1789716730511L, 1789716730512L);
|
|
|
+ when(numberReservations.reserveIfUnused(org.mockito.ArgumentMatchers.eq("991789716730511"), anyString()))
|
|
|
+ .thenReturn(false);
|
|
|
+ }
|
|
|
arrangeQuote();
|
|
|
when(config.selectCurrentForUpdate()).thenReturn(policy());
|
|
|
InfoAddress address = new InfoAddress();
|
|
|
@@ -117,12 +132,28 @@ class MultiStoreCheckoutBatchServiceTest {
|
|
|
"retry-1", "quote-1", List.of(1L, 2L)), 42L);
|
|
|
|
|
|
assertEquals(99L, result.batchId());
|
|
|
+ assertEquals("991789716730512", result.parentOrderNo());
|
|
|
assertEquals("PENDING", result.checkoutStatus());
|
|
|
assertEquals(172, result.totalAmount());
|
|
|
assertEquals(2, result.members().size());
|
|
|
+ // 真实库pos_order.dd_id上限30,积分流水dd_id上限20;预留3位子单序号。
|
|
|
+ assertTrue(result.parentOrderNo().matches("99[0-9]{13}"));
|
|
|
+ assertTrue(result.parentOrderNo().length() <= 17,
|
|
|
+ "父单号须为子单预留序号,兼容现有最短20字符订单关联字段");
|
|
|
+ var parentCaptured = org.mockito.ArgumentCaptor.forClass(OrderParent.class);
|
|
|
+ verify(parents).insert(parentCaptured.capture());
|
|
|
+ assertEquals(result.parentOrderNo(), parentCaptured.getValue().getDdId());
|
|
|
+ var batchCaptured = org.mockito.ArgumentCaptor.forClass(OrderCheckoutBatch.class);
|
|
|
+ verify(checkout).insertOrGetBatch(batchCaptured.capture());
|
|
|
+ assertEquals(result.parentOrderNo(), batchCaptured.getValue().getParentDdId());
|
|
|
+ assertEquals(2, result.members().stream().map(member -> member.orderNo()).distinct().count());
|
|
|
var captured = org.mockito.ArgumentCaptor.forClass(PosOrder.class);
|
|
|
verify(orders, org.mockito.Mockito.times(2)).insert(captured.capture());
|
|
|
+ int sequence = 1;
|
|
|
for (PosOrder order : captured.getAllValues()) {
|
|
|
+ assertTrue(order.getDdId().length() <= 20, "子单号不能超过现有订单关联字段上限");
|
|
|
+ assertEquals(result.parentOrderNo(), order.getParentDdId());
|
|
|
+ assertEquals(result.parentOrderNo() + String.format("%03d", sequence++), order.getDdId());
|
|
|
assertEquals(86, order.getAmount());
|
|
|
assertEquals(36.0, order.getFreight());
|
|
|
assertEquals(new BigDecimal("36"), order.getCustomerDeliveryFee());
|
|
|
@@ -156,6 +187,7 @@ class MultiStoreCheckoutBatchServiceTest {
|
|
|
"retry-1", "quote-1", List.of(1L, 2L)), 42L);
|
|
|
|
|
|
assertEquals("MS-EXISTING", result.parentOrderNo());
|
|
|
+ org.mockito.Mockito.verifyNoInteractions(orderNumbers);
|
|
|
verify(quotes, never()).loadSnapshot(any(), any());
|
|
|
verify(parents, never()).insert(any(OrderParent.class));
|
|
|
}
|