diff --git a/sql/seed_e2e_order_lifecycle.sql b/sql/seed_e2e_order_lifecycle.sql
index a6b4b71..39a66bf 100644
--- a/sql/seed_e2e_order_lifecycle.sql
+++ b/sql/seed_e2e_order_lifecycle.sql
@@ -1,7 +1,7 @@
-- E2E 订单全链路测试主数据(固定 ID 段 900x / 99001)
-- 前置:已执行 db.sql;库中已有 t_country.US
-- 用法:mysql ... oms_test < sql/seed_e2e_order_lifecycle.sql
--- RBAC 菜单/权限:sql/seed_order_lab_rbac_menu.sql + sql/seed_order_lab_role_permissions.sql
+-- RBAC 批量任务菜单/权限:sql/seed_order_lab_rbac_menu.sql + sql/seed_order_lab_role_permissions.sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
diff --git a/sql/seed_order_lab_rbac_menu.sql b/sql/seed_order_lab_rbac_menu.sql
index 0fe3ac7..a186e5c 100644
--- a/sql/seed_order_lab_rbac_menu.sql
+++ b/sql/seed_order_lab_rbac_menu.sql
@@ -1,4 +1,4 @@
--- 订单批量任务 + 链路演练 RBAC 菜单(Fake.Rbac menu 表)
+-- 订单批量任务 RBAC 菜单(Fake.Rbac menu 表)
-- 执行库:RBAC 库(与 seed_xhs_rbac_menu.sql 相同)
-- 幂等:可重复执行
@@ -24,8 +24,7 @@ INSERT INTO `menu` (
`Id`, `PId`, `Name`, `PermissionCode`, `Type`, `Icon`, `Route`, `Component`, `Order`,
`IsHidden`, `IsCached`, `Description`, `IsDeleted`,
`ConcurrencyStamp`, `CreateUserId`, `CreateTime`, `UpdateUserId`, `UpdateTime`
-) VALUES
-(
+) VALUES (
'b1b2c3d4-e5f6-7890-abcd-ef1234567901',
@ORDER_PID,
'批量任务',
@@ -37,19 +36,6 @@ INSERT INTO `menu` (
4,
0, 1, '订单 RabbitMQ 批量任务治理', 0,
UUID(), @ADMIN_USER_ID, NOW(), @ADMIN_USER_ID, NOW()
-),
-(
- 'b1b2c3d4-e5f6-7890-abcd-ef1234567902',
- @ORDER_PID,
- '链路演练',
- 'Order.LifecycleLab',
- 1,
- NULL,
- '/order/lifecycleLab',
- 'views/order/lifecycleLab/index',
- 5,
- 0, 1, '订单全链路可视化演练(E2E)', 0,
- UUID(), @ADMIN_USER_ID, NOW(), @ADMIN_USER_ID, NOW()
)
ON DUPLICATE KEY UPDATE
`Name` = VALUES(`Name`),
@@ -61,3 +47,8 @@ ON DUPLICATE KEY UPDATE
`Description` = VALUES(`Description`),
`CreateUserId` = VALUES(`CreateUserId`),
`UpdateUserId` = VALUES(`UpdateUserId`);
+
+-- 清理已废弃的链路演练菜单
+UPDATE `menu`
+SET `IsDeleted` = 1, `UpdateTime` = NOW(), `UpdateUserId` = @ADMIN_USER_ID
+WHERE `Route` = '/order/lifecycleLab' AND `IsDeleted` = 0;
diff --git a/sql/seed_order_lab_role_permissions.sql b/sql/seed_order_lab_role_permissions.sql
index 515d343..adef590 100644
--- a/sql/seed_order_lab_role_permissions.sql
+++ b/sql/seed_order_lab_role_permissions.sql
@@ -1,4 +1,4 @@
--- 为 Admin / Customer 角色追加批量任务、链路演练权限(幂等)
+-- 为 Admin / Customer 角色追加批量任务权限(幂等)
-- RBAC 库执行;执行后登录用户需重新获取 token 或刷新权限缓存
SET @ADMIN_USER_ID = (
@@ -18,13 +18,14 @@ CROSS JOIN (
SELECT 'Order.BatchJobs.Query' AS `Code` UNION ALL
SELECT 'Order.BatchJobs.View' UNION ALL
SELECT 'Order.BatchJobs.Retry' UNION ALL
- SELECT 'Order.BatchJobs.Cancel' UNION ALL
- SELECT 'Order.LifecycleLab.Query' UNION ALL
- SELECT 'Order.LifecycleLab.RunStep' UNION ALL
- SELECT 'Order.LifecycleLab.RunAll'
+ SELECT 'Order.BatchJobs.Cancel'
) p
WHERE r.`Code` IN ('Admin', 'Customer')
AND NOT EXISTS (
SELECT 1 FROM `role_permission` rp
WHERE rp.`RoleId` = r.`Id` AND rp.`PermissionCode` = p.`Code`
);
+
+-- 清理已废弃的链路演练权限
+DELETE FROM `role_permission`
+WHERE `PermissionCode` LIKE 'Order.LifecycleLab.%';
diff --git a/src/Oms.Application/Services/Orders/OrderService.LifecycleLab.cs b/src/Oms.Application/Services/Orders/OrderService.LifecycleLab.cs
deleted file mode 100644
index 2c90865..0000000
--- a/src/Oms.Application/Services/Orders/OrderService.LifecycleLab.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using Fake.Application;
-using Microsoft.AspNetCore.Mvc;
-using Oms.Application.Dtos.Orders;
-using Oms.Application.Shared;
-using Oms.Domain.OrdersAggregate.Consts;
-
-namespace Oms.Application.Services.Orders;
-
-public partial class OrderService
-{
- ///
- /// 链路演练:模拟签收(待上网/运输中 → 派送成功)。
- /// 仅供 E2E/演练;正式环境签收应接入轨迹同步。
- ///
- [HttpPost("/order/lifecycle-lab/sign")]
- public async Task LifecycleLabSignAsync([FromBody] OrderActionInput input)
- {
- var order = await GetOrderOrThrowAsync(input.Id);
- if (order.OrderStatus == OrderStatusCodes.DeliverySuccess)
- {
- throw new BusinessException("订单已签收");
- }
-
- if (order.OrderStatus is not (OrderStatusCodes.PendingOnline or OrderStatusCodes.Shipping))
- {
- throw new BusinessException(
- $"当前状态「{OmsDocHelper.GetOrderStatusName(order.OrderStatus)}」不可模拟签收,请先完成出库");
- }
-
- var now = DateTime.Now;
- if (order.OrderStatus == OrderStatusCodes.PendingOnline)
- {
- order.OrderStatus = OrderStatusCodes.Shipping;
- }
-
- order.OrderStatus = OrderStatusCodes.DeliverySuccess;
- order.SignTime = now;
- order.UpdateTime = now;
- await UpdateOrderAsync(order);
- }
-}
diff --git a/src/Oms.E2E.Tests/Scenarios/OrderLifecycleHappyPathTests.cs b/src/Oms.E2E.Tests/Scenarios/OrderLifecycleHappyPathTests.cs
index f0cc07a..30ec1ea 100644
--- a/src/Oms.E2E.Tests/Scenarios/OrderLifecycleHappyPathTests.cs
+++ b/src/Oms.E2E.Tests/Scenarios/OrderLifecycleHappyPathTests.cs
@@ -8,7 +8,7 @@ using Oms.E2E.Tests.Support;
namespace Oms.E2E.Tests.Scenarios;
///
-/// 订单主链路:创建 → 入库 → 支付 → 出库 → 签收。
+/// 订单主链路:创建 → 入库 → 支付 → 出库(至 pendingOnline)。
///
[Collection(OrderE2eCollection.Name)]
[Trait("Category", "E2E")]
@@ -84,21 +84,14 @@ public sealed class OrderLifecycleHappyPathTests(OrderE2eFixture fixture)
await AssertOrderStatusAsync(serviceNo, OrderStatusCodes.PendingOnline);
- var signResponse = await fixture.Client.PostAsync("/order/lifecycle-lab/sign", E2eJson.AsJsonContent(new { id }));
- var signText = await signResponse.Content.ReadAsStringAsync();
- signResponse.IsSuccessStatusCode.Should().BeTrue($"sign failed: {signText}");
-
- await AssertOrderStatusAsync(serviceNo, OrderStatusCodes.DeliverySuccess);
-
var detailResponse = await fixture.Client.GetAsync($"/order/detail?id={id}");
detailResponse.IsSuccessStatusCode.Should().BeTrue();
var detail = await E2eJson.ReadAsync(detailResponse);
detail.Should().NotBeNull();
- detail!.OrderStatus.Should().Be(OmsDocHelper.GetOrderStatusName(OrderStatusCodes.DeliverySuccess));
+ detail!.OrderStatus.Should().Be(OmsDocHelper.GetOrderStatusName(OrderStatusCodes.PendingOnline));
detail.ReceiveTime.Should().NotBeNull();
detail.PayTime.Should().NotBeNull();
detail.ShipTime.Should().NotBeNull();
- detail.SignTime.Should().NotBeNull();
}
private static object BuildParcelCreateBody(string clientNo) => new