This commit is contained in:
2026-08-15 11:12:19 +08:00
parent 557ab75319
commit c4adba57db
22 changed files with 95 additions and 32 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
- 负责头程订单主数据、货物明细、快照、状态编排、幂等、Outbox 和内部货物查询。
- 订单交易状态归本模块;履约/入库状态归 `firstleg/`,仓储资源归 `warehouse/`,不得跨库读取。
- `tenant_id` 是客户隔离键;`customer_id` 是业务客户/往来单位快照,不能替代前者。
- `tenant_id` 是客户隔离键;`customer_id` 是客户/企业账号 ID,商户下单时固定来自认证上下文,不得指向 Warehouse 往来单位。发货单位、收货单位只保存为订单 Party 引用与业务快照。
## 模块入口
@@ -1,16 +0,0 @@
package com.baiyue.order.client;
import com.baiyue.common.core.api.ApiResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@FeignClient(name="warehouse-service", contextId="warehousePartnerClient",
url="${baiyue.clients.warehouse.url:}", path="/internal/warehouse-partners")
public interface PartnerClient {
@GetMapping("/{tenantId}/{id}/active")
ApiResponse<Partner> active(@RequestHeader("X-Internal-Service-Token") String token,
@PathVariable("tenantId") long tenantId, @PathVariable("id") long id);
record Partner(Long id, Long tenantId, String partnerName, String status,
String partnerType, List<String> types) { }
}
@@ -28,7 +28,8 @@ public final class OrderRequests {
@Schema(name = "FirstLegOrderSaveRequest", description = "First-leg order create or update request / 头程订单新增或更新请求")
public record SaveRequest(
@Schema(description = "Customer ID / 客户 ID", example = "30001") Long customerId,
@Schema(description = "Deprecated and ignored. Customer ID is always taken from authenticated enterprise context / 已废弃并忽略,客户 ID 固定取认证企业上下文", deprecated = true)
Long customerId,
@Schema(description = "Customer name / 客户名称", example = "Shenzhen Example Trading Co., Ltd. / 深圳示例贸易有限公司", maxLength = 128, requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank @Size(max = 128) String customerName,
@Schema(description = "Transport mode / 运输方式", example = "SEA", allowableValues = {"SEA", "AIR", "RAIL", "TRUCK"}, requiredMode = Schema.RequiredMode.REQUIRED)
@@ -590,7 +590,8 @@ components:
items: {$ref: '#/components/schemas/FirstLegOrderCargo'}
description: >-
订单保存请求中的完整字段以服务端 FirstLegOrderSaveRequest 为准;pricingTaxMode
是新建和编辑订单的必填报价维度;历史存量订单的响应字段仍允许为空。
是新建和编辑订单的必填报价维度;customerId 不接受客户端指定,服务端始终使用认证企业 ID;
发货单位和收货单位仅通过 sender/receiver 保存业务快照。历史存量订单的响应字段仍允许为空。
FirstLegBatchDraftItem:
type: object
required: [clientRowId, draft]
@@ -12,7 +12,6 @@ import static org.assertj.core.api.Assertions.assertThat;
class WarehouseFeignContractTest {
@Test void clientsUseNacosServiceNameAndInternalPathsByDefault() throws Exception {
assertClient(WarehouseClient.class, "/internal/warehouses");
assertClient(PartnerClient.class, "/internal/warehouse-partners");
}
private void assertClient(Class<?> type, String expectedPath) throws Exception {
@@ -363,7 +363,7 @@ class OrderApplicationServiceStateTest {
}
@Test
void publicDestinationCanBeSavedWithoutPartnerSenderOrReceiver() {
void publicDestinationUsesAuthenticatedEnterpriseAsCustomerWithoutPartySnapshots() {
OrderRepository repository = mock(OrderRepository.class);
OrderEligibilityGuard eligibility = mock(OrderEligibilityGuard.class);
OrderMasterDataGuard masterData = mock(OrderMasterDataGuard.class);
@@ -374,7 +374,7 @@ class OrderApplicationServiceStateTest {
service(repository, eligibility, masterData)
.createDraft(20002L, 2L, request, "public-destination-no-parties");
verify(repository).insertOrder(argThat(order -> order.getCustomerId() == null
verify(repository).insertOrder(argThat(order -> Long.valueOf(20002L).equals(order.getCustomerId())
&& "当前企业".equals(order.getCustomerName())));
verify(repository, never()).insertParty(any());
}
@@ -75,7 +75,7 @@ class OrderMasterDataGuardTest {
"CN", null, "深圳", null, "地址", null);
var cargo = new OrderRequests.Cargo("货物", null, "CARTON", 1, BigDecimal.ONE, BigDecimal.ONE,
null, null, null, null, null, false, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, null, null, null);
return new OrderRequests.SaveRequest(null, "当前企业", "SEA", null, "CN", destinationWarehouseId,
"目的仓", null, null, party, party, List.of(cargo), "PICKUP", receivingWarehouseId,
"收货仓", "CH", "渠道", null, null, "BUY_DECLARATION", null, "LCL", false,