暂存提交
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
package com.baiyue.lastleg.trucking;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class UsTruckOrderSchemaContractTest {
|
||||
@Test
|
||||
void baselineContainsOrderAndImmutableHistoryTables() throws Exception {
|
||||
String sql;
|
||||
try (var input = getClass().getResourceAsStream("/db/lastleg.sql")) {
|
||||
sql = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_us_truck_order"));
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_us_truck_order_status_history"));
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_us_truck_order_pallet"));
|
||||
assertTrue(sql.contains("pallet_count INT NOT NULL DEFAULT 1"));
|
||||
assertTrue(sql.contains("received_pallet_count INT NOT NULL DEFAULT 0"));
|
||||
assertTrue(sql.contains("receipt_idempotency_key VARCHAR(255) NULL"));
|
||||
assertTrue(sql.contains("UNIQUE KEY uk_ll_us_truck_order_key(customer_id,idempotency_key)"));
|
||||
assertTrue(sql.contains("KEY idx_ll_us_truck_history(customer_id,order_id,created_at)"));
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.baiyue.lastleg.trucking.controller;
|
||||
|
||||
import com.baiyue.common.security.AuthenticatedUser;
|
||||
import com.baiyue.lastleg.trucking.dto.UsTruckOrderRequests;
|
||||
import com.baiyue.lastleg.trucking.service.UsTruckOrderService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UsTruckOrderControllerTest {
|
||||
@Mock UsTruckOrderService service;
|
||||
private MerchantUsTruckOrderController merchant;
|
||||
private PlatformUsTruckOrderController platform;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
merchant = new MerchantUsTruckOrderController(); platform = new PlatformUsTruckOrderController();
|
||||
ReflectionTestUtils.setField(merchant, "service", service); ReflectionTestUtils.setField(platform, "service", service);
|
||||
}
|
||||
|
||||
@Test
|
||||
void merchantListAlwaysUsesTrustedTenant() {
|
||||
var query = query(); merchant.page(user(100L, "MERCHANT", Set.of()), query);
|
||||
verify(service).page("100", query);
|
||||
}
|
||||
|
||||
@Test
|
||||
void platformStatusChangeRequiresManagePermission() {
|
||||
var request = new UsTruckOrderRequests.ChangeStatus(0L, "DISPATCHED", null);
|
||||
ResponseStatusException error = assertThrows(ResponseStatusException.class,
|
||||
() -> platform.changeStatus(user(0L, "PLATFORM", Set.of()), "100", "TK1", request));
|
||||
assertEquals(403, error.getStatusCode().value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void platformStatusChangeUsesExplicitTargetTenant() {
|
||||
var request = new UsTruckOrderRequests.ChangeStatus(0L, "DISPATCHED", "truck assigned");
|
||||
platform.changeStatus(user(0L, "PLATFORM", Set.of(UsTruckOrderService.MANAGE_PERMISSION)), "100", "TK1", request);
|
||||
verify(service).changeStatus("100", "TK1", "7", request);
|
||||
}
|
||||
|
||||
private UsTruckOrderRequests.Query query() { return new UsTruckOrderRequests.Query(1, 20, null, null, null, null, null, null, null); }
|
||||
private AuthenticatedUser user(long tenant, String app, Set<String> permissions) {
|
||||
return new AuthenticatedUser(7L, tenant, tenant, 8L, "operator", app, "WEB", permissions);
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
package com.baiyue.lastleg.trucking.service;
|
||||
|
||||
import com.baiyue.lastleg.trucking.dto.UsTruckOrderRequests;
|
||||
import com.baiyue.lastleg.trucking.entity.UsTruckOrder;
|
||||
import com.baiyue.lastleg.trucking.entity.UsTruckOrderPallet;
|
||||
import com.baiyue.lastleg.trucking.entity.UsTruckOrderStatusHistory;
|
||||
import com.baiyue.lastleg.trucking.mapper.UsTruckOrderMapper;
|
||||
import com.baiyue.lastleg.trucking.mapper.UsTruckOrderPalletMapper;
|
||||
import com.baiyue.lastleg.trucking.mapper.UsTruckOrderStatusHistoryMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
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.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UsTruckOrderServiceTest {
|
||||
@Mock UsTruckOrderMapper orders;
|
||||
@Mock UsTruckOrderPalletMapper pallets;
|
||||
@Mock UsTruckOrderStatusHistoryMapper histories;
|
||||
private UsTruckOrderService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = new UsTruckOrderService();
|
||||
ReflectionTestUtils.setField(service, "orders", orders);
|
||||
ReflectionTestUtils.setField(service, "pallets", pallets);
|
||||
ReflectionTestUtils.setField(service, "histories", histories);
|
||||
ReflectionTestUtils.setField(service, "objectMapper", new ObjectMapper().findAndRegisterModules());
|
||||
org.mockito.Mockito.lenient().when(pallets.listOrder(anyString(), any())).thenReturn(List.of());
|
||||
}
|
||||
|
||||
@Test
|
||||
void customerOrderStartsPendingConfirmationAndUsesUsdByDefault() {
|
||||
AtomicReference<UsTruckOrder> saved = new AtomicReference<>();
|
||||
when(orders.insert(any(UsTruckOrder.class))).thenAnswer(call -> { saved.set(call.getArgument(0)); return 1; });
|
||||
when(orders.findNo(anyString(), anyString())).thenAnswer(call -> saved.get());
|
||||
when(histories.listOrder(anyString(), any())).thenReturn(List.of());
|
||||
|
||||
var detail = service.create("100", "7", create("key-1"));
|
||||
|
||||
assertEquals(UsTruckOrderService.PENDING_CONFIRMATION, detail.summary().status());
|
||||
assertEquals("USD", detail.summary().currency());
|
||||
assertEquals("100", detail.summary().customerId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusChangePersistsHistoryAndIncrementsVersion() {
|
||||
UsTruckOrder order = order(UsTruckOrderService.PENDING_CONFIRMATION, 0L);
|
||||
when(orders.lockNo("100", "TK1")).thenReturn(order);
|
||||
when(orders.findNo("100", "TK1")).thenReturn(order);
|
||||
when(histories.listOrder("100", 1L)).thenReturn(List.of());
|
||||
|
||||
var result = service.changeStatus("100", "TK1", "7",
|
||||
new UsTruckOrderRequests.ChangeStatus(0L, "WAITING_INBOUND", "accepted"));
|
||||
|
||||
assertEquals(UsTruckOrderService.WAITING_INBOUND, result.summary().status());
|
||||
assertEquals(1, result.summary().version());
|
||||
verify(histories).insert(any(UsTruckOrderStatusHistory.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void staleStatusChangeIsRejected() {
|
||||
when(orders.lockNo("100", "TK1")).thenReturn(order(UsTruckOrderService.DISPATCHED, 2L));
|
||||
ResponseStatusException error = assertThrows(ResponseStatusException.class, () ->
|
||||
service.changeStatus("100", "TK1", "7", new UsTruckOrderRequests.ChangeStatus(1L, "IN_TRANSIT", null)));
|
||||
assertEquals(409, error.getStatusCode().value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void detailIncludesBoundPallets() {
|
||||
UsTruckOrder order = order(UsTruckOrderService.WAITING_INBOUND, 1L);
|
||||
UsTruckOrderPallet pallet = new UsTruckOrderPallet();
|
||||
pallet.setId(10L); pallet.setPalletNo("PLT-001"); pallet.setSequenceNo(1);
|
||||
pallet.setSource("SYSTEM"); pallet.setStatus("OCCUPIED");
|
||||
pallet.setWarehousePalletId(20L); pallet.setPackageCount(12);
|
||||
when(orders.findNo("100", "TK1")).thenReturn(order);
|
||||
when(histories.listOrder("100", 1L)).thenReturn(List.of());
|
||||
when(pallets.listOrder("100", 1L)).thenReturn(List.of(pallet));
|
||||
|
||||
var detail = service.detail("100", "TK1");
|
||||
|
||||
assertEquals(1, detail.pallets().size());
|
||||
assertEquals("PLT-001", detail.pallets().get(0).palletNo());
|
||||
assertEquals(12, detail.pallets().get(0).packageCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void receivingMorePalletsCreatesOverageAndKeepsDeclaredCount() {
|
||||
UsTruckOrder order = order(UsTruckOrderService.WAITING_INBOUND, 0L);
|
||||
order.setPalletCount(1);
|
||||
when(orders.lockNo("100", "TK1")).thenReturn(order);
|
||||
when(orders.findNo("100", "TK1")).thenReturn(order);
|
||||
when(histories.listOrder("100", 1L)).thenReturn(List.of());
|
||||
List<UsTruckOrderPallet> savedPallets = new ArrayList<>();
|
||||
when(pallets.listOrder("100", 1L)).thenAnswer(call -> List.copyOf(savedPallets));
|
||||
when(pallets.insert(any(UsTruckOrderPallet.class))).thenAnswer(call -> {
|
||||
savedPallets.add(call.getArgument(0));
|
||||
return 1;
|
||||
});
|
||||
|
||||
var result = service.receivePallets("100", "TK1", "7",
|
||||
new UsTruckOrderRequests.ReceivePallets(0L, 3, 0, "receive-1", "actual three pallets"));
|
||||
|
||||
assertEquals(1, result.summary().palletCount());
|
||||
assertEquals(3, result.summary().receivedPalletCount());
|
||||
assertEquals(UsTruckOrderService.PALLET_OVERAGE_REVIEW, result.summary().status());
|
||||
verify(pallets, org.mockito.Mockito.times(3)).insert(any(UsTruckOrderPallet.class));
|
||||
}
|
||||
|
||||
private UsTruckOrderRequests.Create create(String key) {
|
||||
return new UsTruckOrderRequests.Create("PORT_PICKUP", "Los Angeles Port", "Pier 1", "Ontario, CA",
|
||||
"Warehouse A", "40HQ", 100, new BigDecimal("12600"), new BigDecimal("55.2"),
|
||||
new BigDecimal("3800"), null, "Alice", "+1-555-0100", LocalDate.now().plusDays(2), null, key);
|
||||
}
|
||||
|
||||
private UsTruckOrder order(String status, long version) {
|
||||
UsTruckOrder order = new UsTruckOrder(); order.setId(1L); order.setCustomerId("100"); order.setOrderNo("TK1");
|
||||
order.setTransportType("PORT_PICKUP"); order.setOrigin("Los Angeles"); order.setDestination("Ontario");
|
||||
order.setContainerType("40HQ"); order.setPalletCount(1); order.setPackageCount(0);
|
||||
order.setReceivedPalletCount(0); order.setAllocatedPalletCount(0); order.setShippedPalletCount(0);
|
||||
order.setStatus(status); order.setVersion(version);
|
||||
order.setCreatedAt(LocalDateTime.now()); order.setUpdatedAt(order.getCreatedAt()); return order;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user