# Order Service 模块指引 ## 职责边界 - 负责头程订单主数据、草稿、提交、平台处理状态、货物、参与方快照、状态历史、内部备注和 Outbox。 - 履约作业与分配属于 `firstleg/`;仓库和往来单位主数据属于 `warehouse/`;订单只保存必要业务快照。 ## 功能快速索引 | 功能 | 入口 | |---|---| | 商户订单创建、编辑、列表、详情、提交、取消 | `controller/MerchantFirstLegOrderController.java`;列表校验 `merchant:order:list`,详情校验 `merchant:order:view` | | 平台订单列表、详情、审核、接单、开始、完成、取消 | `controller/PlatformFirstLegOrderController.java`;列表和详情校验 `platform:order:list` | | 平台批量客户运单数 | `PlatformFirstLegOrderController.java` 的 `GET /tenant-counts`、`service/OrderApplicationService.countByTenantIds`、`repository/OrderRepository.countByTenantIds`、`dto/TenantOrderCountResponse.java` | | Firstleg 查询订单货物明细 | `controller/InternalOrderCargoController.java`(`GET /internal/order/v1/cargoes/{tenantId}/{orderId}/{cargoId}`)→ `repository/OrderRepository.findCargo`;契约测试 `controller/InternalOrderCargoControllerTest.java` | | 内部备注与快递信息 | `PlatformFirstLegOrderController.java` | | 核心编排与状态机 | `service/OrderApplicationService.java`、`entity/OrderStatus.java` | | 企业下单资格 | `service/OrderEligibilityGuard.java`、`client/TenantEligibilityClient.java` | | 仓库/往来单位有效性 | `service/OrderMasterDataGuard.java`、`client/WarehouseClient.java`、`PartnerClient.java`;往来单位响应同时包含多值 `types` 与兼容字段 `partnerType` | | 客户归属与访问范围 | `service/OrderScopeGuard.java`;类内 `tenant` 命名为历史兼容 | | 请求与详情响应 | `dto/OrderRequests.java`、`OrderDetailResponse.java` | | 主单、货物、参与方、历史、备注、Outbox、幂等记录 | `entity/`、`mapper/`、`repository/OrderRepository.java` | | 表结构与一期扩展 | `src/main/resources/db/order.sql`、`phase1-masterdata-extension.sql`、`phase1-order-extension.sql` | | 模块说明 | `README-ORDER.md` | | 状态、主数据与接口权限测试 | `src/test/java/com/baiyue/order/service/`、`src/test/java/com/baiyue/order/controller/` | ## 修改与验证 - 所有商户查询和写入必须执行客户归属/访问范围校验;业务表 `tenant_id` 当前承载客户 ID。平台操作必须验证平台技术作用域、目标客户、权限及合法状态迁移。 - 查询接口同样必须校验权限码;沿用 IAM 已初始化的权限资源,新增权限码时同步补充 IAM 初始化脚本与角色授权。 - 已提交订单中的仓库、往来单位等快照不能随主数据修改而变化。 - 客户列表中的真实运单数归 Order,不得写回 IAM。历史接口 `GET /api/platform/v1/orders/first-leg/tenant-counts?tenantIds=...` 仅允许平台 `platform:order:list`,一次接收 1 至 200 个有效客户 ID,并对没有订单的客户返回 0;路径和参数名保持兼容。 - Warehouse 往来单位已支持多类型;下单校验优先使用 `PartnerClient.Partner.types`,`partnerType` 只作为旧数据兼容。类型语义变化需同步 Warehouse 的 `wh_partner_type`、Order 客户端契约与快照测试。 - 往来单位是平台统一维护、供所有客户共享的公共主数据,Order 调用 Warehouse 内部接口时固定使用公共作用域 `tenant_id=0`;订单自己的 `tenant_id` 仍是客户隔离键,不能拿来查询往来单位。 - 跨服务只通过 `client/` 或事件演进,不跨库查询 IAM/Warehouse;跨域通知优先使用 Outbox。 - 二期第三方测量绑定订单货物时,Firstleg 只能通过 `InternalOrderCargoController` 校验 `tenantId + orderId + cargoId` 并读取必要快照;该接口必须保留内部令牌校验,不能暴露到 Gateway,也不能返回 Order Entity。 - Order 到 Warehouse 的内部调用使用 Nacos 服务名 `warehouse-service`,不经过 Gateway;只有隔离端口回归显式设置 `WAREHOUSE_SERVICE_URL`。内部接口返回 403 时应将外部响应规范化为 `S0503`,并提示核对内部服务凭证,禁止输出真实令牌。 - 新增状态或动作时同步修改 Controller、Service 状态机、历史记录、DTO、SQL、前端消费者和测试。 - 创建草稿和提交订单必须接收 `Idempotency-Key`;幂等范围按客户、操作者和操作隔离,请求指纹包含资源,并由数据库唯一键保证并发安全。 - 订单创建会落库收货仓地址、收货时间和主数据名称快照;既有库必须执行 `phase1-order-extension.sql`,否则实体字段与表结构漂移会在草稿落库时产生 HTTP 200 + `S0500`,真实原因只记录在服务日志。 - 从父目录运行 `mvn -pl order -am test`,再运行 `scripts/order-warehouse-real-api-regression.ps1` 或对应一期回归。 - 普通业务失败使用 HTTP 200 + body code;Feign 收到 HTTP 非 200 代表鉴权、协议或基础设施异常,应归一为 `S0503`,不能用 Feign 状态码推断 404/409 业务语义。 ## 平台代客接口补充 - `POST /api/platform/v1/orders/first-leg?tenantId={tenantId}`:平台代客创建草稿,校验 `platform:order:create`,必须携带 `Idempotency-Key`。 - `PUT /api/platform/v1/orders/first-leg/{id}?tenantId={tenantId}`:平台编辑草稿,校验 `platform:order:edit`。 - `POST /api/platform/v1/orders/first-leg/{id}/submit?tenantId={tenantId}`:平台代客提交订单,校验 `platform:order:submit`,必须携带 `Idempotency-Key`。 - `src/main/resources/openapi/order-v1.yaml` 是静态 OpenAPI 入口;`ord_idempotency_record` 以客户隔离兼容字段、操作人、操作和幂等键建立唯一约束。 - 数据库执行顺序:新库先执行 `order.sql`,已有库执行 `phase1-order-extension.sql`;后者包含幂等表创建,必须在部署订单写接口前完成。