소스 검색

fix(s8): rebuild product design drawings with stage actual_days conservation

按 PRODUCT_DESIGN stage.actual_days 守恒重写 20 单产品设计图号 seed 与回灌 SQL:
SUM(drawing.actual_days) = stage.actual_days × drawing_count(简单平均守恒)。

守恒模型(5 类):
  A) pending(stage.status=pending)→ 3 std actual=NULL pending
  B) green 无非标(A=3)           → 3 std A green
  C) green 有非标(A=3)           → 6 std 1.25 green + 1 nstd 13.50 red, AVG=3.00
  D) red 无非标(A=5)             → 5 std A red
  E) red 有非标(A=5)             → 6 std 4.50 red + 1 nstd 8.00 red, AVG=5.00

非标超期显著(13.50/8.00 > KPI=3),但常规图号数量与周期摊平,TOTAL 平均守恒等于父
stage.actual_days;red 父级有 red 子级支撑,不再出现 SO-2026-004/010 这类父 red 但
子级全 green 的反差。

服务端 BuildProductDesignCategory 去 isNonStandard 守门,STANDARD/NON_STANDARD/TOTAL
三档统一返回真实 KpiDays/AvgActualDays/AchievementRate/Status,不再用 null 掩盖。

新增 UpdateScripts/1.0.144.sql:DELETE 旧 63 行 PRODUCT_DESIGN drawing(按 tenant=1/
factory=1/is_deleted=0/order_code IN 20 单严格限定)+ INSERT 新 106 行。

csproj patch+1 (1.0.143 → 1.0.144) 并注册 1.0.144.sql Copy 条目。

阶段 2 已在 aidopdev 完整冒烟:DB 写入后 18 可比订单 diff=0、2 pending 父子一致;
service 接口 5 单字节级 TOTAL=stage;UI 5 单(001/004/007/016/020)现场守恒一致。
YY968XX 4 달 전
부모
커밋
6134809056

+ 6 - 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.143</AssemblyVersion>
-    <FileVersion>1.0.143</FileVersion>
-    <Version>1.0.143</Version>
+    <AssemblyVersion>1.0.144</AssemblyVersion>
+    <FileVersion>1.0.144</FileVersion>
+    <Version>1.0.144</Version>
   </PropertyGroup>
 
   <ItemGroup>
@@ -91,6 +91,9 @@
     <None Update="UpdateScripts\1.0.143.sql">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
+    <None Update="UpdateScripts\1.0.144.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
 
   <ItemGroup>

+ 144 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.144.sql

