feat: gate overseas receiving and harden phase4 workflows
This commit is contained in:
+2
@@ -15,6 +15,8 @@ class LocalLooseboardSchemaContractTest {
|
||||
}
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_local_looseboard_order"));
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_local_looseboard_history"));
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_local_looseboard_operation"));
|
||||
assertTrue(sql.contains("uk_ll_local_looseboard_operation_key(customer_id,order_id,idempotency_key)"));
|
||||
assertTrue(sql.contains("operation_type VARCHAR(32) NOT NULL"));
|
||||
assertTrue(sql.contains("uk_ll_local_looseboard_no(customer_id,order_no)"));
|
||||
assertTrue(sql.contains("lastleg_order_id BIGINT NULL"));
|
||||
|
||||
+59
-2
@@ -3,8 +3,10 @@ package com.baiyue.lastleg.looseboard.service;
|
||||
import com.baiyue.lastleg.looseboard.dto.LocalLooseboardRequests;
|
||||
import com.baiyue.lastleg.looseboard.entity.LocalLooseboardHistory;
|
||||
import com.baiyue.lastleg.looseboard.entity.LocalLooseboardOrder;
|
||||
import com.baiyue.lastleg.looseboard.entity.LocalLooseboardOperation;
|
||||
import com.baiyue.lastleg.looseboard.mapper.LocalLooseboardHistoryMapper;
|
||||
import com.baiyue.lastleg.looseboard.mapper.LocalLooseboardOrderMapper;
|
||||
import com.baiyue.lastleg.looseboard.mapper.LocalLooseboardOperationMapper;
|
||||
import com.baiyue.lastleg.entity.LastlegOrder;
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderStatusHistoryMapper;
|
||||
@@ -22,6 +24,8 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -29,27 +33,38 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class LocalLooseboardServiceTest {
|
||||
@Mock LocalLooseboardOrderMapper orders;
|
||||
@Mock LocalLooseboardHistoryMapper histories;
|
||||
@Mock LocalLooseboardOperationMapper operations;
|
||||
@Mock LastlegOrderMapper lastlegOrders;
|
||||
@Mock LastlegOrderStatusHistoryMapper lastlegHistories;
|
||||
@Mock LastlegOrderNoGenerator lastlegOrderNoGenerator;
|
||||
private LocalLooseboardService service;
|
||||
private final Map<String, LocalLooseboardOperation> operationRows = new HashMap<>();
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = new LocalLooseboardService();
|
||||
ReflectionTestUtils.setField(service, "orders", orders);
|
||||
ReflectionTestUtils.setField(service, "histories", histories);
|
||||
ReflectionTestUtils.setField(service, "operations", operations);
|
||||
ReflectionTestUtils.setField(service, "lastlegOrders", lastlegOrders);
|
||||
ReflectionTestUtils.setField(service, "lastlegHistories", lastlegHistories);
|
||||
ReflectionTestUtils.setField(service, "lastlegOrderNoGenerator", lastlegOrderNoGenerator);
|
||||
ReflectionTestUtils.setField(service, "objectMapper", new ObjectMapper().findAndRegisterModules());
|
||||
org.mockito.Mockito.lenient().when(lastlegOrderNoGenerator.next()).thenReturn("LMO-LOOSE-1");
|
||||
org.mockito.Mockito.lenient().when(operations.findKey(anyString(), any(), anyString()))
|
||||
.thenAnswer(call -> operationRows.get(call.getArgument(2)));
|
||||
org.mockito.Mockito.lenient().when(operations.insert(any(LocalLooseboardOperation.class))).thenAnswer(call -> {
|
||||
LocalLooseboardOperation value = call.getArgument(0);
|
||||
operationRows.put(value.getIdempotencyKey(), value);
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -103,12 +118,54 @@ class LocalLooseboardServiceTest {
|
||||
when(histories.listOrder("100", 1L)).thenReturn(List.of());
|
||||
|
||||
var detail = service.changeStatus("100", "LB1", "7",
|
||||
new LocalLooseboardRequests.ChangeStatus(0L, "DISPATCHED", "accepted"));
|
||||
new LocalLooseboardRequests.ChangeStatus(0L, "DISPATCHED", "status-1", "accepted"));
|
||||
|
||||
assertEquals(LocalLooseboardService.DISPATCHED, detail.summary().status());
|
||||
assertEquals(1L, detail.summary().version());
|
||||
verify(histories).insert(org.mockito.ArgumentMatchers.<LocalLooseboardHistory>argThat(value ->
|
||||
"STATUS".equals(value.getOperationType()) && "DISPATCHED".equals(value.getToStatus())));
|
||||
"STATUS".equals(value.getOperationType()) && "DISPATCHED".equals(value.getToStatus())
|
||||
&& "7".equals(value.getOperatorId()) && "status-1".equals(value.getIdempotencyKey())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fullStatusLifecycleIsIdempotentAndCompletedCannotReverse() {
|
||||
LocalLooseboardOrder order = order(LocalLooseboardService.PENDING_ACCEPTANCE, 0L);
|
||||
when(orders.lockNo("100", "LB1")).thenReturn(order);
|
||||
when(histories.listOrder("100", 1L)).thenReturn(List.of());
|
||||
var dispatch = new LocalLooseboardRequests.ChangeStatus(0L, "DISPATCHED", "dispatch-1", "dispatch");
|
||||
assertEquals(LocalLooseboardService.DISPATCHED,
|
||||
service.changeStatus("100", "LB1", "operator-7", dispatch).summary().status());
|
||||
assertEquals(1L, service.changeStatus("100", "LB1", "operator-7", dispatch).summary().version());
|
||||
assertThrows(ResponseStatusException.class, () -> service.changeStatus("100", "LB1", "operator-7",
|
||||
new LocalLooseboardRequests.ChangeStatus(1L, "IN_TRANSIT", "dispatch-1", "different")));
|
||||
assertThrows(ResponseStatusException.class, () -> service.changeStatus("100", "LB1", "operator-7",
|
||||
new LocalLooseboardRequests.ChangeStatus(0L, "IN_TRANSIT", "stale-1", "stale")));
|
||||
assertEquals(LocalLooseboardService.IN_TRANSIT, service.changeStatus("100", "LB1", "operator-8",
|
||||
new LocalLooseboardRequests.ChangeStatus(1L, "IN_TRANSIT", "transit-1", "transit"))
|
||||
.summary().status());
|
||||
assertEquals(LocalLooseboardService.COMPLETED, service.changeStatus("100", "LB1", "operator-9",
|
||||
new LocalLooseboardRequests.ChangeStatus(2L, "COMPLETED", "complete-1", "complete"))
|
||||
.summary().status());
|
||||
assertThrows(ResponseStatusException.class, () -> service.changeStatus("100", "LB1", "operator-9",
|
||||
new LocalLooseboardRequests.ChangeStatus(3L, "IN_TRANSIT", "reverse-1", "reverse")));
|
||||
verify(histories, times(3)).insert(org.mockito.ArgumentMatchers.<LocalLooseboardHistory>argThat(value ->
|
||||
"STATUS".equals(value.getOperationType()) && value.getOperatorId() != null
|
||||
&& value.getIdempotencyKey() != null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void separateDispatchedFixtureCanCancelButCannotProgressAfterCancellation() {
|
||||
LocalLooseboardOrder order = order(LocalLooseboardService.PENDING_ACCEPTANCE, 0L);
|
||||
when(orders.lockNo("100", "LB1")).thenReturn(order);
|
||||
when(histories.listOrder("100", 1L)).thenReturn(List.of());
|
||||
assertEquals(LocalLooseboardService.DISPATCHED, service.changeStatus("100", "LB1", "operator-7",
|
||||
new LocalLooseboardRequests.ChangeStatus(0L, "DISPATCHED", "cancel-fixture-dispatch", "dispatch"))
|
||||
.summary().status());
|
||||
assertEquals(LocalLooseboardService.CANCELLED, service.changeStatus("100", "LB1", "operator-7",
|
||||
new LocalLooseboardRequests.ChangeStatus(1L, "CANCELLED", "cancel-1", "cancel"))
|
||||
.summary().status());
|
||||
assertThrows(ResponseStatusException.class, () -> service.changeStatus("100", "LB1", "operator-7",
|
||||
new LocalLooseboardRequests.ChangeStatus(2L, "IN_TRANSIT", "after-cancel", "invalid")));
|
||||
}
|
||||
|
||||
private LocalLooseboardRequests.Create create(String key) {
|
||||
|
||||
Reference in New Issue
Block a user