fix: validate transfer rejection and align dispatch HTTP contracts
This commit is contained in:
+1
@@ -52,6 +52,7 @@ public final class WarehouseTransferRequests {
|
||||
}
|
||||
}
|
||||
|
||||
/** 审核通过备注选填;驳回必须提供非空原因,由服务在任何状态写入前校验。 */
|
||||
public record Review(@NotBlank @Size(max = 32) String decision,
|
||||
@Size(max = 1000) String remark) {}
|
||||
|
||||
|
||||
+5
-1
@@ -358,6 +358,9 @@ public class WarehouseTransferService {
|
||||
case "REJECT", REJECTED -> REJECTED;
|
||||
default -> throw badRequest("Review decision must be APPROVE or REJECT");
|
||||
};
|
||||
if (REJECTED.equals(next) && !StringUtils.hasText(request.remark())) {
|
||||
throw badRequest("驳回原因不能为空");
|
||||
}
|
||||
WarehouseTransferOrder transfer = transfers.lockNo(customerId, transferNo);
|
||||
if (transfer == null) throw notFound("Warehouse transfer order not found");
|
||||
if (!PENDING_REVIEW.equals(transfer.getStatus())) {
|
||||
@@ -384,7 +387,8 @@ public class WarehouseTransferService {
|
||||
order.setUpdatedAt(now); orders.updateById(order);
|
||||
if (!java.util.Objects.equals(before, orderStatus)) {
|
||||
insertOrderHistory(customerId, order.getId(), before, orderStatus, transferNo,
|
||||
"Warehouse transfer reviewed: " + next, now);
|
||||
"Warehouse transfer reviewed: " + next
|
||||
+ (StringUtils.hasText(request.remark()) ? "; " + request.remark().trim() : ""), now);
|
||||
}
|
||||
return detail(customerId, transferNo);
|
||||
}
|
||||
|
||||
+36
-1
@@ -222,7 +222,7 @@ class WarehouseTransferServiceTest {
|
||||
when(sourceOrders.selectList(any())).thenReturn(List.of());
|
||||
|
||||
var result = service.review("TENANT-A", "WTR-1", "USER-1",
|
||||
new WarehouseTransferRequests.Review("APPROVE", "approved"));
|
||||
new WarehouseTransferRequests.Review("APPROVE", null));
|
||||
|
||||
assertEquals(WarehouseTransferService.APPROVED, transfer.getStatus());
|
||||
assertEquals(WarehouseTransferService.PENDING_ASSIGNMENT, tailOrder.getCurrentStatus());
|
||||
@@ -233,6 +233,41 @@ class WarehouseTransferServiceTest {
|
||||
verifyNoInteractions(inventory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectionRequiresNonBlankReasonBeforeAnyStateOrInventoryChange() {
|
||||
for (String decision : List.of("REJECT", "REJECTED")) {
|
||||
for (String reason : new String[] { null, "", " \t\n" }) {
|
||||
var error = assertThrows(ResponseStatusException.class, () -> service.review(
|
||||
"TENANT-A", "WTR-1", "USER-1", new WarehouseTransferRequests.Review(decision, reason)));
|
||||
assertEquals(400, error.getStatusCode().value());
|
||||
assertEquals("驳回原因不能为空", error.getReason());
|
||||
}
|
||||
}
|
||||
verifyNoInteractions(transfers, orders, orderHistories, inventory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectionWithReasonCancelsLinkedOrderAndPreservesReasonInHistory() {
|
||||
WarehouseTransferOrder transfer = persistedTransfer();
|
||||
transfer.setStatus(WarehouseTransferService.PENDING_REVIEW);
|
||||
LastlegOrder tailOrder = historicalOrder();
|
||||
tailOrder.setId(31L); tailOrder.setCurrentStatus(WarehouseTransferService.PENDING_REVIEW);
|
||||
when(transfers.lockNo("TENANT-A", "WTR-1")).thenReturn(transfer);
|
||||
when(transfers.findNo("TENANT-A", "WTR-1")).thenReturn(transfer);
|
||||
when(orders.selectById(31L)).thenReturn(tailOrder);
|
||||
when(transferItems.selectList(any())).thenReturn(List.of());
|
||||
when(sourceOrders.selectList(any())).thenReturn(List.of());
|
||||
|
||||
var result = service.review("TENANT-A", "WTR-1", "USER-1",
|
||||
new WarehouseTransferRequests.Review("REJECT", " 地址不完整 "));
|
||||
assertEquals("REJECTED", result.status());
|
||||
assertEquals("CANCELLED", tailOrder.getCurrentStatus());
|
||||
var history = ArgumentCaptor.forClass(com.baiyue.lastleg.entity.LastlegOrderStatusHistory.class);
|
||||
verify(orderHistories).insert(history.capture());
|
||||
assertTrue(history.getValue().getRemark().endsWith("; 地址不完整"));
|
||||
verifyNoInteractions(inventory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void approvedTransferAllocatesExactSourceInboundPalletWithoutMovingInventory() {
|
||||
WarehouseTransferOrder transfer = transfer("APPROVED");
|
||||
|
||||
Reference in New Issue
Block a user