fix: reserve stable inbound code for draft label printing
This commit is contained in:
@@ -5,6 +5,8 @@ import com.baiyue.order.entity.OrderCargoEntity;
|
||||
import com.baiyue.order.entity.OrderEntity;
|
||||
import com.baiyue.order.entity.OrderInternalNoteEntity;
|
||||
import com.baiyue.order.repository.OrderRepository;
|
||||
import com.baiyue.order.service.OrderApplicationService;
|
||||
import com.baiyue.order.service.PrintableInboundSnapshotService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
@@ -23,11 +25,13 @@ import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
@SpringJUnitConfig(InternalOrderCargoController.class)
|
||||
@TestPropertySource(properties = "baiyue.security.internal-service-token=internal-token")
|
||||
class InternalOrderCargoControllerTest {
|
||||
@MockBean private OrderRepository orders;
|
||||
@MockBean private PrintableInboundSnapshotService printableInboundSnapshots;
|
||||
@Resource private InternalOrderCargoController controller;
|
||||
|
||||
@Test
|
||||
@@ -145,6 +149,24 @@ class InternalOrderCargoControllerTest {
|
||||
verify(orders).findOwned(11L, 21L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void reservesPrintableSnapshotThroughExplicitCommandRoute() throws Exception {
|
||||
OrderEntity order = new OrderEntity();
|
||||
order.setTenantId(11L); order.setId(21L); order.setDestinationType("FBA");
|
||||
order.setTransportMode("SEA");
|
||||
var snapshot = OrderApplicationService.inboundCommand(order, 3);
|
||||
when(printableInboundSnapshots.reserve(11L, 21L)).thenReturn(snapshot);
|
||||
|
||||
var response = controller.printableInboundSnapshot("internal-token", 11L, 21L);
|
||||
|
||||
assertThat(response.data()).isSameAs(snapshot);
|
||||
verify(printableInboundSnapshots).reserve(11L, 21L);
|
||||
Method route = InternalOrderCargoController.class.getMethod(
|
||||
"printableInboundSnapshot", String.class, long.class, long.class);
|
||||
assertThat(route.getAnnotation(PostMapping.class).value())
|
||||
.containsExactly("/{tenantId}/{orderId}/printable-inbound-snapshot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void measurementDeclarationUsesOrderReferenceAndSumsCargoFacts() {
|
||||
OrderEntity order = new OrderEntity();
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baiyue.order.controller;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class PrintableInboundSnapshotOpenApiContractTest {
|
||||
@Test
|
||||
void documentsTheMutatingInternalCommandAsPost() throws Exception {
|
||||
try (var stream = getClass().getResourceAsStream("/openapi/order-v1.yaml")) {
|
||||
assertThat(stream).isNotNull();
|
||||
String yaml = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
assertThat(yaml).contains(
|
||||
"/internal/order/v1/cargoes/{tenantId}/{orderId}/printable-inbound-snapshot:",
|
||||
"若 AUTO 模式草稿尚无入仓码,则按订单渠道原子预留全局唯一入仓码",
|
||||
"后续订单提交继续复用");
|
||||
}
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package com.baiyue.order.service;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.order.config.InboundCodeModeProvider;
|
||||
import com.baiyue.order.entity.OrderCargoEntity;
|
||||
import com.baiyue.order.entity.OrderEntity;
|
||||
import com.baiyue.order.repository.OrderRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class PrintableInboundSnapshotServiceTest {
|
||||
@Test
|
||||
void reservesStableCodeForDraftAndReturnsPrintableSnapshot() {
|
||||
OrderRepository orders = mock(OrderRepository.class);
|
||||
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
|
||||
OrderApplicationService application = mock(OrderApplicationService.class);
|
||||
OrderEntity order = draft();
|
||||
OrderCargoEntity cargo = new OrderCargoEntity();
|
||||
cargo.setPackageCount(3);
|
||||
when(orders.findOwned(11L, 21L)).thenReturn(order);
|
||||
when(pricing.requireAvailable(11L, 41L, "CH", "FBA")).thenReturn("PCHK");
|
||||
when(application.nextInboundCode("PCHK")).thenReturn("PCHK2609080001");
|
||||
when(orders.assignInboundCodeIfBlank(11L, 21L, "PCHK2609080001")).thenReturn(1);
|
||||
when(orders.findCargoInheritedByOrder(11L, 21L)).thenReturn(List.of(cargo));
|
||||
|
||||
var result = service(orders, pricing, application, "AUTO").reserve(11L, 21L);
|
||||
|
||||
assertThat(result.inboundCode()).isEqualTo("PCHK2609080001");
|
||||
assertThat(result.totalPackageCount()).isEqualTo(3);
|
||||
verify(orders).assignInboundCodeIfBlank(11L, 21L, "PCHK2609080001");
|
||||
}
|
||||
|
||||
@Test
|
||||
void reusesCodeAlreadyReservedByAConcurrentRequest() {
|
||||
OrderRepository orders = mock(OrderRepository.class);
|
||||
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
|
||||
OrderApplicationService application = mock(OrderApplicationService.class);
|
||||
OrderEntity initial = draft();
|
||||
OrderEntity winner = draft();
|
||||
winner.setInboundCode("PCHK2609080002");
|
||||
when(orders.findOwned(11L, 21L)).thenReturn(initial, winner);
|
||||
when(pricing.requireAvailable(11L, 41L, "CH", "FBA")).thenReturn("PCHK");
|
||||
when(application.nextInboundCode("PCHK")).thenReturn("PCHK2609080001");
|
||||
when(orders.assignInboundCodeIfBlank(11L, 21L, "PCHK2609080001")).thenReturn(0);
|
||||
when(orders.findCargoInheritedByOrder(11L, 21L)).thenReturn(List.of());
|
||||
|
||||
var result = service(orders, pricing, application, "AUTO").reserve(11L, 21L);
|
||||
|
||||
assertThat(result.inboundCode()).isEqualTo("PCHK2609080002");
|
||||
}
|
||||
|
||||
@Test
|
||||
void existingCodeDoesNotAllocateAnotherSequence() {
|
||||
OrderRepository orders = mock(OrderRepository.class);
|
||||
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
|
||||
OrderApplicationService application = mock(OrderApplicationService.class);
|
||||
OrderEntity order = draft();
|
||||
order.setInboundCode("PCHK2609080001");
|
||||
when(orders.findOwned(11L, 21L)).thenReturn(order);
|
||||
when(orders.findCargoInheritedByOrder(11L, 21L)).thenReturn(List.of());
|
||||
|
||||
var result = service(orders, pricing, application, "AUTO").reserve(11L, 21L);
|
||||
|
||||
assertThat(result.inboundCode()).isEqualTo("PCHK2609080001");
|
||||
verify(application, never()).nextInboundCode(org.mockito.ArgumentMatchers.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void legacyManualModeRejectsMissingCodeWithoutWriting() {
|
||||
OrderRepository orders = mock(OrderRepository.class);
|
||||
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
|
||||
OrderApplicationService application = mock(OrderApplicationService.class);
|
||||
when(orders.findOwned(11L, 21L)).thenReturn(draft());
|
||||
|
||||
assertThatThrownBy(() -> service(orders, pricing, application, "LEGACY_MANUAL").reserve(11L, 21L))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessage("当前系统使用旧系统入仓码,请先填写入仓码");
|
||||
|
||||
verify(orders, never()).assignInboundCodeIfBlank(
|
||||
org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong(),
|
||||
org.mockito.ArgumentMatchers.anyString());
|
||||
}
|
||||
|
||||
private PrintableInboundSnapshotService service(OrderRepository orders,
|
||||
OrderPricingChannelGuard pricing,
|
||||
OrderApplicationService application,
|
||||
String mode) {
|
||||
return new PrintableInboundSnapshotService(
|
||||
orders, pricing, new InboundCodeModeProvider(mode), application);
|
||||
}
|
||||
|
||||
private OrderEntity draft() {
|
||||
OrderEntity order = new OrderEntity();
|
||||
order.setId(21L);
|
||||
order.setTenantId(11L);
|
||||
order.setOrderNo("FL21");
|
||||
order.setCustomerId(11L);
|
||||
order.setReceivingWarehouseId(41L);
|
||||
order.setChannelCode("CH");
|
||||
order.setDestinationType("FBA");
|
||||
order.setTransportMode("SEA");
|
||||
order.setFulfillmentType("STANDARD");
|
||||
return order;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user