@@ -0,0 +1,144 @@
+-- 1.0.144.sql
+-- S8-ORDER-CHAIN-PRODUCT-DESIGN-20ORDER-GENERATION-CONSISTENCY-AUDIT-1
+-- 重建 ado_s8_order_flow_product_design_drawing 数据,使 AVG(drawing.actual_days)=stage.actual_days 守恒。
+-- 关联前置:
+--   * S8OrderFlowProductDesignDrawingSeedData.cs 已重写为 DeriveLayout 守恒模型;
+--   * 服务层 BuildProductDesignCategory 已去 STANDARD/TOTAL 强制 null 守门。
+-- 守恒约束:
+--   AVG(drawing.actual_days WHERE order_code=X) = ado_s8_order_flow_stage.actual_days WHERE order_flow_code='PRODUCT_DESIGN'
+-- 守恒模型:
+--   A) pending  → 3 std NULL pending
+--   B) green 无非标 → 3 std A green
+--   C) green 有非标 → 6 std 1.25 green + 1 nstd 13.50 red, AVG=3.00
+--   D) red 无非标 → 5 std A red
+--   E) red 有非标 → 6 std 4.50 red + 1 nstd 8.00 red, AVG=5.00
+-- 总图号数:106 行;DELETE 旧 63 行 + INSERT 新 106 行。
+-- 授权范围:仅 aidopdev;仅 ado_s8_order_flow_product_design_drawing;仅 PRODUCT_DESIGN drawing。
+-- 幂等性:脚本两步顺序执行;重复运行第二次 DELETE 106 行 + INSERT 106 行,最终状态等同。
+--   * 不依赖临时表;不读写其它任何表。
+-- 安全边界:
+--   * DELETE 严格按 tenant_id=1 AND factory_id=1 AND is_deleted=0 AND order_code IN (SO-2026-001..020) 限定;
+--   * 不动 ado_s8_order_flow_stage / ado_s8_order_flow_order / 订单评审 substep/unit / 其它阶段表;
+--   * 无 ALTER;无 schema 变更;无 UPDATE。
+-- 2026-06-01
+
+-- 1) DELETE 旧产品设计图号(严格按 20 单 order_code IN 限定,不无条件清表)
+DELETE FROM ado_s8_order_flow_product_design_drawing
+ WHERE tenant_id = 1
+   AND factory_id = 1
+   AND is_deleted = 0
+   AND order_code IN ('SO-2026-001', 'SO-2026-002', 'SO-2026-003', 'SO-2026-004', 'SO-2026-005', 'SO-2026-006', 'SO-2026-007', 'SO-2026-008', 'SO-2026-009', 'SO-2026-010', 'SO-2026-011', 'SO-2026-012', 'SO-2026-013', 'SO-2026-014', 'SO-2026-015', 'SO-2026-016', 'SO-2026-017', 'SO-2026-018', 'SO-2026-019', 'SO-2026-020');
+
+-- 2) INSERT 新 106 行 drawing(守恒模型生成)
+INSERT INTO ado_s8_order_flow_product_design_drawing
+  (id, tenant_id, factory_id, order_code, drawing_no, product_type, product_quantity,
+   responsible_person, planned_start_date, planned_end_date,
+   actual_start_date, actual_end_date, kpi_days, actual_days,
+   is_achieved, status, sort_no, is_deleted, create_time, update_time)
+VALUES
+  (1329909130001, 1, 1, 'SO-2026-001', 'D-SO-2026-001-G01', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-24 21:00:00', 3.00, 4.50, 0, 'red', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130002, 1, 1, 'SO-2026-001', 'D-SO-2026-001-G02', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-24 21:00:00', 3.00, 4.50, 0, 'red', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130003, 1, 1, 'SO-2026-001', 'D-SO-2026-001-G03', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-24 21:00:00', 3.00, 4.50, 0, 'red', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130004, 1, 1, 'SO-2026-001', 'D-SO-2026-001-G04', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-24 21:00:00', 3.00, 4.50, 0, 'red', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130005, 1, 1, 'SO-2026-001', 'D-SO-2026-001-G05', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-24 21:00:00', 3.00, 4.50, 0, 'red', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130006, 1, 1, 'SO-2026-001', 'D-SO-2026-001-G06', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-24 21:00:00', 3.00, 4.50, 0, 'red', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130007, 1, 1, 'SO-2026-001', 'D-SO-2026-001-X01', 'NON_STANDARD', 2, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-28 09:00:00', 3.00, 8.00, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130008, 1, 1, 'SO-2026-002', 'D-SO-2026-002-G01', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130009, 1, 1, 'SO-2026-002', 'D-SO-2026-002-G02', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130010, 1, 1, 'SO-2026-002', 'D-SO-2026-002-G03', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130011, 1, 1, 'SO-2026-002', 'D-SO-2026-002-G04', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130012, 1, 1, 'SO-2026-002', 'D-SO-2026-002-G05', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130013, 1, 1, 'SO-2026-002', 'D-SO-2026-002-G06', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130014, 1, 1, 'SO-2026-002', 'D-SO-2026-002-X01', 'NON_STANDARD', 2, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130015, 1, 1, 'SO-2026-003', 'D-SO-2026-003-G01', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130016, 1, 1, 'SO-2026-003', 'D-SO-2026-003-G02', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130017, 1, 1, 'SO-2026-003', 'D-SO-2026-003-G03', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130018, 1, 1, 'SO-2026-003', 'D-SO-2026-003-G04', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130019, 1, 1, 'SO-2026-003', 'D-SO-2026-003-G05', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130020, 1, 1, 'SO-2026-003', 'D-SO-2026-003-G06', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130021, 1, 1, 'SO-2026-003', 'D-SO-2026-003-X01', 'NON_STANDARD', 2, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130022, 1, 1, 'SO-2026-004', 'D-SO-2026-004-G01', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130023, 1, 1, 'SO-2026-004', 'D-SO-2026-004-G02', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130024, 1, 1, 'SO-2026-004', 'D-SO-2026-004-G03', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130025, 1, 1, 'SO-2026-004', 'D-SO-2026-004-G04', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130026, 1, 1, 'SO-2026-004', 'D-SO-2026-004-G05', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130027, 1, 1, 'SO-2026-005', 'D-SO-2026-005-G01', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130028, 1, 1, 'SO-2026-005', 'D-SO-2026-005-G02', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130029, 1, 1, 'SO-2026-005', 'D-SO-2026-005-G03', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130030, 1, 1, 'SO-2026-005', 'D-SO-2026-005-G04', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130031, 1, 1, 'SO-2026-005', 'D-SO-2026-005-G05', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130032, 1, 1, 'SO-2026-006', 'D-SO-2026-006-G01', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130033, 1, 1, 'SO-2026-006', 'D-SO-2026-006-G02', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130034, 1, 1, 'SO-2026-006', 'D-SO-2026-006-G03', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130035, 1, 1, 'SO-2026-006', 'D-SO-2026-006-G04', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130036, 1, 1, 'SO-2026-006', 'D-SO-2026-006-G05', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130037, 1, 1, 'SO-2026-006', 'D-SO-2026-006-G06', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130038, 1, 1, 'SO-2026-006', 'D-SO-2026-006-X01', 'NON_STANDARD', 2, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130039, 1, 1, 'SO-2026-007', 'D-SO-2026-007-G01', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130040, 1, 1, 'SO-2026-007', 'D-SO-2026-007-G02', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130041, 1, 1, 'SO-2026-007', 'D-SO-2026-007-G03', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130042, 1, 1, 'SO-2026-007', 'D-SO-2026-007-G04', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130043, 1, 1, 'SO-2026-007', 'D-SO-2026-007-G05', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130044, 1, 1, 'SO-2026-007', 'D-SO-2026-007-G06', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130045, 1, 1, 'SO-2026-007', 'D-SO-2026-007-X01', 'NON_STANDARD', 2, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130046, 1, 1, 'SO-2026-008', 'D-SO-2026-008-G01', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130047, 1, 1, 'SO-2026-008', 'D-SO-2026-008-G02', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130048, 1, 1, 'SO-2026-008', 'D-SO-2026-008-G03', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130049, 1, 1, 'SO-2026-008', 'D-SO-2026-008-G04', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130050, 1, 1, 'SO-2026-008', 'D-SO-2026-008-G05', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130051, 1, 1, 'SO-2026-008', 'D-SO-2026-008-G06', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130052, 1, 1, 'SO-2026-008', 'D-SO-2026-008-X01', 'NON_STANDARD', 2, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130053, 1, 1, 'SO-2026-009', 'D-SO-2026-009-G01', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130054, 1, 1, 'SO-2026-009', 'D-SO-2026-009-G02', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130055, 1, 1, 'SO-2026-009', 'D-SO-2026-009-G03', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130056, 1, 1, 'SO-2026-010', 'D-SO-2026-010-G01', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130057, 1, 1, 'SO-2026-010', 'D-SO-2026-010-G02', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130058, 1, 1, 'SO-2026-010', 'D-SO-2026-010-G03', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130059, 1, 1, 'SO-2026-010', 'D-SO-2026-010-G04', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130060, 1, 1, 'SO-2026-010', 'D-SO-2026-010-G05', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-25 09:00:00', 3.00, 5.00, 0, 'red', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130061, 1, 1, 'SO-2026-011', 'D-SO-2026-011-G01', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130062, 1, 1, 'SO-2026-011', 'D-SO-2026-011-G02', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130063, 1, 1, 'SO-2026-011', 'D-SO-2026-011-G03', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130064, 1, 1, 'SO-2026-012', 'D-SO-2026-012-G01', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130065, 1, 1, 'SO-2026-012', 'D-SO-2026-012-G02', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130066, 1, 1, 'SO-2026-012', 'D-SO-2026-012-G03', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130067, 1, 1, 'SO-2026-012', 'D-SO-2026-012-G04', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130068, 1, 1, 'SO-2026-012', 'D-SO-2026-012-G05', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130069, 1, 1, 'SO-2026-012', 'D-SO-2026-012-G06', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130070, 1, 1, 'SO-2026-012', 'D-SO-2026-012-X01', 'NON_STANDARD', 2, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130071, 1, 1, 'SO-2026-013', 'D-SO-2026-013-G01', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130072, 1, 1, 'SO-2026-013', 'D-SO-2026-013-G02', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130073, 1, 1, 'SO-2026-013', 'D-SO-2026-013-G03', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130074, 1, 1, 'SO-2026-014', 'D-SO-2026-014-G01', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130075, 1, 1, 'SO-2026-014', 'D-SO-2026-014-G02', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130076, 1, 1, 'SO-2026-014', 'D-SO-2026-014-G03', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130077, 1, 1, 'SO-2026-015', 'D-SO-2026-015-G01', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130078, 1, 1, 'SO-2026-015', 'D-SO-2026-015-G02', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130079, 1, 1, 'SO-2026-015', 'D-SO-2026-015-G03', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-23 09:00:00', 3.00, 3.00, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130080, 1, 1, 'SO-2026-016', 'D-SO-2026-016-G01', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', NULL, 3.00, NULL, 0, 'pending', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130081, 1, 1, 'SO-2026-016', 'D-SO-2026-016-G02', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', NULL, 3.00, NULL, 0, 'pending', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130082, 1, 1, 'SO-2026-016', 'D-SO-2026-016-G03', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', NULL, 3.00, NULL, 0, 'pending', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130083, 1, 1, 'SO-2026-017', 'D-SO-2026-017-G01', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', NULL, 3.00, NULL, 0, 'pending', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130084, 1, 1, 'SO-2026-017', 'D-SO-2026-017-G02', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', NULL, 3.00, NULL, 0, 'pending', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130085, 1, 1, 'SO-2026-017', 'D-SO-2026-017-G03', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', NULL, 3.00, NULL, 0, 'pending', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130086, 1, 1, 'SO-2026-018', 'D-SO-2026-018-G01', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130087, 1, 1, 'SO-2026-018', 'D-SO-2026-018-G02', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130088, 1, 1, 'SO-2026-018', 'D-SO-2026-018-G03', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130089, 1, 1, 'SO-2026-018', 'D-SO-2026-018-G04', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130090, 1, 1, 'SO-2026-018', 'D-SO-2026-018-G05', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130091, 1, 1, 'SO-2026-018', 'D-SO-2026-018-G06', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130092, 1, 1, 'SO-2026-018', 'D-SO-2026-018-X01', 'NON_STANDARD', 2, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130093, 1, 1, 'SO-2026-019', 'D-SO-2026-019-G01', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130094, 1, 1, 'SO-2026-019', 'D-SO-2026-019-G02', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130095, 1, 1, 'SO-2026-019', 'D-SO-2026-019-G03', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130096, 1, 1, 'SO-2026-019', 'D-SO-2026-019-G04', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130097, 1, 1, 'SO-2026-019', 'D-SO-2026-019-G05', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130098, 1, 1, 'SO-2026-019', 'D-SO-2026-019-G06', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130099, 1, 1, 'SO-2026-019', 'D-SO-2026-019-X01', 'NON_STANDARD', 2, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130100, 1, 1, 'SO-2026-020', 'D-SO-2026-020-G01', 'STANDARD', 7, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 1, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130101, 1, 1, 'SO-2026-020', 'D-SO-2026-020-G02', 'STANDARD', 7, '刘振宇', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 2, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130102, 1, 1, 'SO-2026-020', 'D-SO-2026-020-G03', 'STANDARD', 7, '周启明', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 3, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130103, 1, 1, 'SO-2026-020', 'D-SO-2026-020-G04', 'STANDARD', 7, '李海峰', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 4, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130104, 1, 1, 'SO-2026-020', 'D-SO-2026-020-G05', 'STANDARD', 7, '陈思远', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 5, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130105, 1, 1, 'SO-2026-020', 'D-SO-2026-020-G06', 'STANDARD', 7, '王明华', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-04-21 15:00:00', 3.00, 1.25, 1, 'green', 6, 0, '2026-05-12 00:00:00', NULL),
+  (1329909130106, 1, 1, 'SO-2026-020', 'D-SO-2026-020-X01', 'NON_STANDARD', 2, '赵建国', '2026-04-20 09:00:00', '2026-04-23 09:00:00', '2026-04-20 09:00:00', '2026-05-03 21:00:00', 3.00, 13.50, 0, 'red', 7, 0, '2026-05-12 00:00:00', NULL);

