新增仓储模块页面与 API、店铺授权/店铺订单页面及路由权限目录; 扩展菜单管理同步能力支持二级子菜单与三级按钮;优化公告、仓库地址、下单等页面。 Co-authored-by: Cursor <cursoragent@cursor.com>
603 lines
21 KiB
Markdown
603 lines
21 KiB
Markdown
# 订单全链路自动化测试方案
|
||
|
||
> **版本**:v1.0
|
||
> **日期**:2026-07-08
|
||
> **适用范围**:OMS 订单从创建 → 预报 → 入库 → 支付 → 出库 → 轨迹 → 签收(设计态)
|
||
> **关联文档**:`oms系统设计-050801.md` §4、§6、§10.3;`物流下单协议.md`;`订单批量处理与异步队列方案0707.md`
|
||
|
||
---
|
||
|
||
## 1. 目标与范围
|
||
|
||
### 1.1 目标
|
||
|
||
建立一套**可重复执行、可接入 CI** 的自动化测试流程,覆盖订单主 happy path:
|
||
|
||
```
|
||
下单预报 → 入库收货 → 客户支付 → 出库发货 → 轨迹同步 → 签收完成
|
||
```
|
||
|
||
并验证各阶段:
|
||
|
||
- **订单状态**(`OrderStatus`)与时间字段(`ReceiveTime` / `PayTime` / `ShipTime` / `SignTime`)
|
||
- **费用**(预报 / 入库 / 出库阶段 `t_order_fee`)
|
||
- **客户余额与流水**(`t_customer.Balance`、`t_customer_account_flow`)
|
||
- **仓储操作记录**(`t_inbound_record` / `t_outbound_record`)
|
||
- **轨迹服务联动**(UpsertSmallBag,可 mock)
|
||
- **权限与数据范围**(客户只能看到自己的订单)
|
||
|
||
### 1.2 当前实现边界(必读)
|
||
|
||
| 阶段 | 状态码 | 后端是否已实现 | 自动化策略 |
|
||
|------|--------|----------------|------------|
|
||
| 小包创建 + 预报计费 | `predeclared` | ✅ | API 断言 |
|
||
| 入库扫描 | `pendingPayment` | ✅ | API 断言 |
|
||
| 支付 | `pendingShip` | ✅ | API + 余额断言 |
|
||
| 出库扫描 | `pendingOnline` | ✅ | API 断言 |
|
||
| 运输中 | `shipping` | ❌ 无写入逻辑 | **Phase 2**:mock 轨迹回调或手工 DB 置态 |
|
||
| 派送成功(签收) | `deliverySuccess` + `SignTime` | ❌ 无写入逻辑 | **Phase 2**:同上;或 Track 服务 `UpdateOrderStatus` |
|
||
| 问题件 / 理赔件 | `problematic` / `claimed` | ✅ | 分支用例 |
|
||
|
||
> **结论**:Phase 1 自动化覆盖到 **`pendingOnline`(待上网)** 为「OMS 内闭环」;签收段在 OMS 回写接口落地前,用 **Track 侧断言 + 预留 OMS 状态同步测试桩** 衔接。
|
||
|
||
---
|
||
|
||
## 2. 测试分层架构
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph L4["L4 可选 UI E2E"]
|
||
UI[Playwright / Cypress<br/>关键页面冒烟]
|
||
end
|
||
|
||
subgraph L3["L3 API 全链路 E2E(推荐主战场)"]
|
||
E2E[OrderLifecycleE2ETests<br/>真实 MySQL + TestServer]
|
||
end
|
||
|
||
subgraph L2["L2 API 集成"]
|
||
INT[SimpleAdmin.Api.IntegrationTests<br/>路由注册 + Mock 依赖]
|
||
end
|
||
|
||
subgraph L1["L1 单元测试"]
|
||
UNIT[Oms.Tests<br/>计费 / 签名 / Batch 治理]
|
||
end
|
||
|
||
L1 --> L2 --> L3
|
||
L3 -.-> L4
|
||
```
|
||
|
||
| 层级 | 项目位置 | 依赖 | 运行频率 |
|
||
|------|----------|------|----------|
|
||
| L1 单元 | `oms0414-back/src/Oms.Tests` | 无 DB | 每次 PR |
|
||
| L2 集成 | `oms0414-back/src/SimpleAdmin.Api.IntegrationTests` | TestServer + 内存 RBAC | 每次 PR |
|
||
| L3 API E2E | **待建** `Oms.E2E.Tests` 或扩展现有 IntegrationTests | Docker MySQL + 可选 RabbitMQ/WireMock | 每日 / 合并前 |
|
||
| L4 UI E2E | **待建** `oms0414/e2e/` | 前端 dev + 后端 API | 发版前手动 / 夜间 |
|
||
|
||
---
|
||
|
||
## 3. 测试环境与配置
|
||
|
||
### 3.1 基础服务
|
||
|
||
| 组件 | 用途 | 本地 / CI 建议 |
|
||
|------|------|----------------|
|
||
| MySQL 8.x | 业务库 `oms_test` | `docker compose` 独立库,每次 E2E 前 migrate |
|
||
| SimpleAdmin.Api | OMS 后端 | `ASPNETCORE_ENVIRONMENT=Testing` |
|
||
| 前端 Vite | UI E2E 可选 | `localhost:5173` |
|
||
| RabbitMQ | 批量任务 E2E | 默认 **关闭**;批量专项用例单独 job 开启 |
|
||
| WireMock / MockServer | Track、itfx 下游 | E2E 默认 mock,避免外网依赖 |
|
||
|
||
### 3.2 后端配置项(`appsettings.Testing.json` 或环境变量)
|
||
|
||
```json
|
||
{
|
||
"ConnectionStrings": { "Default": "Server=127.0.0.1;Port=3306;Database=oms_test;..." },
|
||
"OrderBatch": {
|
||
"RabbitMq": { "Enabled": false }
|
||
},
|
||
"Oms": {
|
||
"TrackService": {
|
||
"Enabled": true,
|
||
"BaseUrl": "http://127.0.0.1:9090",
|
||
"AppKey": "TEST_KEY",
|
||
"AppSecret": "TEST_SECRET",
|
||
"TimeoutSeconds": 5
|
||
},
|
||
"Itfx": {
|
||
"BaseUrl": "http://127.0.0.1:9091",
|
||
"TimeoutSeconds": 5
|
||
}
|
||
},
|
||
"App": { "SendStartupNotification": false }
|
||
}
|
||
```
|
||
|
||
| 配置节 | 测试关注点 | Mock 策略 |
|
||
|--------|------------|-----------|
|
||
| `Oms:TrackService` | 创建订单后异步 `UpsertSmallBag` | WireMock 返回 200 + 固定 body |
|
||
| `Oms:Itfx` | 下游预报转发(可选步骤) | WireMock 或跳过 |
|
||
| `OrderBatch:RabbitMq` | 批量支付/入库等 | 主链路用同步 API;批量单独用例开启 |
|
||
|
||
### 3.3 数据库初始化顺序
|
||
|
||
```text
|
||
1. db.sql # 全量表结构
|
||
2. sql/migrate_*.sql # 增量迁移(issue_template、xhs 等按需)
|
||
3. scripts/order_batch_job_tables.sql
|
||
4. sql/seed_e2e_order_lifecycle.sql # 【待建】E2E 专用主数据(见 §4)
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 主数据 Fixture(测试前置条件)
|
||
|
||
自动化执行前,库中须存在以下**稳定可引用**的数据。建议新增 `sql/seed_e2e_order_lifecycle.sql`,所有 E2E 用例共用同一套编码。
|
||
|
||
### 4.1 主数据清单
|
||
|
||
| 类别 | 表 / 模块 | 测试用固定值 | 说明 |
|
||
|------|-----------|--------------|------|
|
||
| 国家 | `t_country` | `US` / `CN` | 收件国用于分区计价 |
|
||
| 客户 | `t_customer` | `customerCode=E2E001`,`Balance >= 10000` | 支付前须余额充足 |
|
||
| RBAC 用户 | `user` | 客户主账号,绑定 `E2E001` | 登录拿 JWT |
|
||
| 仓库 | `t_warehouse_address` | `warehouseId=9001` | 下单、扫描共用 |
|
||
| 销售产品 | `t_sales_product` | `productCode=E2E-SP-01` | 已发布、已绑定规则/价格快照 |
|
||
| 服务渠道 | `t_service_channel` | `channelCode=E2E-CH-01` | 排货后可写入订单 |
|
||
| 价格 / 分区 | `t_sales_product_price*`、`t_kpi_area*` | 覆盖 US 分区 | 否则创建订单会 `draft` + `PredeclareFailReason` |
|
||
| 计重 / 进位 | `t_weight_rule`、`t_weight_rounding` | 匹配 1kg 标准件 | 入库/outbound 计费依赖 |
|
||
| 数据权限 | 数据范围 | 测试用户可见 E2E 客户 | 否则列表为空 |
|
||
|
||
### 4.2 登录与请求头
|
||
|
||
```http
|
||
POST /admin/auth/login
|
||
Content-Type: application/json
|
||
|
||
{ "userName": "e2e_customer", "password": "..." }
|
||
```
|
||
|
||
后续请求:
|
||
|
||
```http
|
||
Authorization: Bearer {accessToken}
|
||
```
|
||
|
||
客户会话下单时 **不传 `customerId`**(由 `OmsSessionHelper` 解析);内部运营账号测入库/出库时用 **运营 RBAC 账号**。
|
||
|
||
### 4.3 推荐双角色
|
||
|
||
| 角色 | 用途 | 权限前缀 |
|
||
|------|------|----------|
|
||
| `e2e_customer` | 下单、支付、查单 | `Order.PlaceOrder.*`、`Order.MyOrders.*` |
|
||
| `e2e_operator` | 入库、出库扫描 | `Operation.InboundScan.*`、`Operation.OutboundScan.*` |
|
||
|
||
---
|
||
|
||
## 5. 主流程用例设计(Happy Path)
|
||
|
||
### 5.1 流程总览
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as 客户 API
|
||
participant O as OMS OrderService
|
||
participant W as 仓储 Operation
|
||
participant F as Finance
|
||
participant T as Track(Mock)
|
||
|
||
C->>O: POST /order/parcel/create
|
||
O-->>C: predeclared + serviceNo
|
||
O->>T: UpsertSmallBag (async)
|
||
|
||
C->>W: POST /operation/inbound/create
|
||
W->>O: ApplyReceiveBilling
|
||
W-->>C: pendingPayment + ReceiveTime
|
||
|
||
C->>O: POST /order/pay
|
||
O->>F: DebitOrderPay
|
||
O-->>C: pendingShip + PayTime
|
||
|
||
C->>W: POST /operation/outbound/create
|
||
W->>O: ApplyShipBilling
|
||
W-->>C: pendingOnline + ShipTime
|
||
|
||
Note over C,T: Phase 2 签收
|
||
T-->>O: (待实现) 状态回写
|
||
O-->>C: deliverySuccess + SignTime
|
||
```
|
||
|
||
### 5.2 分步用例表
|
||
|
||
| 步骤 | API | 方法 | 关键入参 | 期望 `OrderStatus` | 期望副作用 |
|
||
|------|-----|------|----------|-------------------|------------|
|
||
| 0 可选试算 | `/order/price-check` | POST | `productCode`, 件重尺, 收件国 | — | 返回价格 > 0 |
|
||
| 1 创建订单 | `/order/parcel/create` | POST | 见 §5.3 | `predeclared` | `t_order_fee` 预报应收;`ServiceNo` 生成 |
|
||
| 2 查详情 | `/order/detail` | GET | `id` | `predeclared` | 发件人/收件人/申报齐全 |
|
||
| 3 入库 | `/operation/inbound/create` | POST | `waybillNo`, 实重尺 | `pendingPayment` | `ReceiveTime` 非空;入库费 `ChargingStage=inbound` |
|
||
| 4 支付 | `/order/pay` | POST | `{ "id": orderId }` | `pendingShip` | `IsPaid=1`, `PayTime`;余额减少;`account_flow` |
|
||
| 5 出库 | `/operation/outbound/create` | POST | `waybillNo`, 实重尺 | `pendingOnline` | `ShipTime` 非空;出库费 |
|
||
| 6 列表 | `/order/list` | POST | `status=pendingOnline` | — | 包含该 `serviceNo` |
|
||
| 7 轨迹 | Mock 校验 | — | — | — | UpsertSmallBag 被调用 1 次 |
|
||
| 8 签收 | **Phase 2** | — | — | `deliverySuccess` | `SignTime` 非空 |
|
||
|
||
### 5.3 创建订单请求模板(E2E Fixture)
|
||
|
||
```json
|
||
{
|
||
"requestId": "e2e-{uuid}",
|
||
"clientNo": "E2E-CLIENT-{timestamp}",
|
||
"productCode": "E2E-SP-01",
|
||
"cargoAttribute": "general",
|
||
"warehouseId": 9001,
|
||
"length": 30,
|
||
"width": 20,
|
||
"height": 10,
|
||
"actualWeight": 1.2,
|
||
"quantity": 1,
|
||
"receiver": {
|
||
"name": "E2E Receiver",
|
||
"phone": "13800000001",
|
||
"countryCode": "US",
|
||
"state": "CA",
|
||
"city": "Los Angeles",
|
||
"address": "100 Test St",
|
||
"postcode": "90001"
|
||
},
|
||
"sender": {
|
||
"name": "E2E Sender",
|
||
"phone": "13900000001",
|
||
"countryCode": "CN",
|
||
"city": "Shenzhen",
|
||
"address": "Test Warehouse"
|
||
},
|
||
"items": [
|
||
{
|
||
"nameEn": "Test Goods",
|
||
"nameCn": "测试商品",
|
||
"quantity": 1,
|
||
"unitPrice": 10,
|
||
"weight": 1.2,
|
||
"hsCode": "6109100021"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 5.4 入库 / 出库请求模板
|
||
|
||
```json
|
||
// POST /operation/inbound/create
|
||
{
|
||
"waybillNo": "{serviceNo}",
|
||
"weight": 1.2,
|
||
"length": 30,
|
||
"width": 20,
|
||
"height": 10,
|
||
"warehouseId": 9001
|
||
}
|
||
|
||
// POST /operation/outbound/create
|
||
{
|
||
"waybillNo": "{serviceNo}",
|
||
"weight": 1.2,
|
||
"length": 30,
|
||
"width": 20,
|
||
"height": 10,
|
||
"warehouseId": 9001
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 功能模块与 API 映射
|
||
|
||
| 业务阶段 | 后端 Service | 前端模块 | 路由 | 权限(`pageButtonCatalog`) |
|
||
|----------|--------------|----------|------|---------------------------|
|
||
| 试算 / 下单 | `OrderService` | 物流下单 | `/order/placeOrder` | `Order.PlaceOrder.*` |
|
||
| 订单管理 | `OrderService` | 我的订单 | `/order/myOrders` | `Order.MyOrders.*` |
|
||
| 入库 | `InboundRecordService` | 入库扫描 | `/operation/inboundScan` | `Operation.InboundScan.Inbound` |
|
||
| 出库 | `OutboundRecordService` | 出库扫描 | `/operation/outboundScan` | `Operation.OutboundScan.Outbound` |
|
||
| 客户余额 | `CustomerBalanceMutator` | 客户管理 / 充值 | `/user/customer` | `User.Customer.*` |
|
||
| 应收应付 | `FinanceService` | 应收应付 | `/finance/receivablePayable` | `Finance.ReceivablePayable.Query` |
|
||
| 账户流水 | `CustomerAccountFlowService` | — | API | — |
|
||
| 渠道配置 | `SalesProductService` 等 | 销售产品 / 服务渠道 | `/channel/*` | 各模块 Query/Edit |
|
||
| 轨迹推送 | `SmallBagTrackOrderNotifier` | 我的订单-创建轨迹 | — | `Order.MyOrders.CreateTrackOrder` |
|
||
| 下游预报 | `OrderService.DownstreamForward` | 转发下游 | — | `Order.MyOrders.ForwardDownstreamCreate` |
|
||
| 批量任务 | `OrderBatchJobCoordinator` | 批量任务 | `/order/batchJobs` | `Order.BatchJobs.*` |
|
||
|
||
---
|
||
|
||
## 7. 断言检查点(每层必验)
|
||
|
||
### 7.1 HTTP 层
|
||
|
||
- 状态码 200(业务错误时 Fake 框架返回统一错误体,需断言 `message` 为空或 success 标志)
|
||
- 响应 JSON 关键字段类型与枚举值
|
||
|
||
### 7.2 订单主表 `t_order`
|
||
|
||
```sql
|
||
SELECT OrderStatus, IsPaid, ReceiveTime, PayTime, ShipTime, SignTime,
|
||
PredeclareFailReason, ChannelCode, ChargeableWeight
|
||
FROM t_order WHERE ServiceNo = @serviceNo;
|
||
```
|
||
|
||
| 步骤后 | OrderStatus | IsPaid | 时间字段 |
|
||
|--------|-------------|--------|----------|
|
||
| 创建 | `predeclared` | 0 | 全 NULL |
|
||
| 入库 | `pendingPayment` | 0 | ReceiveTime 有值 |
|
||
| 支付 | `pendingShip` | 1 | PayTime 有值 |
|
||
| 出库 | `pendingOnline` | 1 | ShipTime 有值 |
|
||
| 签收 | `deliverySuccess` | 1 | SignTime 有值 |
|
||
|
||
### 7.3 费用 `t_order_fee`
|
||
|
||
- 预报后:存在 `Type=receivable` 且 `ChargingStage` 含 forecast/predeclare
|
||
- 入库后:新增 `ChargingStage=inbound` 行(若产品配置入库计费)
|
||
- 出库后:新增 `ChargingStage=outbound` 行
|
||
- 支付金额 = 当前应收合计
|
||
|
||
### 7.4 客户财务
|
||
|
||
```sql
|
||
SELECT Balance FROM t_customer WHERE Id = @customerId;
|
||
SELECT * FROM t_customer_account_flow
|
||
WHERE BizType = 'orderPay' AND BizId = @orderId;
|
||
```
|
||
|
||
- 支付后:`Balance` 减少额 = 订单应收合计
|
||
- 流水 `Amount` 为负,`BalanceBefore/After` 连贯
|
||
|
||
### 7.5 仓储记录
|
||
|
||
```sql
|
||
SELECT * FROM t_inbound_record WHERE WaybillNo = @serviceNo;
|
||
SELECT * FROM t_outbound_record WHERE WaybillNo = @serviceNo;
|
||
```
|
||
|
||
### 7.6 轨迹 Mock
|
||
|
||
- WireMock 收到 `POST /OrderV2/UpsertSmallBag`
|
||
- 请求头含 `appKey`、`timestamp`、`sign`(签名算法见 `SmallBagTrackSignHelperTests`)
|
||
|
||
---
|
||
|
||
## 8. 负向与分支用例(摘要)
|
||
|
||
| 编号 | 场景 | 触发 | 期望 |
|
||
|------|------|------|------|
|
||
| N01 | 余额不足支付 | 客户 Balance < 应收 | `账户余额不足` |
|
||
| N02 | 未入库支付 | 跳过步骤 3 直接 pay | `当前订单状态不可支付` |
|
||
| N03 | 未支付出库 | 跳过步骤 4 直接 outbound | `订单未付款,禁止出库` |
|
||
| N04 | 重复支付 | pay 两次 | `订单已支付` |
|
||
| N05 | 价格未配置 | 错误 productCode | `draft` + `PredeclareFailReason` |
|
||
| N06 | 黑名单国家/客户 | 命中黑名单 | 创建失败,不落库或 draft |
|
||
| N07 | 拦截单出库 | intercept 后 outbound | 按业务规则拒绝或警告 |
|
||
| B01 | 问题件流程 | mark-problematic | `problematic` + `handleStatus=pending` |
|
||
| B02 | 处理完成 | handle-status/update | `handleStatus=processed` |
|
||
| B03 | 批量支付 | `/order/batch/pay` + RabbitMQ | Job 全部 success(独立 job) |
|
||
|
||
---
|
||
|
||
## 9. 自动化实现建议
|
||
|
||
### 9.1 推荐新建项目结构(后端)
|
||
|
||
```text
|
||
oms0414-back/
|
||
src/
|
||
Oms.E2E.Tests/ # 新建
|
||
Fixtures/
|
||
OrderLifecycleFixture.cs # 登录、种子数据、清理
|
||
WireMockTrackServer.cs
|
||
Scenarios/
|
||
OrderLifecycleHappyPathTests.cs
|
||
OrderLifecycleNegativeTests.cs
|
||
sql/
|
||
seed_e2e_order_lifecycle.sql
|
||
assert_order_state.sql
|
||
appsettings.E2E.json
|
||
```
|
||
|
||
### 9.2 技术选型
|
||
|
||
| 能力 | 库 |
|
||
|------|-----|
|
||
| API 宿主 | 复用 `SimpleAdminApiTestHost` 或 `WebApplicationFactory` + 真实 MySQL |
|
||
| DB 断言 | `Dapper` / 直接 `SqlSugar` 查询 |
|
||
| HTTP 客户端 | `HttpClient` + `System.Text.Json` |
|
||
| Mock 外服 | `WireMock.Net` |
|
||
| 测试框架 | xUnit + FluentAssertions(与现有一致) |
|
||
|
||
### 9.3 示例测试类骨架(伪代码)
|
||
|
||
```csharp
|
||
[Collection("OrderLifecycle")]
|
||
public class OrderLifecycleHappyPathTests
|
||
{
|
||
[Fact]
|
||
public async Task Step01_To_Step05_PendingOnline_ShouldSucceed()
|
||
{
|
||
var token = await Fixture.LoginAsCustomerAsync();
|
||
var create = await Fixture.Api.PostJsonAsync("/admin/order/parcel/create", body, token);
|
||
create.OrderStatus.Should().Be("predeclared");
|
||
var serviceNo = create.ServiceNo;
|
||
|
||
await Fixture.Api.PostJsonAsync("/admin/operation/inbound/create", inboundBody, operatorToken);
|
||
await Fixture.AssertOrderStatusAsync(serviceNo, "pendingPayment");
|
||
|
||
await Fixture.Api.PostJsonAsync("/admin/order/pay", new { id = create.Id }, token);
|
||
await Fixture.AssertOrderStatusAsync(serviceNo, "pendingShip");
|
||
await Fixture.AssertBalanceDebitedAsync(create.CustomerId, create.Id);
|
||
|
||
await Fixture.Api.PostJsonAsync("/admin/operation/outbound/create", outboundBody, operatorToken);
|
||
await Fixture.AssertOrderStatusAsync(serviceNo, "pendingOnline");
|
||
|
||
Fixture.TrackMock.VerifyUpsertCalledOnce(serviceNo);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.4 数据隔离策略
|
||
|
||
| 策略 | 做法 |
|
||
|------|------|
|
||
| **A 每用例独立 clientNo** | `E2E-{guid}`,不删库,靠唯一键隔离(推荐) |
|
||
| **B 事务回滚** | SqlSugar 难包裹跨 HTTP 请求,不推荐 |
|
||
| **C 每 job 重建库** | CI 慢但最干净;夜间全量 E2E 使用 |
|
||
|
||
---
|
||
|
||
## 10. CI/CD 流水线设计
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
PR[PR / Push] --> L1[dotnet test Oms.Tests]
|
||
L1 --> L2[dotnet test IntegrationTests]
|
||
L2 --> E2E{main 分支?}
|
||
E2E -->|是| Docker[启动 MySQL + WireMock]
|
||
Docker --> Seed[执行 seed_e2e_order_lifecycle.sql]
|
||
Seed --> L3[dotnet test Oms.E2E.Tests]
|
||
L3 --> Report[测试报告 / 飞书通知]
|
||
```
|
||
|
||
### 10.1 GitHub Actions 示例(片段)
|
||
|
||
```yaml
|
||
jobs:
|
||
unit-and-integration:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- run: dotnet test src/Oms.Tests
|
||
- run: dotnet test src/SimpleAdmin.Api.IntegrationTests
|
||
|
||
order-lifecycle-e2e:
|
||
if: github.ref == 'refs/heads/main'
|
||
runs-on: ubuntu-latest
|
||
services:
|
||
mysql:
|
||
image: mysql:8.0
|
||
env:
|
||
MYSQL_ROOT_PASSWORD: test
|
||
MYSQL_DATABASE: oms_test
|
||
steps:
|
||
- run: mysql -h 127.0.0.1 -uroot -ptest oms_test < db.sql
|
||
- run: mysql -h 127.0.0.1 -uroot -ptest oms_test < sql/seed_e2e_order_lifecycle.sql
|
||
- run: dotnet test src/Oms.E2E.Tests --filter Category=E2E
|
||
```
|
||
|
||
### 10.2 本地一键脚本(建议 `scripts/run-order-e2e.ps1`)
|
||
|
||
```powershell
|
||
docker compose -f docker-compose.e2e.yml up -d
|
||
dotnet test src/Oms.E2E.Tests
|
||
docker compose -f docker-compose.e2e.yml down
|
||
```
|
||
|
||
---
|
||
|
||
## 11. Phase 2:签收段衔接方案
|
||
|
||
OMS 尚未实现 `shipping` → `deliverySuccess` 回写时,任选其一:
|
||
|
||
| 方案 | 说明 | 适用 |
|
||
|------|------|------|
|
||
| **P2-A Track 侧完成** | 调 `trackApi/Track/Order/UpdateOrderStatus` 置 `isCompleted=true` | 验证轨迹系统闭环 |
|
||
| **P2-B 测试专用 API** | 新增 `[TestingOnly] POST /order/test/mark-delivered` | 仅 Testing 环境注册 |
|
||
| **P2-C SQL 置态** | E2E 直接 `UPDATE t_order SET OrderStatus='deliverySuccess', SignTime=NOW()` | 临时;不验 API |
|
||
| **P2-D 实现正式回调** | Track Webhook → OMS Consumer | 生产方案,纳入同一 E2E |
|
||
|
||
**推荐路径**:先 **P2-B** unblock E2E,上线前替换为 **P2-D** 并删除测试 API。
|
||
|
||
---
|
||
|
||
## 12. 实施路线图
|
||
|
||
| 阶段 | 交付物 | 工时估 |
|
||
|------|--------|--------|
|
||
| **P0** | 本文档 + `seed_e2e_order_lifecycle.sql` | 1d |
|
||
| **P1** | `Oms.E2E.Tests` Happy Path(至 pendingOnline) | 2–3d |
|
||
| **P1** | WireMock Track + 负向用例 N01–N04 | 1d |
|
||
| **P2** | 签收置态 / Webhook + 完整端到签收 | 2d |
|
||
| **P3** | Playwright 冒烟(下单页 + 扫描页) | 2d |
|
||
| **P3** | CI nightly + 测试报告 | 1d |
|
||
|
||
---
|
||
|
||
## 13. 关键代码与文档索引
|
||
|
||
### 后端
|
||
|
||
| 路径 | 说明 |
|
||
|------|------|
|
||
| `Oms.Domain/OrdersAggregate/Consts/OrderStatusCodes.cs` | 订单状态枚举 |
|
||
| `Oms.Application/Services/Orders/OrderService.ParcelBilling.cs` | 创建、入库/出库计费 |
|
||
| `Oms.Application/Services/Orders/OrderService.cs` | 支付、列表 |
|
||
| `Oms.Application/Services/Operations/InboundRecordService.cs` | 入库 |
|
||
| `Oms.Application/Services/Operations/OutboundRecordService.cs` | 出库 |
|
||
| `Oms.Application/Shared/CustomerBalanceMutator.cs` | 支付扣款 |
|
||
| `Oms.Application/Integrations/SmallBagTrack/` | 轨迹推送 |
|
||
| `SimpleAdmin.Api.IntegrationTests/Support/SimpleAdminApiTestHost.cs` | 集成测试宿主 |
|
||
| `Oms.Tests/ParcelBillingCalculatorTests.cs` | 计费单元测试 |
|
||
|
||
### 前端
|
||
|
||
| 路径 | 说明 |
|
||
|------|------|
|
||
| `src/constants/orderStatus.ts` | 状态常量 |
|
||
| `src/api/order/index.ts` | 订单 API |
|
||
| `src/api/operation/index.ts` | 仓储 API |
|
||
| `src/views/order/placeOrder/index.vue` | 下单页 |
|
||
| `src/views/operation/inboundScan/index.vue` | 入库 |
|
||
| `src/views/operation/outboundScan/index.vue` | 出库 |
|
||
|
||
### 文档
|
||
|
||
| 路径 | 说明 |
|
||
|------|------|
|
||
| `docs/oms系统设计-050801.md` | 主设计(§4 订单、§6 操作、§10.3 状态码) |
|
||
| `docs/物流下单协议.md` | parcel/create 协议 |
|
||
| `docs/订单批量处理与异步队列方案0707.md` | 批量异步 |
|
||
|
||
---
|
||
|
||
## 14. 附录:手动冒烟检查清单(5 分钟)
|
||
|
||
自动化未就绪时,可按此手工验证主链路:
|
||
|
||
- [ ] 客户登录,余额 ≥ 100
|
||
- [ ] 销售产品 `E2E-SP-01` 已发布且 US 有价格
|
||
- [ ] `POST /order/parcel/create` → 返回 `predeclared`
|
||
- [ ] `POST /operation/inbound/create` → 订单变 `pendingPayment`
|
||
- [ ] `POST /order/pay` → `pendingShip`,余额减少
|
||
- [ ] `POST /operation/outbound/create` → `pendingOnline`
|
||
- [ ] `GET /order/detail` → `ReceiveTime`、`PayTime`、`ShipTime` 均有值
|
||
- [ ] (可选)Track Mock 日志有 UpsertSmallBag
|
||
|
||
---
|
||
|
||
## 15. 已落地实现(2026-07-08)
|
||
|
||
| 交付物 | 路径 |
|
||
|--------|------|
|
||
| E2E 主数据种子 | `oms0414-back/sql/seed_e2e_order_lifecycle.sql` |
|
||
| E2E 测试项目 | `oms0414-back/src/Oms.E2E.Tests/` |
|
||
| Happy Path 用例 | `Scenarios/OrderLifecycleHappyPathTests.cs` |
|
||
| 一键脚本 | `oms0414-back/scripts/run-order-e2e.ps1` |
|
||
|
||
**运行方式:**
|
||
|
||
```powershell
|
||
$env:OMS_E2E_ENABLED = "1"
|
||
$env:OMS_E2E_CONNECTION = "Server=127.0.0.1;Port=3306;Database=oms;Uid=root;Pwd=你的密码;CharSet=utf8mb4;"
|
||
cd oms0414-back
|
||
.\scripts\run-order-e2e.ps1
|
||
```
|
||
|
||
未设置 `OMS_E2E_ENABLED` 时,E2E 用例自动跳过(不失败)。
|
||
|
||
---
|
||
|
||
**维护说明**:OMS 实现签收回写后,更新 §1.2 边界表、§5 步骤 8、§11,并将 Phase 2 用例并入 P1 必跑集。
|