Parcourir la source

fix(mdp): restore S1/S2 scheduled MDP and document P0 ASN UAT data

mdp_entity inserts now set create_time; 1.0.175 adds column defaults. Add P0 sales ASN seed SQL and update S0-S4 KPI quick reference.

chore: bump version server 1.0.175
skygu il y a 1 semaine
Parent
commit
ee51647682

+ 41 - 14
doc/plan/S0-S4_KPI测试数据速查表.md

@@ -33,7 +33,8 @@
 | FULL 批次(45 单) | `UAT导入:S1S4_UAT_FULL_20260605_V1` |
 | 采购 PO | `PO-UAT-20260604-*` 或 `PO-UAT-FULL-20260605-*` |
 | 采购申请 PR | `PR-UAT-*` |
-| 供应商发货 | `SH-UAT-*` |
+| 供应商发货(S4) | `scm_shd.shddh` 以 `SH-UAT-` 开头 |
+| 销售 ASN 发货(S1) | `ASNBOLShipperMaster.Id` 以 `SH-UAT-P0-` 开头;或 `OrdNbr` = 销售订单号 |
 
 **数据规模(AIDOP 租户)**:销售订单 **50**、PO **50**、发货 **50**、PR **229**、工单 **230**
 
@@ -56,7 +57,8 @@ MPO482024102300001
   → M500029406 / M500029407
   → PR-UAT-20260604-01
   → PO-UAT-20260604-01
