feat: gate overseas receiving and harden phase4 workflows
This commit is contained in:
+10
@@ -31,6 +31,16 @@ class OverseasProcurementOpenApiContractTest {
|
||||
}
|
||||
assertTrue(yaml.contains("platform:overseas-business:truck:create"));
|
||||
assertTrue(yaml.contains("platform:overseas-business:truck:edit"));
|
||||
assertTrue(yaml.contains("/{orderNo}/review:"));
|
||||
assertTrue(yaml.contains("/{orderNo}/receive-pallets:"));
|
||||
assertTrue(yaml.contains("/{orderNo}/review-pallet-overage:"));
|
||||
assertTrue(yaml.contains("/{orderNo}/allocate-pallets:"));
|
||||
assertTrue(yaml.contains("/{orderNo}/prepare-dispatch:"));
|
||||
assertTrue(yaml.contains("/{orderNo}/dispatch:"));
|
||||
assertTrue(yaml.contains("/{orderNo}/start-transit:"));
|
||||
assertTrue(yaml.contains("/{orderNo}/complete:"));
|
||||
assertTrue(yaml.contains("enum: [PENDING_REVIEW, WAITING_INBOUND, RECEIVING, WAITING_CONSOLIDATION, PALLET_OVERAGE_REVIEW, PARTIALLY_ALLOCATED, ALLOCATED, PENDING_DISPATCH, DISPATCHED, IN_TRANSIT, COMPLETED, REJECTED, CANCELLED]"));
|
||||
assertTrue(yaml.contains("required: [version, status, idempotencyKey]"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/local-looseboard-orders:"));
|
||||
assertTrue(yaml.contains("platform:overseas-business:looseboard:list"));
|
||||
assertTrue(yaml.contains("platform:overseas-business:looseboard:create"));
|
||||
|
||||
+3
@@ -16,6 +16,9 @@ class OverseasProcurementSchemaContractTest {
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_overseas_procurement_order"));
|
||||
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_overseas_procurement_status_history"));
|
||||
assertTrue(sql.contains("operation_type VARCHAR(32) NOT NULL"));
|
||||
assertTrue(sql.contains("review_idempotency_key VARCHAR(255) NULL"));
|
||||
assertTrue(sql.contains("review_request_hash CHAR(64) NULL"));
|
||||
assertTrue(sql.contains("idempotency_key VARCHAR(255) NULL COMMENT '操作幂等键'"));
|
||||
assertTrue(sql.contains("change_detail JSON NULL"));
|
||||
org.junit.jupiter.api.Assertions.assertFalse(sql.contains("CREATE TABLE IF NOT EXISTS ll_overseas_procurement_outbound"));
|
||||
org.junit.jupiter.api.Assertions.assertFalse(sql.contains("outbound_quantity BIGINT"));
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ class OverseasProcurementControllerTest {
|
||||
|
||||
@Test
|
||||
void reviewRequiresExplicitPermission() {
|
||||
var request = new OverseasProcurementRequests.Review("APPROVE", null);
|
||||
var request = new OverseasProcurementRequests.Review(0L, "APPROVE", "review-1", null);
|
||||
ResponseStatusException error = assertThrows(ResponseStatusException.class,
|
||||
() -> platform.review(user(0L, "PLATFORM", Set.of()), "100", "HC1", request));
|
||||
assertEquals(403, error.getStatusCode().value());
|
||||
@@ -56,7 +56,7 @@ class OverseasProcurementControllerTest {
|
||||
|
||||
@Test
|
||||
void platformReviewUsesExplicitTargetTenant() {
|
||||
var request = new OverseasProcurementRequests.Review("APPROVE", "ok");
|
||||
var request = new OverseasProcurementRequests.Review(0L, "APPROVE", "review-1", "ok");
|
||||
platform.review(user(0L, "PLATFORM", Set.of(OverseasProcurementService.REVIEW_PERMISSION)),
|
||||
"100", "HC1", request);
|
||||
verify(service).review("100", "HC1", "7", request);
|
||||
|
||||
+27
@@ -145,6 +145,33 @@ class OverseasProcurementServiceTest {
|
||||
assertEquals("Acme", values.get(0).customerName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void approveReviewIsIdempotentAuditedAndTerminalCannotReverse() {
|
||||
OverseasProcurementOrder order = order(OverseasProcurementService.PENDING_REVIEW, 0, 0);
|
||||
when(orders.lockNo("100", "HC1")).thenReturn(order);
|
||||
when(orders.findNo("100", "HC1")).thenReturn(order);
|
||||
when(histories.listOrder("100", 1L)).thenReturn(List.of());
|
||||
var request = new OverseasProcurementRequests.Review(0L, "APPROVE", "approve-1", "approved");
|
||||
|
||||
var approved = service.review("100", "HC1", "operator-7", request);
|
||||
assertEquals(OverseasProcurementService.APPROVED, approved.summary().status());
|
||||
assertEquals(1L, approved.summary().version());
|
||||
assertEquals(1L, service.review("100", "HC1", "operator-7", request).summary().version());
|
||||
verify(histories).insert(org.mockito.ArgumentMatchers
|
||||
.<com.baiyue.lastleg.procurement.entity.OverseasProcurementStatusHistory>argThat(value ->
|
||||
"REVIEW".equals(value.getOperationType()) && "operator-7".equals(value.getOperatorId())
|
||||
&& "approve-1".equals(value.getIdempotencyKey())
|
||||
&& OverseasProcurementService.APPROVED.equals(value.getToStatus())));
|
||||
|
||||
assertThrows(ResponseStatusException.class, () -> service.review("100", "HC1", "operator-7",
|
||||
new OverseasProcurementRequests.Review(1L, "REJECT", "approve-1", "different payload")));
|
||||
assertThrows(ResponseStatusException.class, () -> service.review("100", "HC1", "operator-7",
|
||||
new OverseasProcurementRequests.Review(0L, "REJECT", "stale-review", "old version")));
|
||||
assertThrows(ResponseStatusException.class, () -> service.review("100", "HC1", "operator-7",
|
||||
new OverseasProcurementRequests.Review(1L, "REJECT", "reject-after-approved", "reverse")));
|
||||
assertEquals(OverseasProcurementService.APPROVED, order.getStatus());
|
||||
}
|
||||
|
||||
private OverseasProcurementOrder order(String status, long inbound, long outbound) {
|
||||
OverseasProcurementOrder order = new OverseasProcurementOrder();
|
||||
order.setId(1L);
|
||||
|
||||
Reference in New Issue
Block a user