+ 113 - 85
server/Plugins/Admin.NET.Plugin.AiDOP/SeedData/S8OrderFlowProductDesignDrawingSeedData.cs

@@ -3,19 +3,26 @@ using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
 namespace Admin.NET.Plugin.AiDOP.SeedData;
 
 /// <summary>
-/// S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:S8 订单链路产品设计阶段基准业务初始化数据种子。
-/// 20 单 × 63 图号;按业务口径修正:
-///   1) COUNT(DISTINCT drawing_no) = 63;STANDARD=52 / NON_STANDARD=11
-///   2) SUM(product_quantity ALL) = 382;STANDARD=357 / NON_STANDARD=25
-///   3) PRODUCT_DESIGN 阶段统一 KPI=3 天:STANDARD 与 NON_STANDARD 的 kpi_days 均为 3
-///   4) NON_STANDARD 图号 actual_days 全部 > 3 → is_achieved=false / status='red'
-///   5) STANDARD 51 张图号 actual_days ≤ 3 → is_achieved=true / status='green';1 张超期 actual=4.50 → red
-///   6) AVG(actual_days WHERE product_type='STANDARD')     落在 [1.17, 1.21]
-///   7) AVG(actual_days WHERE product_type='NON_STANDARD') 落在 [9.25, 9.31]
-/// 图号编码:常规 D-{OrderCode}-G{NN};非标 D-{OrderCode}-X{NN}(绑定 SO-2026-001..020 真实 OrderCode)。
-/// 责任人字段承载具体设计师姓名(产品设计阶段基准业务初始化数据,6 人按全表全局递增序号 seq 循环分配,确保 6 桶全覆盖)。
-/// 默认基线展示(顶部 2.5 / 98 + 分类汇总 354/28/382 PPT 口径)由 snapshot 表与前端基线数据共同支撑;
-/// 本表负责单订单态与多订单态的图号粒度真实数据。
+/// S8-ORDER-CHAIN-PRODUCT-DESIGN-20ORDER-GENERATION-CONSISTENCY-AUDIT-1:
+/// S8 订单链路产品设计图号种子,按订单父级 actual_days 守恒生成(不再使用全局聚合口径)。
+///
+/// 守恒约束(核心业务规则):
+///   AVG(drawing.actual_days WHERE order_code = X)
+///   = ado_s8_order_flow_stage.actual_days WHERE order_code = X AND order_flow_code = 'PRODUCT_DESIGN'
+/// 即 SUM(all drawing.actual_days) = stage.actual_days × drawing_count(简单平均,非台数加权)。
+///
+/// 守恒模型(按 stage.actual_days × 是否有非标 5 类分类):
+///   A) pending(stage.status=pending)            → 3 张 STANDARD,actual_days=NULL,status=pending
+///   B) green 无非标(stage.actual_days=A=3)      → 3 张 STANDARD,actual_days=A=3.00,status=green
+///   C) green 有非标(A=3)                        → 6 张 STANDARD (1.25 green) + 1 张 NON_STANDARD (13.50 red)
+///                                                    AVG=(6×1.25 + 13.50)/7 = 21/7 = 3.00;非标显著超期,常规摊平
+///   D) red 无非标(A=5)                          → 5 张 STANDARD,actual_days=A=5.00,status=red
+///   E) red 有非标(A=5)                          → 6 张 STANDARD (4.50 red) + 1 张 NON_STANDARD (8.00 red)
+///                                                    AVG=(6×4.50 + 8.00)/7 = 35/7 = 5.00;全部 red 支撑父 red
+///
+/// 图号编码:常规 D-{OrderCode}-G{NN};非标 D-{OrderCode}-X{NN}。
+/// 责任人按全局序号 seq 在 6 桶(李海峰 / 陈思远 / 王明华 / 赵建国 / 刘振宇 / 周启明)循环。
+/// 总图号数:106 = A(2×3) + B(5×3) + C(9×7) + D(3×5) + E(1×7) = 6 + 15 + 63 + 15 + 7。
 /// </summary>
 [IncreSeed]
 public class S8OrderFlowProductDesignDrawingSeedData
