贴标申请,仓储转运

This commit is contained in:
2026-10-13 18:05:30 +08:00
parent c07131b26f
commit 38958c891a
3 changed files with 41 additions and 2 deletions
@@ -20,7 +20,8 @@ public final class RelabelResponses {
String fulfillmentStatus, String outboundOrderNo, LocalDateTime customerConfirmedAt, String fulfillmentStatus, String outboundOrderNo, LocalDateTime customerConfirmedAt,
String reviewChannel, String reviewRemark, LocalDateTime createdAt, String reviewChannel, String reviewRemark, LocalDateTime createdAt,
LocalDateTime reviewedAt, LocalDateTime relabelCompletedAt, LocalDateTime outboundAt, LocalDateTime reviewedAt, LocalDateTime relabelCompletedAt, LocalDateTime outboundAt,
String productNameZh, String labelRequirement, List<String> operationTypes) {} String productNameZh, String labelRequirement, List<String> operationTypes,
List<String> relatedBusinessOrderNos) {}
public record Milestones(LocalDateTime reviewedAt, LocalDateTime relabelCompletedAt, public record Milestones(LocalDateTime reviewedAt, LocalDateTime relabelCompletedAt,
LocalDateTime outboundAt) {} LocalDateTime outboundAt) {}
public record Item(Long id, String skuCode, String productImageFileId, String productImageFileName, public record Item(Long id, String skuCode, String productImageFileId, String productImageFileName,
@@ -1228,7 +1228,22 @@ public class RelabelApplicationService implements WalletResultHandler {
detailItems.stream().map(RelabelItem::getLabelRequirement).filter(StringUtils::hasText) detailItems.stream().map(RelabelItem::getLabelRequirement).filter(StringUtils::hasText)
.map(String::trim).distinct().collect(Collectors.joining(";")), .map(String::trim).distinct().collect(Collectors.joining(";")),
detailItems.stream().map(RelabelItem::getOperationType).filter(StringUtils::hasText) detailItems.stream().map(RelabelItem::getOperationType).filter(StringUtils::hasText)
.map(String::trim).distinct().toList()); .map(String::trim).distinct().toList(), relatedBusinessOrderNos(value, order, detailItems));
}
private List<String> relatedBusinessOrderNos(RelabelApplication application, LastlegOrder order,
List<RelabelItem> detailItems) {
if (order != null && Objects.equals(application.getCustomerId(), order.getCustomerId())
&& !"RELABEL_APPLICATION".equals(order.getOrderType())) {
String businessNo = StringUtils.hasText(order.getSourceOrderNo()) ? order.getSourceOrderNo() : order.getOrderNo();
if (StringUtils.hasText(businessNo)) return List.of(businessNo.trim());
}
// Standalone relabel orders keep the actual inventory source on their item snapshots.
// Their tail sourceOrderNo is a customer reference, not a business order number.
return detailItems.stream().map(item -> StringUtils.hasText(item.getSourceInboundOrderNo())
? item.getSourceInboundOrderNo()
: "RETURN_BULK_SKU_LABEL".equals(item.getOperationType()) ? item.getShipmentNo() : null)
.filter(StringUtils::hasText).map(String::trim).distinct().toList();
} }
@Override public boolean supports(String businessType) { return "RELABEL_ORDER".equals(businessType); } @Override public boolean supports(String businessType) { return "RELABEL_ORDER".equals(businessType); }
@@ -66,6 +66,29 @@ import static org.mockito.Mockito.times;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class RelabelApplicationServiceTest { class RelabelApplicationServiceTest {
@Test void relatedBusinessNumbersUseAuthoritativeSourcesInsteadOfCustomerReferences() {
var application = new RelabelApplication(); application.setCustomerId("C1"); application.setCustomerOrderNo("CUSTOMER-REFERENCE");
var order = new LastlegOrder(); order.setCustomerId("C1"); order.setOrderNo("TAIL-INTERNAL-NO");
for (var type : List.of("WAREHOUSE_TRANSFER", "RETURN_RELABEL", "FIRST_LEG")) {
order.setOrderType(type); order.setSourceOrderNo(type + "-BUSINESS-NO");
List<String> numbers = ReflectionTestUtils.invokeMethod(service, "relatedBusinessOrderNos", application, order, List.of());
assertEquals(List.of(type + "-BUSINESS-NO"), numbers);
}
order.setOrderType("RELABEL_APPLICATION"); order.setSourceOrderNo("CUSTOMER-REFERENCE");
var first = new RelabelItem(); first.setSourceInboundOrderNo(" RT-SOURCE-1 ");
var duplicate = new RelabelItem(); duplicate.setSourceInboundOrderNo("RT-SOURCE-1");
var second = new RelabelItem(); second.setSourceInboundOrderNo("IN-SOURCE-2");
var bulkReturn = new RelabelItem(); bulkReturn.setOperationType("RETURN_BULK_SKU_LABEL"); bulkReturn.setShipmentNo("RT-SOURCE-3");
var shipment = new RelabelItem(); shipment.setOperationType("CARTON_LABEL"); shipment.setShipmentNo("FBA-SHIPMENT");
List<String> sources = ReflectionTestUtils.invokeMethod(service, "relatedBusinessOrderNos", application, order,
List.of(first, duplicate, second, bulkReturn, shipment));
assertEquals(List.of("RT-SOURCE-1", "IN-SOURCE-2", "RT-SOURCE-3"), sources);
List<String> missing = ReflectionTestUtils.invokeMethod(service, "relatedBusinessOrderNos", application, order, List.of(shipment));
assertEquals(List.of(), missing);
order.setOrderType("RETURN_RELABEL"); order.setCustomerId("OTHER"); order.setSourceOrderNo("RT-OTHER-CUSTOMER");
List<String> foreign = ReflectionTestUtils.invokeMethod(service, "relatedBusinessOrderNos", application, order, List.of());
assertEquals(List.of(), foreign);
}
@Test void summaryReturnsMilestonesFromCustomerScopedFacts() { @Test void summaryReturnsMilestonesFromCustomerScopedFacts() {
var application = new RelabelApplication(); var application = new RelabelApplication();
application.setId(42L); application.setCustomerId("10001"); application.setId(42L); application.setCustomerId("10001");