fix: reserve stable inbound code for draft label printing

This commit is contained in:
2026-09-08 17:33:44 +08:00
parent eead11e99d
commit 60a41ec3ea
10 changed files with 289 additions and 3 deletions
@@ -0,0 +1,18 @@
package com.baiyue.firstleg.client;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
@FeignClient(name = "order-service", contextId = "printableOrderInboundClient",
url = "${baiyue.clients.order.url:}", path = "/internal/order/v1/cargoes")
public interface PrintableOrderInboundClient {
@PostMapping("/{tenantId}/{orderId}/printable-inbound-snapshot")
ApiResponse<OrderApprovedInboundCommand> reserve(
@RequestHeader("X-Internal-Service-Token") String token,
@PathVariable long tenantId,
@PathVariable long orderId);
}
@@ -5,6 +5,7 @@ import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.ResultCode; import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.exception.BizException; import com.baiyue.common.core.exception.BizException;
import com.baiyue.firstleg.client.OrderCargoClient; import com.baiyue.firstleg.client.OrderCargoClient;
import com.baiyue.firstleg.client.PrintableOrderInboundClient;
import com.baiyue.firstleg.dto.InboundCartonLabels; import com.baiyue.firstleg.dto.InboundCartonLabels;
import com.baiyue.firstleg.entity.InboundCartonLabelEntity; import com.baiyue.firstleg.entity.InboundCartonLabelEntity;
import com.baiyue.firstleg.entity.InboundOrderEntity; import com.baiyue.firstleg.entity.InboundOrderEntity;
@@ -35,6 +36,7 @@ public class InboundCartonLabelService implements CartonLabelBindingResolver {
@Resource private InboundCartonLabelRepository repository; @Resource private InboundCartonLabelRepository repository;
@Resource private OrderCargoClient orderCargoClient; @Resource private OrderCargoClient orderCargoClient;
@Resource private PrintableOrderInboundClient printableOrderInboundClient;
@Resource private InboundOrderCreationService inboundOrderCreationService; @Resource private InboundOrderCreationService inboundOrderCreationService;
@Value("${baiyue.security.internal-service-token}") private String internalToken; @Value("${baiyue.security.internal-service-token}") private String internalToken;
@@ -101,7 +103,7 @@ public class InboundCartonLabelService implements CartonLabelBindingResolver {
private InboundOrderEntity prepareMissingInbound(long tenantId, long orderId) { private InboundOrderEntity prepareMissingInbound(long tenantId, long orderId) {
try { try {
ApiResponse<com.baiyue.firstleg.dto.OrderApprovedInboundCommand> response = ApiResponse<com.baiyue.firstleg.dto.OrderApprovedInboundCommand> response =
orderCargoClient.inboundSnapshot(internalToken, tenantId, orderId); printableOrderInboundClient.reserve(internalToken, tenantId, orderId);
if (response == null || !response.successful() || response.data() == null) { if (response == null || !response.successful() || response.data() == null) {
throw new BizException(ResultCode.NOT_FOUND, "订单不存在或无法生成预入库单"); throw new BizException(ResultCode.NOT_FOUND, "订单不存在或无法生成预入库单");
} }
@@ -3,6 +3,7 @@ package com.baiyue.firstleg.service;
import com.baiyue.common.core.api.ApiResponse; import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.exception.BizException; import com.baiyue.common.core.exception.BizException;
import com.baiyue.firstleg.client.OrderCargoClient; import com.baiyue.firstleg.client.OrderCargoClient;
import com.baiyue.firstleg.client.PrintableOrderInboundClient;
import com.baiyue.firstleg.entity.InboundCartonLabelEntity; import com.baiyue.firstleg.entity.InboundCartonLabelEntity;
import com.baiyue.firstleg.entity.InboundOrderEntity; import com.baiyue.firstleg.entity.InboundOrderEntity;
import com.baiyue.firstleg.repository.InboundCartonLabelRepository; import com.baiyue.firstleg.repository.InboundCartonLabelRepository;
@@ -28,6 +29,7 @@ import static org.mockito.Mockito.when;
class InboundCartonLabelServiceTest { class InboundCartonLabelServiceTest {
@Mock private InboundCartonLabelRepository repository; @Mock private InboundCartonLabelRepository repository;
@Mock private OrderCargoClient orderCargoClient; @Mock private OrderCargoClient orderCargoClient;
@Mock private PrintableOrderInboundClient printableOrderInboundClient;
@Mock private InboundOrderCreationService inboundOrderCreationService; @Mock private InboundOrderCreationService inboundOrderCreationService;
private InboundCartonLabelService service; private InboundCartonLabelService service;
@@ -36,6 +38,7 @@ class InboundCartonLabelServiceTest {
service = new InboundCartonLabelService(); service = new InboundCartonLabelService();
ReflectionTestUtils.setField(service, "repository", repository); ReflectionTestUtils.setField(service, "repository", repository);
ReflectionTestUtils.setField(service, "orderCargoClient", orderCargoClient); ReflectionTestUtils.setField(service, "orderCargoClient", orderCargoClient);
ReflectionTestUtils.setField(service, "printableOrderInboundClient", printableOrderInboundClient);
ReflectionTestUtils.setField(service, "inboundOrderCreationService", inboundOrderCreationService); ReflectionTestUtils.setField(service, "inboundOrderCreationService", inboundOrderCreationService);
ReflectionTestUtils.setField(service, "internalToken", "internal-token"); ReflectionTestUtils.setField(service, "internalToken", "internal-token");
} }
@@ -222,7 +225,7 @@ class InboundCartonLabelServiceTest {
@Test @Test
void rejectsAnOrderWithoutAnOwnedPreparingInbound() { void rejectsAnOrderWithoutAnOwnedPreparingInbound() {
when(repository.findByOrder(10001L, 60001L)).thenReturn(null); when(repository.findByOrder(10001L, 60001L)).thenReturn(null);
when(orderCargoClient.inboundSnapshot("internal-token", 10001L, 60001L)) when(printableOrderInboundClient.reserve("internal-token", 10001L, 60001L))
.thenThrow(org.mockito.Mockito.mock(feign.FeignException.class)); .thenThrow(org.mockito.Mockito.mock(feign.FeignException.class));
assertThatThrownBy(() -> service.requireInboundIdByOrder(10001L, 60001L)) assertThatThrownBy(() -> service.requireInboundIdByOrder(10001L, 60001L))
@@ -239,7 +242,7 @@ class InboundCartonLabelServiceTest {
null, null, null, 2); null, null, null, 2);
InboundOrderEntity repaired = inbound(); InboundOrderEntity repaired = inbound();
when(repository.findByOrder(10001L, 60001L)).thenReturn(null, repaired); when(repository.findByOrder(10001L, 60001L)).thenReturn(null, repaired);
when(orderCargoClient.inboundSnapshot("internal-token", 10001L, 60001L)) when(printableOrderInboundClient.reserve("internal-token", 10001L, 60001L))
.thenReturn(ApiResponse.success(snapshot)); .thenReturn(ApiResponse.success(snapshot));
assertThat(service.requireInboundIdByOrder(10001L, 60001L)).isEqualTo(70001L); assertThat(service.requireInboundIdByOrder(10001L, 60001L)).isEqualTo(70001L);
@@ -9,10 +9,12 @@ import com.baiyue.common.core.exception.BizException;
import com.baiyue.order.entity.OrderCargoEntity; import com.baiyue.order.entity.OrderCargoEntity;
import com.baiyue.order.repository.OrderRepository; import com.baiyue.order.repository.OrderRepository;
import com.baiyue.order.service.OrderApplicationService; import com.baiyue.order.service.OrderApplicationService;
import com.baiyue.order.service.PrintableInboundSnapshotService;
import com.baiyue.order.client.FirstlegInboundClient; import com.baiyue.order.client.FirstlegInboundClient;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -29,6 +31,7 @@ import java.util.stream.Collectors;
@RequestMapping("/internal/order/v1/cargoes") @RequestMapping("/internal/order/v1/cargoes")
public class InternalOrderCargoController { public class InternalOrderCargoController {
@Resource private OrderRepository orders; @Resource private OrderRepository orders;
@Resource private PrintableInboundSnapshotService printableInboundSnapshots;
@Value("${baiyue.security.internal-service-token}") private String internalToken; @Value("${baiyue.security.internal-service-token}") private String internalToken;
private byte[] expectedToken; private byte[] expectedToken;
@@ -98,6 +101,18 @@ public class InternalOrderCargoController {
return ApiResponse.success(OrderApplicationService.inboundCommand(order, packageCount)); return ApiResponse.success(OrderApplicationService.inboundCommand(order, packageCount));
} }
@PostMapping("/{tenantId}/{orderId}/printable-inbound-snapshot")
public ApiResponse<FirstlegInboundClient.OrderApprovedInboundCommand> printableInboundSnapshot(
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
@PathVariable long tenantId,
@PathVariable long orderId) {
requireToken(token);
if (tenantId <= 0 || orderId <= 0) {
throw new BizException(ResultCode.BAD_REQUEST, "租户和订单ID必须大于0");
}
return ApiResponse.success(printableInboundSnapshots.reserve(tenantId, orderId));
}
@GetMapping("/{tenantId}/{orderId}/measurement-declaration") @GetMapping("/{tenantId}/{orderId}/measurement-declaration")
public ApiResponse<MeasurementDeclarationSnapshot> measurementDeclaration( public ApiResponse<MeasurementDeclarationSnapshot> measurementDeclaration(
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token, @RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
@@ -54,6 +54,17 @@ public class OrderRepository {
.eq(OrderEntity::getId, order.getId()) .eq(OrderEntity::getId, order.getId())
.eq(OrderEntity::getTenantId, tenantId)); .eq(OrderEntity::getTenantId, tenantId));
} }
public int assignInboundCodeIfBlank(long tenantId, long orderId, String inboundCode) {
return orderMapper.update(null, new LambdaUpdateWrapper<OrderEntity>()
.eq(OrderEntity::getTenantId, tenantId)
.eq(OrderEntity::getId, orderId)
.eq(OrderEntity::getDeleted, false)
.and(wrapper -> wrapper.isNull(OrderEntity::getInboundCode)
.or().eq(OrderEntity::getInboundCode, ""))
.set(OrderEntity::getInboundCode, inboundCode)
.set(OrderEntity::getUpdatedAt, LocalDateTime.now())
.setSql("version = version + 1"));
}
public int updateDeclarationHeader(long tenantId, long orderId, int expectedVersion, long operatorId, public int updateDeclarationHeader(long tenantId, long orderId, int expectedVersion, long operatorId,
String customerRemark, LocalDateTime expectedArrivalAt, String customerRemark, LocalDateTime expectedArrivalAt,
java.math.BigDecimal estimatedVolumeCbm, java.math.BigDecimal estimatedVolumeCbm,
@@ -0,0 +1,64 @@
package com.baiyue.order.service;
import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.order.client.FirstlegInboundClient;
import com.baiyue.order.config.InboundCodeModeProvider;
import com.baiyue.order.entity.OrderCargoEntity;
import com.baiyue.order.entity.OrderEntity;
import com.baiyue.order.repository.OrderRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
/** 为草稿箱唛打印预留稳定入仓码;订单提交时继续复用该码。 */
@Service
public class PrintableInboundSnapshotService {
private final OrderRepository orders;
private final OrderPricingChannelGuard pricingChannels;
private final InboundCodeModeProvider inboundCodeMode;
private final OrderApplicationService orderApplication;
public PrintableInboundSnapshotService(OrderRepository orders,
OrderPricingChannelGuard pricingChannels,
InboundCodeModeProvider inboundCodeMode,
OrderApplicationService orderApplication) {
this.orders = orders;
this.pricingChannels = pricingChannels;
this.inboundCodeMode = inboundCodeMode;
this.orderApplication = orderApplication;
}
@Transactional
public FirstlegInboundClient.OrderApprovedInboundCommand reserve(long tenantId, long orderId) {
OrderEntity order = requireOwned(tenantId, orderId);
if (!StringUtils.hasText(order.getInboundCode())) {
if (inboundCodeMode.legacyManual()) {
throw new BizException(ResultCode.VALIDATION_FAILED, "当前系统使用旧系统入仓码,请先填写入仓码");
}
String prefix = pricingChannels.requireAvailable(tenantId, order.getReceivingWarehouseId(),
order.getChannelCode(), order.getDestinationType());
String allocated = orderApplication.nextInboundCode(prefix);
if (orders.assignInboundCodeIfBlank(tenantId, orderId, allocated) == 1) {
order.setInboundCode(allocated);
} else {
order = requireOwned(tenantId, orderId);
if (!StringUtils.hasText(order.getInboundCode())) {
throw new BizException(ResultCode.CONFLICT, "入仓码预留冲突,请刷新后重试");
}
}
}
int packageCount = orders.findCargoInheritedByOrder(tenantId, orderId).stream()
.map(OrderCargoEntity::getPackageCount).filter(java.util.Objects::nonNull)
.mapToInt(Integer::intValue).sum();
return OrderApplicationService.inboundCommand(order, packageCount);
}
private OrderEntity requireOwned(long tenantId, long orderId) {
OrderEntity order = orders.findOwned(tenantId, orderId);
if (order == null) {
throw new BizException(ResultCode.NOT_FOUND, "订单不存在或不属于当前客户");
}
return order;
}
}
@@ -28,6 +28,23 @@ paths:
application/json: application/json:
schema: {$ref: '#/components/schemas/CargoLabelBindingListEnvelope'} schema: {$ref: '#/components/schemas/CargoLabelBindingListEnvelope'}
'403': {description: 内部服务令牌无效} '403': {description: 内部服务令牌无效}
/internal/order/v1/cargoes/{tenantId}/{orderId}/printable-inbound-snapshot:
post:
security: []
summary: 为 Firstleg 箱唛打印读取并预留稳定入仓快照
description: >-
仅接受内部服务令牌。若 AUTO 模式草稿尚无入仓码,则按订单渠道原子预留全局唯一入仓码;
并发重放返回已胜出的同一码,后续订单提交继续复用,避免已打印二维码失效。
parameters:
- name: X-Internal-Service-Token
in: header
required: true
schema: {type: string}
- {name: tenantId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: orderId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 返回带稳定入仓码及总箱数的订单快照}
'403': {description: 内部服务令牌无效}
/internal/order/v1/pending-review-orders: /internal/order/v1/pending-review-orders:
get: get:
security: [] security: []
@@ -5,6 +5,8 @@ import com.baiyue.order.entity.OrderCargoEntity;
import com.baiyue.order.entity.OrderEntity; import com.baiyue.order.entity.OrderEntity;
import com.baiyue.order.entity.OrderInternalNoteEntity; import com.baiyue.order.entity.OrderInternalNoteEntity;
import com.baiyue.order.repository.OrderRepository; import com.baiyue.order.repository.OrderRepository;
import com.baiyue.order.service.OrderApplicationService;
import com.baiyue.order.service.PrintableInboundSnapshotService;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
@@ -23,11 +25,13 @@ import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@SpringJUnitConfig(InternalOrderCargoController.class) @SpringJUnitConfig(InternalOrderCargoController.class)
@TestPropertySource(properties = "baiyue.security.internal-service-token=internal-token") @TestPropertySource(properties = "baiyue.security.internal-service-token=internal-token")
class InternalOrderCargoControllerTest { class InternalOrderCargoControllerTest {
@MockBean private OrderRepository orders; @MockBean private OrderRepository orders;
@MockBean private PrintableInboundSnapshotService printableInboundSnapshots;
@Resource private InternalOrderCargoController controller; @Resource private InternalOrderCargoController controller;
@Test @Test
@@ -145,6 +149,24 @@ class InternalOrderCargoControllerTest {
verify(orders).findOwned(11L, 21L); verify(orders).findOwned(11L, 21L);
} }
@Test
void reservesPrintableSnapshotThroughExplicitCommandRoute() throws Exception {
OrderEntity order = new OrderEntity();
order.setTenantId(11L); order.setId(21L); order.setDestinationType("FBA");
order.setTransportMode("SEA");
var snapshot = OrderApplicationService.inboundCommand(order, 3);
when(printableInboundSnapshots.reserve(11L, 21L)).thenReturn(snapshot);
var response = controller.printableInboundSnapshot("internal-token", 11L, 21L);
assertThat(response.data()).isSameAs(snapshot);
verify(printableInboundSnapshots).reserve(11L, 21L);
Method route = InternalOrderCargoController.class.getMethod(
"printableInboundSnapshot", String.class, long.class, long.class);
assertThat(route.getAnnotation(PostMapping.class).value())
.containsExactly("/{tenantId}/{orderId}/printable-inbound-snapshot");
}
@Test @Test
void measurementDeclarationUsesOrderReferenceAndSumsCargoFacts() { void measurementDeclarationUsesOrderReferenceAndSumsCargoFacts() {
OrderEntity order = new OrderEntity(); OrderEntity order = new OrderEntity();
@@ -0,0 +1,21 @@
package com.baiyue.order.controller;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import static org.assertj.core.api.Assertions.assertThat;
class PrintableInboundSnapshotOpenApiContractTest {
@Test
void documentsTheMutatingInternalCommandAsPost() throws Exception {
try (var stream = getClass().getResourceAsStream("/openapi/order-v1.yaml")) {
assertThat(stream).isNotNull();
String yaml = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
assertThat(yaml).contains(
"/internal/order/v1/cargoes/{tenantId}/{orderId}/printable-inbound-snapshot:",
"若 AUTO 模式草稿尚无入仓码,则按订单渠道原子预留全局唯一入仓码",
"后续订单提交继续复用");
}
}
}
@@ -0,0 +1,113 @@
package com.baiyue.order.service;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.order.config.InboundCodeModeProvider;
import com.baiyue.order.entity.OrderCargoEntity;
import com.baiyue.order.entity.OrderEntity;
import com.baiyue.order.repository.OrderRepository;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class PrintableInboundSnapshotServiceTest {
@Test
void reservesStableCodeForDraftAndReturnsPrintableSnapshot() {
OrderRepository orders = mock(OrderRepository.class);
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
OrderApplicationService application = mock(OrderApplicationService.class);
OrderEntity order = draft();
OrderCargoEntity cargo = new OrderCargoEntity();
cargo.setPackageCount(3);
when(orders.findOwned(11L, 21L)).thenReturn(order);
when(pricing.requireAvailable(11L, 41L, "CH", "FBA")).thenReturn("PCHK");
when(application.nextInboundCode("PCHK")).thenReturn("PCHK2609080001");
when(orders.assignInboundCodeIfBlank(11L, 21L, "PCHK2609080001")).thenReturn(1);
when(orders.findCargoInheritedByOrder(11L, 21L)).thenReturn(List.of(cargo));
var result = service(orders, pricing, application, "AUTO").reserve(11L, 21L);
assertThat(result.inboundCode()).isEqualTo("PCHK2609080001");
assertThat(result.totalPackageCount()).isEqualTo(3);
verify(orders).assignInboundCodeIfBlank(11L, 21L, "PCHK2609080001");
}
@Test
void reusesCodeAlreadyReservedByAConcurrentRequest() {
OrderRepository orders = mock(OrderRepository.class);
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
OrderApplicationService application = mock(OrderApplicationService.class);
OrderEntity initial = draft();
OrderEntity winner = draft();
winner.setInboundCode("PCHK2609080002");
when(orders.findOwned(11L, 21L)).thenReturn(initial, winner);
when(pricing.requireAvailable(11L, 41L, "CH", "FBA")).thenReturn("PCHK");
when(application.nextInboundCode("PCHK")).thenReturn("PCHK2609080001");
when(orders.assignInboundCodeIfBlank(11L, 21L, "PCHK2609080001")).thenReturn(0);
when(orders.findCargoInheritedByOrder(11L, 21L)).thenReturn(List.of());
var result = service(orders, pricing, application, "AUTO").reserve(11L, 21L);
assertThat(result.inboundCode()).isEqualTo("PCHK2609080002");
}
@Test
void existingCodeDoesNotAllocateAnotherSequence() {
OrderRepository orders = mock(OrderRepository.class);
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
OrderApplicationService application = mock(OrderApplicationService.class);
OrderEntity order = draft();
order.setInboundCode("PCHK2609080001");
when(orders.findOwned(11L, 21L)).thenReturn(order);
when(orders.findCargoInheritedByOrder(11L, 21L)).thenReturn(List.of());
var result = service(orders, pricing, application, "AUTO").reserve(11L, 21L);
assertThat(result.inboundCode()).isEqualTo("PCHK2609080001");
verify(application, never()).nextInboundCode(org.mockito.ArgumentMatchers.anyString());
}
@Test
void legacyManualModeRejectsMissingCodeWithoutWriting() {
OrderRepository orders = mock(OrderRepository.class);
OrderPricingChannelGuard pricing = mock(OrderPricingChannelGuard.class);
OrderApplicationService application = mock(OrderApplicationService.class);
when(orders.findOwned(11L, 21L)).thenReturn(draft());
assertThatThrownBy(() -> service(orders, pricing, application, "LEGACY_MANUAL").reserve(11L, 21L))
.isInstanceOf(BizException.class)
.hasMessage("当前系统使用旧系统入仓码,请先填写入仓码");
verify(orders, never()).assignInboundCodeIfBlank(
org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong(),
org.mockito.ArgumentMatchers.anyString());
}
private PrintableInboundSnapshotService service(OrderRepository orders,
OrderPricingChannelGuard pricing,
OrderApplicationService application,
String mode) {
return new PrintableInboundSnapshotService(
orders, pricing, new InboundCodeModeProvider(mode), application);
}
private OrderEntity draft() {
OrderEntity order = new OrderEntity();
order.setId(21L);
order.setTenantId(11L);
order.setOrderNo("FL21");
order.setCustomerId(11L);
order.setReceivingWarehouseId(41L);
order.setChannelCode("CH");
order.setDestinationType("FBA");
order.setTransportMode("SEA");
order.setFulfillmentType("STANDARD");
return order;
}
}