@@ -27,19 +34,22 @@ public class S8OrderFlowProductDesignDrawingSeedData
 
 internal static class S8OrderFlowProductDesignDrawingDataset
 {
-    /// <summary>图号 id 基址(与其他 S8 种子号段隔离)。</summary>
+    /// <summary>图号 id 基址(与其他 S8 种子号段隔离;本表新设计行数 106,使用 IdBase+1..106)。</summary>
     internal const long IdBase = 1329909130000L;
 
     internal const string ProductTypeStandard = "STANDARD";
     internal const string ProductTypeNonStandard = "NON_STANDARD";
 
-    /// <summary>常规产品 KPI(天)。PRODUCT_DESIGN 阶段统一标准。</summary>
-    internal const decimal StandardKpiDays = 3.00m;
+    /// <summary>PRODUCT_DESIGN 阶段统一 KPI=3 天,常规与非标共用同一阈值。</summary>
+    internal const decimal KpiDays = 3.00m;
 
-    /// <summary>非标产品 KPI(天)。与常规产品同阶段标准。</summary>
-    internal const decimal NonStandardKpiDays = 3.00m;
+    /// <summary>常规图号统一 product_quantity=7(设计阶段每张图号承载 7 台)。</summary>
+    internal const int StandardQuantity = 7;
 
-    /// <summary>产品设计阶段基准业务初始化数据:设计师姓名清单(6 人按全表全局递增序号 seq 循环分配,sort_no 仅为订单内序号,无法保证 6 桶全覆盖)。</summary>
+    /// <summary>非标图号统一 product_quantity=2(非标少量定制)。</summary>
+    internal const int NonStandardQuantity = 2;
+
+    /// <summary>责任人 6 桶;按全局递增序号 seq 循环分配,sort_no 仅订单内序号。</summary>
     private static readonly string[] Designers =
     {
         "李海峰",
@@ -51,105 +61,115 @@ internal static class S8OrderFlowProductDesignDrawingDataset
     };
 
     /// <summary>
-    /// 每订单 (常规图号数, 非标图号数)。20 行合计 52 / 11;其中 4 单 4 图、16 单 3 图。
-    /// 非标集中在大客户、P1 优先级与 in_progress 订单上,与业务直觉一致。
+    /// 每订单是否含非标产品(与 stage 派生 layout 共同决定 std/nstd 数量)。
+    /// 11 单含非标(沿用原业务直觉:大客户 / P1 优先级 / completed 订单),9 单无非标。
+    /// pending 父级订单(016, 017)按守恒约束统一不分配非标(产品设计阶段尚未进入或刚开始)。
     /// </summary>
-    private static readonly (int StdCount, int NonStdCount)[] PerOrderConfig =
+    private static readonly bool[] HasNonStandardByIdx =
     {
         // SO-2026-001..005
-        (3, 1), (3, 1), (3, 1), (3, 0), (3, 0),
+        true,  true,  true,  false, false,
         // SO-2026-006..010
-        (2, 1), (2, 1), (2, 1), (3, 0), (3, 0),
+        true,  true,  true,  false, false,
         // SO-2026-011..015
-        (3, 0), (2, 1), (3, 0), (3, 0), (3, 0),
+        false, true,  false, false, false,
         // SO-2026-016..020
-        (3, 0), (2, 1), (2, 1), (2, 1), (2, 1),
+        false, false, true,  true,  true,
     };
 
-    /// <summary>52 张常规图号 spec:合计 actual_days=61.88、qty=357、1 张超期 (qty=3)。</summary>
-    private static readonly DrawingSpec[] StandardSequence = BuildStandardSequence();
+    /// <summary>单订单图号布局:std/nstd 数量 + 各自 actual_days + 各自 status。null actual=pending。</summary>
+    internal readonly record struct OrderLayout(
+        int StdN,
+        int NstdN,
+        decimal? StdActualDays,
+        decimal? NstdActualDays,
+        string StdStatus,
+        string NstdStatus);
 
-    /// <summary>11 张非标图号 spec:合计 actual_days=102.08、qty=25;全部 actual_days &gt; 3 → 全部不达标 red。</summary>
-    private static readonly DrawingSpec[] NonStandardSequence = BuildNonStandardSequence();
+    /// <summary>
+    /// 按 PRODUCT_DESIGN stage 派生订单布局。守恒前提:SUM(actual_days) = stage.actual_days × drawing_count。
+    /// stage seed 引用:S8OrderFlowStageDataset.BuildLifecycleValues(spec)[1] 即 PRODUCT_DESIGN 阶段。
+    /// </summary>
+    internal static OrderLayout DeriveLayout(S8OrderFlowDataset.OrderSpec spec, int idx)
+    {
+        var lifecycle = S8OrderFlowStageDataset.BuildLifecycleValues(spec);
+        var stage = lifecycle[1]; // 索引 1 = PRODUCT_DESIGN(lifecycle[0]=ORDER_REVIEW_PLAN_CALC)
 
-    /// <summary>单张图号的回卷规格:actual_days / quantity / is_achieved / status。</summary>
-    internal readonly record struct DrawingSpec(decimal ActualDays, int Quantity, bool IsAchieved, string Status);
+        // 类别 A:pending 父级 → 3 std NULL pending
+        if (stage.status == "pending")
+        {
+            return new OrderLayout(3, 0, null, null, "pending", "pending");
+        }
 
-    private static DrawingSpec[] BuildStandardSequence()
-    {
-        // 52 张分布:24×(1.13, qty=7) + 24×(1.12, qty=7) + 2×(1.13, qty=6) + 1×(1.12, qty=6) + 1×(4.50, qty=3, red)
-        // actual_days 合计 = 24×1.13 + 24×1.12 + 2×1.13 + 1×1.12 + 4.50
-        //                  = 27.12 + 26.88 + 2.26 + 1.12 + 4.50 = 61.88  → avg 1.190 (在 [1.17, 1.21])
-        // quantity 合计    = 24×7 + 24×7 + 2×6 + 1×6 + 3 = 168 + 168 + 12 + 6 + 3 = 357
-        var seq = new DrawingSpec[52];
-        for (var i = 0; i < 24; i++) seq[i] = new DrawingSpec(1.13m, 7, true, "green");
-        for (var i = 24; i < 48; i++) seq[i] = new DrawingSpec(1.12m, 7, true, "green");
-        seq[48] = new DrawingSpec(1.13m, 6, true, "green");
-        seq[49] = new DrawingSpec(1.13m, 6, true, "green");
-        seq[50] = new DrawingSpec(1.12m, 6, true, "green");
-        // 唯一一张超期常规图号:actual=4.50 > kpi=3 → (4.5-3)/3 = 0.50 > 0.20 → red
-        seq[51] = new DrawingSpec(4.50m, 3, false, "red");
-        return seq;
-    }
+        var A = stage.actualDays;
+        var hasNonStandard = HasNonStandardByIdx[idx];
 
-    private static DrawingSpec[] BuildNonStandardSequence()
-    {
-        // 11 张分布:5×(8.34, qty=1) + 4×(8.34, qty=2) + 2×(13.51, qty=6)
-        // actual_days 合计 = 9×8.34 + 2×13.51 = 75.06 + 27.02 = 102.08 → avg 9.28 (在 [9.25, 9.31])
-        // quantity 合计    = 5×1 + 4×2 + 2×6 = 5 + 8 + 12 = 25
-        // 非标 KPI=3 后,所有 actual_days ≥ 8.34 > 3 → 全部 is_achieved=false / status='red'
-        var seq = new DrawingSpec[11];
-        for (var i = 0; i < 5; i++) seq[i] = new DrawingSpec(8.34m, 1, false, "red");
-        for (var i = 5; i < 9; i++) seq[i] = new DrawingSpec(8.34m, 2, false, "red");
-        seq[9] = new DrawingSpec(13.51m, 6, false, "red");
-        seq[10] = new DrawingSpec(13.51m, 6, false, "red");
-        return seq;
+        if (A <= KpiDays)
+        {
+            // 类别 C:green 有非标 → 6 std 1.25 + 1 nstd 13.50;AVG=(6×1.25 + 13.50)/7=3.00
+            if (hasNonStandard)
+            {
+                return new OrderLayout(6, 1, 1.25m, 13.50m, "green", "red");
+            }
+            // 类别 B:green 无非标 → 3 std 各 A green;AVG=A
+            return new OrderLayout(3, 0, A, null, "green", "green");
+        }
+        else
+        {
+            // 类别 E:red 有非标 → 6 std 4.50 + 1 nstd 8.00;AVG=(6×4.50 + 8.00)/7=5.00;全 red
+            if (hasNonStandard)
+            {
+                return new OrderLayout(6, 1, 4.50m, 8.00m, "red", "red");
+            }
+            // 类别 D:red 无非标 → 5 std 各 A red;AVG=A;多张图号都超期支撑父 red
+            return new OrderLayout(5, 0, A, null, "red", "red");
+        }
     }
 
     public static IEnumerable<AdoS8OrderFlowProductDesignDrawing> BuildDrawings()
     {
-        int stdCursor = 0, nonStdCursor = 0;
         long seq = 0;
+        // 图号粒度计划开始 = release_at + 5 天(ORDER_REVIEW KPI=5 天结束后进入 PRODUCT_DESIGN)
+        var plannedStart = S8OrderFlowDataset.ReleaseBase.AddDays(5);
+        var plannedEnd = plannedStart.AddDays((double)KpiDays);
 
         for (var i = 0; i < S8OrderFlowDataset.Specs.Length; i++)
         {
             var orderSpec = S8OrderFlowDataset.Specs[i];
-            var (stdN, nonStdN) = PerOrderConfig[i];
-
-            // 图号粒度计划开始 = release_at + 5 天(ORDER_REVIEW KPI=5 天结束后进入 PRODUCT_DESIGN)。
-            // 所有图号同基准开始,actualEnd 由 actualDays 派生,保证 actualEnd - actualStart 严格等于 actualDays。
-            var plannedStart = S8OrderFlowDataset.ReleaseBase.AddDays(5);
+            var layout = DeriveLayout(orderSpec, i);
 
             var sortNo = 0;
 
-            for (var g = 0; g < stdN; g++)
+            for (var g = 0; g < layout.StdN; g++)
             {
                 sortNo++;
-                var spec = StandardSequence[stdCursor++];
                 yield return BuildDrawing(
                     seq: ++seq,
                     orderSpec: orderSpec,
                     sortNo: sortNo,
                     drawingNo: $"D-{orderSpec.OrderCode}-G{g + 1:D2}",
                     productType: ProductTypeStandard,
-                    kpiDays: StandardKpiDays,
+                    productQuantity: StandardQuantity,
                     plannedStart: plannedStart,
-                    spec: spec);
+                    plannedEnd: plannedEnd,
+                    actualDays: layout.StdActualDays,
+                    status: layout.StdStatus);
             }
 
-            for (var x = 0; x < nonStdN; x++)
+            for (var x = 0; x < layout.NstdN; x++)
             {
                 sortNo++;
-                var spec = NonStandardSequence[nonStdCursor++];
                 yield return BuildDrawing(
                     seq: ++seq,
                     orderSpec: orderSpec,
                     sortNo: sortNo,
                     drawingNo: $"D-{orderSpec.OrderCode}-X{x + 1:D2}",
                     productType: ProductTypeNonStandard,
-                    kpiDays: NonStandardKpiDays,
+                    productQuantity: NonStandardQuantity,
                     plannedStart: plannedStart,
-                    spec: spec);
+                    plannedEnd: plannedEnd,
+                    actualDays: layout.NstdActualDays,
+                    status: layout.NstdStatus);
             }
         }
     }
