feat(order): accept optional courier tracking on customer drafts

This commit is contained in:
2026-10-19 17:39:54 +08:00
parent a563f63857
commit 5368da03d8
6 changed files with 84 additions and 6 deletions
@@ -81,7 +81,9 @@ public final class OrderRequests {
@Schema(description = "Selected customer pickup address ID; required for PICKUP / 已选客户取货地址 ID;PICKUP 时必填")
@Min(1) Long senderAddressId,
@Schema(description = "Selected private destination address ID; required for PRIVATE / 已选私人目的仓地址 ID;PRIVATE 时必填")
@Min(1) Long privateDestinationAddressId
@Min(1) Long privateDestinationAddressId,
@Schema(description = "Optional customer courier tracking number for SELF_EXPRESS / 快递自提选填快递单号;其他取货方式不保存", maxLength = 128)
@Size(max = 128) String expressTrackingNo
) {
public SaveRequest(Long customerId, String customerName, String transportMode, String tradeTerm,
String destinationCountryCode, Long destinationWarehouseId,
@@ -98,7 +100,7 @@ public final class OrderRequests {
sender, receiver, cargoes, pickupMethod, requestedPickupAt, receivingWarehouseId,
receivingWarehouseName, channelCode, channelName, carrierId, carrierName, taxMode,
pricingTaxMode, containerMode, customsInspection, destinationType, amazonWarehouseCode,
shipmentId, referenceId, inboundCode, fulfillmentType, null, null, null);
shipmentId, referenceId, inboundCode, fulfillmentType, null, null, null, null);
}
public SaveRequest(Long customerId, String customerName, String transportMode, String tradeTerm,
@@ -116,7 +118,7 @@ public final class OrderRequests {
sender, receiver, cargoes, pickupMethod, requestedPickupAt, receivingWarehouseId,
receivingWarehouseName, channelCode, channelName, carrierId, carrierName, taxMode,
pricingTaxMode, containerMode, customsInspection, destinationType, amazonWarehouseCode,
shipmentId, referenceId, inboundCode, null, null, null, null);
shipmentId, referenceId, inboundCode, null, null, null, null, null);
}
public SaveRequest(Long customerId, String customerName, String transportMode, String tradeTerm,
@@ -133,7 +135,7 @@ public final class OrderRequests {
sender, receiver, cargoes, pickupMethod, requestedPickupAt, receivingWarehouseId,
receivingWarehouseName, channelCode, channelName, carrierId, carrierName, taxMode,
pricingTaxMode, containerMode, customsInspection, destinationType, amazonWarehouseCode,
shipmentId, referenceId, null, null, null, null, null);
shipmentId, referenceId, null, null, null, null, null, null);
}
public SaveRequest(Long customerId, String customerName, String transportMode, String tradeTerm,
@@ -150,7 +152,7 @@ public final class OrderRequests {
sender, receiver, cargoes, pickupMethod, null, receivingWarehouseId,
receivingWarehouseName, channelCode, channelName, carrierId, carrierName, taxMode,
pricingTaxMode, containerMode, customsInspection, destinationType, amazonWarehouseCode,
shipmentId, referenceId, null, null, null, null, null);
shipmentId, referenceId, null, null, null, null, null, null);
}
@AssertTrue(message = "承运商 ID 和名称必须同时填写或同时留空")
@@ -642,6 +642,7 @@ public class OrderApplicationService {
default -> false;
};
}
// 保存客户下单资料;快递单号仅属于快递自提,切换方式时清空避免误带。
private void apply(OrderEntity order, long tenantId, OrderRequests.SaveRequest request,
OrderMasterDataGuard.Snapshots snapshots, AddressSnapshots addresses,
boolean allowLegacyInboundCode) {
@@ -662,6 +663,10 @@ public class OrderApplicationService {
order.setExpectedArrivalAt(request.expectedShipDate() == null ? null : request.expectedShipDate().atStartOfDay());
order.setCustomerRemark(request.customerRemark());
order.setPickupMethod(request.pickupMethod());
if (order.getStatus() == OrderStatus.DRAFT || order.getStatus() == OrderStatus.REJECTED) {
order.setExpressTrackingNo("SELF_EXPRESS".equals(request.pickupMethod())
? normalizeRemark(request.expressTrackingNo()) : null);
}
order.setRequestedPickupAt("PICKUP".equals(request.pickupMethod()) ? request.requestedPickupAt() : null);
order.setReceivingWarehouseId(request.receivingWarehouseId());
order.setReceivingWarehouseName(snapshots.receiving().warehouse().warehouseName());
@@ -162,7 +162,7 @@ public class PlatformLegacyOrderImportService {
"买单".equals(required(row, 5, "买单/退税")) ? "BUY_DECLARATION" : "TAX_REFUND",
channel.channelName().contains("包税") && !channel.channelName().contains("不包税") ? "TAX_INCLUDED" : "TAX_EXCLUDED",
"LCL", false, destinationType, amazonCode, shipmentId, referenceId, inboundCode, fulfillmentType,
"ONE_CLICK_DROPSHIP".equals(fulfillmentType) ? referenceId : null, null, null);
"ONE_CLICK_DROPSHIP".equals(fulfillmentType) ? referenceId : null, null, null, null);
}
private Customer fixedCustomer() {
@@ -1451,6 +1451,7 @@ components:
pricingTaxMode: {$ref: '#/components/schemas/PricingTaxMode'}
senderAddressId: {type: string, pattern: '^[1-9][0-9]*$', description: PICKUP 时必填;必须是本客户 PICKUP 地址}
privateDestinationAddressId: {type: string, pattern: '^[1-9][0-9]*$', description: PRIVATE 时必填;必须是本客户 PRIVATE_DESTINATION 地址}
expressTrackingNo: {type: string, nullable: true, maxLength: 128, description: 快递自提(SELF_EXPRESS)时选填;留空清空单号,其他取货方式不保存。客户仅能在下单或编辑草稿时填写}
customsInspection: {type: boolean, nullable: true, description: 非木制品可空;任一货物 woodenProduct=true 时必须为 true}
cargoes:
type: array