-  → SH-UAT-20260604-01
+  → SH-UAT-20260604-01          (S4 供应商发货 scm_shd)
+  → SH-UAT-P0-20260614-01       (S1 销售 ASN,订单发货页可搜主订单号)
 ```
 
 ### FULL 包抽查
@@ -76,10 +78,10 @@ MPO482024102300001
 
 | 页面类型 | 可用数据 | 备注 |
 |----------|----------|------|
-| 物料 | `3121C0035`、`1A0C885`、`1AB9275`、`3124C0015` | `ItemMaster` 约 5,127 条 |
+| 物料 | `3121C0035`、`1A0C885`、`1AB9275`、`3124C0015` | `ItemMaster` 约 2.7 条 |
 | 产线 / 工作中心 | `LineMaster` 118 条、`WorkCtrMaster` 11 条 | Domain 多为 `8010` |
 | 员工 | `EmployeeMaster` 469 条 | |
-| 条码规则 | — | 当前无 UAT 种子,需单独造数 |
+| 条码规则 | `ado_s0_barcode_rule` | 有少量历史样例(非 UAT 专包) |
 | BOM | `ProductStructureMaster` | 有历史数据,部分需治理 |
 
 ---
@@ -89,12 +91,14 @@ MPO482024102300001
 | 页面 | 路径 | 搜什么 | 预期 |
 |------|------|--------|------|
 | 订单评审 | `/aidop/s1/order-mgmt/order` | `MPO482024102300001` | 1 单、2 行 |
-| 订单交付 | `/aidop/s1/order-mgmt/orderDelivery` | 同上 | 2 行 |
+| 订单交付 | `/aidop/s1/order-mgmt/orderDelivery` | 同上 | 2 行(读 `dwd_ship_trans`,需 S1 MDP **SUCCESS**) |
+| 订单发货 | `/aidop/s1/order-mgmt/asnShipper` | `MPO482024102300001` 或 `SH-UAT-P0-20260614-01` | **1 单、2 行明细** |
 | 指标看板 | `/aidop/s1/SalesKanBan/kanban` | — | 有 KPI |
 | 智能运营 | `/aidop/smart-ops/s1` | — | L1/L2 有数 |
-| 需求明细核验 | `/aidop/s1/SalesKanBan/requirement-examine-detail` | — | **可能无数据** |
+| 需求明细核验 | `/aidop/s1/SalesKanBan/requirement-examine-detail` | — | 有数据(DWD 已打通) |
 
-**KPI**:`S1_L1_001`~`003`,`S1_L2_001`~`015` | DWD:`dwd_ship_trans`
+**KPI**:`S1_L1_001`~`003`,`S1_L2_001`~`015` | DWD:`dwd_ship_trans`  
+**刷新**:`POST /api/AidopKanban/s1-mdp/refresh`(订单交付依赖最近 SUCCESS 批次)
 
 ---
 
@@ -135,7 +139,8 @@ MPO482024102300001
 | 供应商发货 | `/aidop/s4/delivery/supplier-shipment` | `SH-UAT-20260604-01` | 关联 PO |
 | 供应商交货管理 | `/aidop/s4/delivery/supplier-delivery-management` | `PO-UAT-20260604-01` | 可打开 |
 | 执行看板 | `/aidop/s4/execution-kanban/dashboard` | — | 页面可加载 |
-| 欠料看板 | `/aidop/s4/execution-kanban/supplier-shortage-kanban` | — | 约 8 条缺料 DWD |
+| 欠料看板 | `/aidop/s4/execution-kanban/supplier-shortage-kanban` | — | 列表有数(约 5 条,与 DWD 租户口径可能不一致) |
+| 采购退货 | `/aidop/s4/return-mgmt/purchase-return-order` | — | 有历史/增强 seed 时可测列表 |
 | 智能运营 | `/aidop/smart-ops/s4` | — | **先刷新 MDP** |
 | S4 看板 | `/aidop/kanban/s4` | 筛 `PO-UAT-20260604-01` | KPI/下钻有响应 |
 
@@ -151,7 +156,7 @@ MPO482024102300001
 
 | 模块 | 业务看板 | 智能运营 | MDP 刷新 | 核心 DWD |
 |------|----------|----------|----------|----------|
-| S1 | `/aidop/s1/SalesKanBan/kanban` | `/aidop/smart-ops/s1` | S1 MDP | `dwd_ship_trans` |
+| S1 | `/aidop/s1/SalesKanBan/kanban` | `/aidop/smart-ops/s1` | `s1-mdp/refresh` | `dwd_ship_trans` |
 | S2 | `/aidop/s2/collaboration-kanban/work-order-progress` | `/aidop/smart-ops/s2` | `s2-mdp/refresh` | `dwd_order_schedule_trans` |
 | S3 | `/aidop/s3/supply-kanban/mdp-monitor` | `/aidop/smart-ops/s3` | `s3-mdp/refresh` | `dwd_material_readiness` 等 |
 | S4 | `/aidop/kanban/s4` | `/aidop/smart-ops/s4` | `s4-mdp/refresh` | `dwd_s4_purchase_execution` |
@@ -167,7 +172,8 @@ MPO482024102300001
 
 - [ ] A1 登录 AIDOP + `AIDOPDemo`
 - [ ] A2 S1 订单评审:`MPO482024102300001`(1 单 2 行)
-- [ ] A3 S1 订单交付:同上
+- [ ] A3 S1 订单交付:同上(2 行)
+- [ ] A3b S1 订单发货:`MPO482024102300001` 或 `SH-UAT-P0-20260614-01`(1 单 2 行)
 - [ ] A4 S2 工单:`M500029406`、`M500029407`
 - [ ] A5 S3 PO:`PO-UAT-20260604-01`
 - [ ] A6 S3 PR:`PR-UAT-20260604-01`
@@ -205,6 +211,26 @@ FROM crm_seorderentry
 WHERE tenant_id = @tid AND bill_no = 'MPO482024102300001'
 GROUP BY bill_no;
 
+-- 主样例订单交付 DWD(需最近 S1 MDP SUCCESS)
+SELECT order_no, item_code, calc_batch_id
+FROM dwd_ship_trans
+WHERE tenant_id = @tid AND order_no = 'MPO482024102300001'
+ORDER BY calc_batch_id DESC
+LIMIT 5;
+
+-- S1 销售 ASN(主样例)
+SELECT m.Id, m.OrdNbr, d.Line, d.ContainerItem, d.QtyToShip
+FROM ASNBOLShipperMaster m
+LEFT JOIN ASNBOLShipperDetail d ON d.ASNBOLShipperRecID = m.RecID
+WHERE m.tenant_id = @tid AND m.OrdNbr = 'MPO482024102300001';
+
+-- S1/S2 MDP 最近批次
+SELECT job_code, batch_id, status, start_time
+FROM mdp_transform_run_log
+WHERE job_code IN ('S1_MDP_SYNC_TRANSFORM', 'S2_MDP_SYNC_TRANSFORM')
+ORDER BY start_time DESC
+LIMIT 4;
+
 -- PO / 发货串联(前 10 条)
 SELECT pom.PurOrd, pom.SalesOrd, sh.shddh
 FROM PurOrdMaster pom
@@ -235,12 +261,11 @@ SELECT COUNT(*) AS s4_pe FROM dwd_s4_purchase_execution WHERE tenant_id = @tid;
 | 现象 | 处理 |
 |------|------|
 | 列表全空 | 检查租户是否为 AIDOP |
-| S1 需求明细核验无数据 | 未导入 BOM 核验,测空态 |
+| S1 订单交付空、订单评审有数 | S1 MDP 未 SUCCESS;点刷新或查 `mdp_transform_run_log`(2026-06-14 已修 `mdp_entity.create_time`) |
+| S1 订单发货按主订单搜不到 | 执行 `sql/S1S4_UAT_P0_补ASN_主样例_20260614.sql` 补种子 |
 | S2 日计划/排程明细偏少 | 以工单进度为主 |
-| S4 退货 / IQC 为空 | 主链路未造异常;可用 seed 补 |
 | S4 看板 KPI 空 | 点「刷新 MDP」 |
-| `scm_shd` 按租户筛空 | 用 `SH-UAT-*` 或 `po_billno` 查 |
-| S0 条码规则无数据 | 需单独造数 |
+| `scm_shd` 按租户筛空 | 用 `SH-UAT-*` 或 `po_billno` 查(S4 表多无 `tenant_id`) |
 | S8 事件单为空 | 仅配置 + 少量样例 |
 
 ---
@@ -268,4 +293,6 @@ SELECT COUNT(*) AS s4_pe FROM dwd_s4_purchase_execution WHERE tenant_id = @tid;
 | [aidopdev_当前UAT测试数据场景说明.md](./aidopdev_当前UAT测试数据场景说明.md) | 库内快照 |
 | [sql/S1S4_UAT_P0_execute_write.sql](./sql/S1S4_UAT_P0_execute_write.sql) | P0 写入脚本 |
 | [sql/S1S4_UAT_FULL_execute_write.sql](./sql/S1S4_UAT_FULL_execute_write.sql) | FULL 写入脚本 |
+| [sql/S1S4_UAT_P0_补ASN_主样例_20260614.sql](./sql/S1S4_UAT_P0_补ASN_主样例_20260614.sql) | P0 主样例 S1 销售 ASN 种子 |
 | [../db/s4_global_uat_seed_20260608.sql](../db/s4_global_uat_seed_20260608.sql) | S4 收货/退货增强 |
+| 后端 `UpdateScripts/1.0.175.sql` | 修复 S1/S2 MDP `mdp_entity.create_time` 缺省值 |

+ 55 - 0
doc/plan/sql/S1S4_UAT_P0_补ASN_主样例_20260614.sql

@@ -0,0 +1,55 @@
+-- P0 主样例销售订单 ASN 发货种子(订单发货页可按 MPO482024102300001 检索)
+-- 租户:AIDOP 797403760988229
+-- 执行前请确认未占用单号 SH-UAT-P0-20260614-01
+
+SET @tenant_id := 797403760988229;
+SET @order_no := 'MPO482024102300001';
+SET @asn_id := 'SH-UAT-P0-20260614-01';
+SET @operator := 'UAT数据导入';
+SET @ship_date := '2024-10-29';
+SET @now := NOW();
+
+-- 主表(ShType=SH, Typed 非 S, IsActive=1)
+INSERT INTO ASNBOLShipperMaster
+    (Id, OrdNbr, SoldTo, ShipDate, Status, Remark, ShType, Typed, IsActive, IsConfirm, CreateUser, CreateTime2, tenant_id)
+SELECT
+    @asn_id, @order_no, 'CUST0005', @ship_date, '', 'UAT导入:P0主样例ASN', 'SH', '', 1, 0, @operator, @now, @tenant_id
+FROM DUAL
+WHERE NOT EXISTS (
+    SELECT 1 FROM ASNBOLShipperMaster
+    WHERE tenant_id = @tenant_id AND Id = @asn_id
+);
+
+SET @master_rec_id := (
+    SELECT RecID FROM ASNBOLShipperMaster
+    WHERE tenant_id = @tenant_id AND Id = @asn_id
+    LIMIT 1
+);
+
+-- 明细行 1:3121C0035 × 1500
+INSERT INTO ASNBOLShipperDetail
+    (Line, OrdNbr, OrdLine, ContainerItem, Descr, QtyToShip, ShType, Typed, IsActive, IsConfirm, ASNBOLShipperRecID, tenant_id)
+SELECT 1, @order_no, 1, '3121C0035', 'P0主样例行1', 1500, 'SH', '', 1, 0, @master_rec_id, @tenant_id
+FROM DUAL
+WHERE @master_rec_id IS NOT NULL
+  AND NOT EXISTS (
+    SELECT 1 FROM ASNBOLShipperDetail
+    WHERE tenant_id = @tenant_id AND ASNBOLShipperRecID = @master_rec_id AND Line = 1
+);
+
+-- 明细行 2:1A0C885 × 3500
+INSERT INTO ASNBOLShipperDetail
+    (Line, OrdNbr, OrdLine, ContainerItem, Descr, QtyToShip, ShType, Typed, IsActive, IsConfirm, ASNBOLShipperRecID, tenant_id)
+SELECT 2, @order_no, 2, '1A0C885', 'P0主样例行2', 3500, 'SH', '', 1, 0, @master_rec_id, @tenant_id
+FROM DUAL
+WHERE @master_rec_id IS NOT NULL
+  AND NOT EXISTS (
+    SELECT 1 FROM ASNBOLShipperDetail
+    WHERE tenant_id = @tenant_id AND ASNBOLShipperRecID = @master_rec_id AND Line = 2
+);
+
+SELECT m.RecID, m.Id, m.OrdNbr, d.Line, d.ContainerItem, d.QtyToShip
+FROM ASNBOLShipperMaster m
+LEFT JOIN ASNBOLShipperDetail d ON d.ASNBOLShipperRecID = m.RecID
+WHERE m.tenant_id = @tenant_id AND m.OrdNbr = @order_no
+ORDER BY d.Line;

+ 3 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.174</AssemblyVersion>
-    <FileVersion>1.0.174</FileVersion>
-    <Version>1.0.174</Version>
+    <AssemblyVersion>1.0.175</AssemblyVersion>
+    <FileVersion>1.0.175</FileVersion>
+    <Version>1.0.175</Version>
   </PropertyGroup>
 
   <ItemGroup>

+ 14 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.175.sql

@@ -0,0 +1,14 @@
+-- S1/S2 MDP:mdp_entity.create_time 缺省值修复(根因:INSERT 未带 create_time 且列无 DEFAULT)
+-- 版本:1.0.175
+
+SET NAMES utf8mb4;
+
+ALTER TABLE mdp_entity
+    MODIFY COLUMN create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+    MODIFY COLUMN update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间';
+
+-- 历史 NULL 行兜底(若存在)
+UPDATE mdp_entity
+SET create_time = COALESCE(create_time, CURRENT_TIMESTAMP),
+    update_time = COALESCE(update_time, CURRENT_TIMESTAMP)
+WHERE create_time IS NULL OR update_time IS NULL;

+ 6 - 6
server/Plugins/Admin.NET.Plugin.AiDOP/Order/S1MdpSyncTransformService.cs

@@ -96,9 +96,9 @@ public class S1MdpSyncTransformService : ITransient
         await _db.Ado.ExecuteCommandAsync(
             """
             INSERT INTO mdp_entity
-            (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, batch_size, status, remark)
+            (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, batch_size, status, remark, create_time, update_time)
             SELECT 0, s.id, 'S1_REQUIREMENT_EXAMINE_RESULT', 'S1需求核验结果主表', 'TABLE',
-                   'b_examine_result', 'mdp_stg_so', 'FULL', 5000, 1, '需求核验结果主表,进入 S1 贴源层'
+                   'b_examine_result', 'mdp_stg_so', 'FULL', 5000, 1, '需求核验结果主表,进入 S1 贴源层', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
             FROM mdp_source s
             WHERE s.tenant_id=0 AND s.source_code='AIDOPDEV_MYSQL'
             LIMIT 1
@@ -111,9 +111,9 @@ public class S1MdpSyncTransformService : ITransient
         await _db.Ado.ExecuteCommandAsync(
             """
             INSERT INTO mdp_entity
-            (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, batch_size, status, remark)
+            (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, batch_size, status, remark, create_time, update_time)
             SELECT 0, s.id, 'S1_REQUIREMENT_EXAMINE_DETAIL', 'S1需求核验BOM明细', 'TABLE',
-                   'b_bom_child_examine', 'mdp_stg_so', 'FULL', 5000, 1, '需求核验BOM明细,进入 S1 贴源层和 DWD'
+                   'b_bom_child_examine', 'mdp_stg_so', 'FULL', 5000, 1, '需求核验BOM明细,进入 S1 贴源层和 DWD', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
             FROM mdp_source s
             WHERE s.tenant_id=0 AND s.source_code='AIDOPDEV_MYSQL'
             LIMIT 1
@@ -126,8 +126,8 @@ public class S1MdpSyncTransformService : ITransient
         await _db.Ado.ExecuteCommandAsync(
             """
             INSERT INTO mdp_entity
-            (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, incr_column, batch_size, status, remark)
-            SELECT 0, s.id, v.entity_code, v.entity_name, 'TABLE', v.source_table_name, 'mdp_stg_so', 'INCR', 'UpdateTime', 5000, 1, v.remark
+            (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, incr_column, batch_size, status, remark, create_time, update_time)
+            SELECT 0, s.id, v.entity_code, v.entity_name, 'TABLE', v.source_table_name, 'mdp_stg_so', 'INCR', 'UpdateTime', 5000, 1, v.remark, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
             FROM mdp_source s
             JOIN (
                 SELECT 'S1_PRODUCT_DESIGN' AS entity_code, 'S1产品设计主表' AS entity_name, 'ado_product_design' AS source_table_name, '产品设计主表,进入订单标准层' AS remark

+ 2 - 2
server/Plugins/Admin.NET.Plugin.AiDOP/Production/S2MdpSyncTransformService.cs

@@ -902,8 +902,8 @@ internal static class S2MdpDdl
         """,
         """
         INSERT INTO mdp_entity
-        (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, batch_size, status, remark)
-        SELECT 0, s.id, v.entity_code, v.entity_name, 'TABLE', v.source_table_name, 'mdp_stg_schedule', 'FULL', 5000, 1, v.remark
+        (tenant_id, source_id, entity_code, entity_name, entity_type, source_table_name, target_table_name, sync_mode, batch_size, status, remark, create_time, update_time)
+        SELECT 0, s.id, v.entity_code, v.entity_name, 'TABLE', v.source_table_name, 'mdp_stg_schedule', 'FULL', 5000, 1, v.remark, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
         FROM mdp_source s
         JOIN (
             SELECT 'S2_WORK_ORDER_MASTER' AS entity_code, 'S2工单主数据' AS entity_name, 'WorkOrdMaster' AS source_table_name, '工单主数据进入 S2 贴源层' AS remark