@@ -160,14 +180,22 @@ internal static class S8OrderFlowProductDesignDrawingDataset
         int sortNo,
         string drawingNo,
         string productType,
-        decimal kpiDays,
+        int productQuantity,
         DateTime plannedStart,
-        DrawingSpec spec)
+        DateTime plannedEnd,
+        decimal? actualDays,
+        string status)
     {
-        // 计划区间按 KPI 推算;非标 KPI 与常规 KPI 同阶段标准 3 天,但非标设计周期允许 actual_days 较长。
-        var plannedEnd = plannedStart.AddDays((double)kpiDays);
-        var actualStart = plannedStart;
-        var actualEnd = actualStart.AddDays((double)spec.ActualDays);
+        // 完成态:actualStart=plannedStart,actualEnd=plannedStart + actualDays
+        // pending:actualStart=plannedStart 表示已起步但未完工,actualEnd=NULL(与 stage seed pending 路径一致)
+        DateTime? actualStart = plannedStart;
+        DateTime? actualEnd = actualDays.HasValue
+            ? plannedStart.AddDays((double)actualDays.Value)
+            : (DateTime?)null;
+
+        // is_achieved:actual_days <= kpi_days;pending 时为 false(entity bool 不可 null)
+        var isAchieved = actualDays.HasValue && actualDays.Value <= KpiDays;
+
         var responsible = Designers[(seq - 1) % Designers.Length];
 
         return new AdoS8OrderFlowProductDesignDrawing
@@ -178,16 +206,16 @@ internal static class S8OrderFlowProductDesignDrawingDataset
             OrderCode = orderSpec.OrderCode,
             DrawingNo = drawingNo,
             ProductType = productType,
-            ProductQuantity = spec.Quantity,
+            ProductQuantity = productQuantity,
             ResponsiblePerson = responsible,
             PlannedStartDate = plannedStart,
             PlannedEndDate = plannedEnd,
             ActualStartDate = actualStart,
             ActualEndDate = actualEnd,
-            KpiDays = kpiDays,
-            ActualDays = spec.ActualDays,
-            IsAchieved = spec.IsAchieved,
-            Status = spec.Status,
+            KpiDays = KpiDays,
+            ActualDays = actualDays,
+            IsAchieved = isAchieved,
+            Status = status,
             SortNo = sortNo,
             IsDeleted = false,
             CreateTime = S8OrderFlowDataset.CreatedAt,

+ 12 - 11
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/OrderFlow/S8OrderFlowService.cs

@@ -821,11 +821,12 @@ public class S8OrderFlowService : ITransient
         var actualDays = rows.Where(r => r.ActualDays.HasValue).Select(r => r.ActualDays!.Value).ToList();
         var rate = totalQty == 0 ? 0m : (decimal)achievedQty / totalQty;
 
-        // S8-ORDER-CHAIN-PRODUCT-DESIGN-PPT-STATIC-AND-SINGLE-ORDER-ALIGN-1:分类汇总按业务口径差异化输出。
-        // STANDARD / TOTAL:KPI、平均设计周期、达成率均返回 null,由前端展示 --。
-        // NON_STANDARD:返回真实 KPI=3 天、actual_days 算术平均、quantity 加权达成率与对应状态色。
-        var isNonStandard = productType == ProductDesignTypeNonStandard;
-
+        // S8-ORDER-CHAIN-PRODUCT-DESIGN-20ORDER-GENERATION-CONSISTENCY-AUDIT-1:
+        // STANDARD / NON_STANDARD / TOTAL 三档统一返回真实指标,不再用 null 掩盖。
+        // - KpiDays:始终返回常量 KPI=3,方便前端展示阈值。
+        // - AvgActualDays:actualDays 简单平均(pending 行已经被 HasValue 过滤)。TOTAL 平均 == 父 stage.actual_days(守恒)。
+        // - AchievementRate:以 product_quantity 加权达成率(与 Overall 一致),保留业务台数权重直觉。
+        // - Status:达成率 ≥0.95 green / ≥0.80 yellow / 否则 red;无完工行(all pending)时返回空串。
         return new AdoS8OrderFlowProductDesignCategorySummaryDto
         {
             ProductType = productType,
@@ -833,12 +834,12 @@ public class S8OrderFlowService : ITransient
             DrawingCount = rows.Select(r => r.DrawingNo).Distinct(StringComparer.Ordinal).Count(),
             TotalQuantity = totalQty,
             Ratio = grandTotalQty == 0 ? 0m : (decimal)totalQty / grandTotalQty,
-            KpiDays = isNonStandard ? kpiDays : (decimal?)null,
-            AvgActualDays = isNonStandard
-                ? (actualDays.Count == 0 ? (decimal?)null : actualDays.Average())
-                : (decimal?)null,
-            AchievementRate = isNonStandard ? rate : (decimal?)null,
-            Status = isNonStandard ? ClassifyProductDesignCategoryStatus(rate, totalQty) : string.Empty,
+            KpiDays = kpiDays,
+            AvgActualDays = actualDays.Count == 0 ? (decimal?)null : actualDays.Average(),
+            AchievementRate = rate,
+            Status = actualDays.Count == 0
+                ? string.Empty
+                : ClassifyProductDesignCategoryStatus(rate, totalQty),
         };
     }