Преглед изворни кода

feat(s8): t1a add order flow entity skeleton (order/stage/snapshot)

ORDER-FLOW-S8-INTEGRATED-DOMAIN-RESET-1 t1a:
- Add AdoS8OrderFlowOrder (25 fields, 3 KPI cols, no exception_count预存)
- Add AdoS8OrderFlowStage (22 fields, order_flow_code UPPER + name redundant)
- Add AdoS8OrderFlowSnapshot (15 fields, longtext stage_snapshots_json)
- Register 3 entities in Startup.cs CodeFirst InitTables (+4 lines)
- CodeFirst verified on aidopdev: 3 tables, 11 indexes, 0 rows
- No SeedData / Service / Controller / DTO / frontend touched
YY968XX пре 5 дана
родитељ
комит
65cae3ef5b

+ 95 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Entity/S8/OrderFlow/AdoS8OrderFlowOrder.cs

@@ -0,0 +1,95 @@
+namespace Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
+
+/// <summary>
+/// ORDER-FLOW-S8-INTEGRATED-DOMAIN-RESET-1 t1a:S8 订单执行链路主档(正式领域表)。
+/// 替代 ado_demo_order_flow;order_code 为业务键;不保留异常数预存字段,
+/// 异常数由 ado_s8_exception 实时聚合,order 表只持有 response/processing/loss KPI。
+/// </summary>
+[SugarTable("ado_s8_order_flow_order", "S8 订单执行链路主档")]
+[SugarIndex("uk_order_flow_order_code", nameof(TenantId), OrderByType.Asc, nameof(FactoryId), OrderByType.Asc, nameof(OrderCode), OrderByType.Asc, IsUnique = true)]
+[SugarIndex("idx_order_flow_order_current_flow", nameof(TenantId), OrderByType.Asc, nameof(FactoryId), OrderByType.Asc, nameof(CurrentOrderFlowCode), OrderByType.Asc)]
+[SugarIndex("idx_order_flow_order_customer", nameof(TenantId), OrderByType.Asc, nameof(FactoryId), OrderByType.Asc, nameof(CustomerCode), OrderByType.Asc)]
+public class AdoS8OrderFlowOrder
+{
+    [SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true, ColumnDataType = "bigint")]
+    public long Id { get; set; }
+
+    [SugarColumn(ColumnName = "tenant_id", ColumnDataType = "bigint")]
+    public long TenantId { get; set; }
+
+    [SugarColumn(ColumnName = "factory_id", ColumnDataType = "bigint")]
+    public long FactoryId { get; set; }
+
+    /// <summary>订单业务键,全局唯一(tenant/factory 维度)。</summary>
+    [SugarColumn(ColumnName = "order_code", Length = 64)]
+    public string OrderCode { get; set; } = string.Empty;
+
+    [SugarColumn(ColumnName = "product_name", Length = 128)]
+    public string ProductName { get; set; } = string.Empty;
+
+    [SugarColumn(ColumnName = "product_line", Length = 32)]
+    public string ProductLine { get; set; } = string.Empty;
+
+    [SugarColumn(ColumnName = "customer_code", Length = 64)]
+    public string CustomerCode { get; set; } = string.Empty;
+
+    [SugarColumn(ColumnName = "customer_name", Length = 128)]
+    public string CustomerName { get; set; } = string.Empty;
+
+    /// <summary>KA / SMB / MICRO。</summary>
+    [SugarColumn(ColumnName = "customer_type", Length = 16)]
+    public string CustomerType { get; set; } = "KA";
+
+    [SugarColumn(ColumnName = "region", Length = 32)]
+    public string Region { get; set; } = string.Empty;
+
+    /// <summary>P1 / P2 / P3。</summary>
+    [SugarColumn(ColumnName = "priority", Length = 16)]
+    public string Priority { get; set; } = "P2";
+
+    /// <summary>completed / in_progress。</summary>
+    [SugarColumn(ColumnName = "workflow_status", Length = 32)]
+    public string WorkflowStatus { get; set; } = "in_progress";
+
+    /// <summary>UPPER ORDER_FLOW node_code(5 选 1):ORDER_REVIEW_PLAN_CALC / PRODUCT_DESIGN / MATERIAL_PURCHASE / BODY_PRODUCTION / FINAL_ASSEMBLY_DELIVERY。白名单由 service 层校验。</summary>
+    [SugarColumn(ColumnName = "current_order_flow_code", Length = 64)]
+    public string CurrentOrderFlowCode { get; set; } = string.Empty;
+
+    [SugarColumn(ColumnName = "release_at")]
+    public DateTime ReleaseAt { get; set; }
+
+    [SugarColumn(ColumnName = "target_cycle_days", DecimalDigits = 1, Length = 6)]
+    public decimal TargetCycleDays { get; set; }
+
+    [SugarColumn(ColumnName = "actual_cycle_days", DecimalDigits = 1, Length = 6, IsNullable = true)]
+    public decimal? ActualCycleDays { get; set; }
+
+    /// <summary>KPI:响应时长(分钟)。来源 = 主档业务字段,不从 ado_s8_exception 派生。</summary>
+    [SugarColumn(ColumnName = "response_minutes", IsNullable = true)]
+    public int? ResponseMinutes { get; set; }
+
+    /// <summary>KPI:处理时长(分钟)。来源 = 主档业务字段。</summary>
+    [SugarColumn(ColumnName = "processing_minutes", IsNullable = true)]
+    public int? ProcessingMinutes { get; set; }
+
+    /// <summary>KPI:总损失时长(分钟)。来源 = 主档业务字段。</summary>
+    [SugarColumn(ColumnName = "total_loss_minutes", IsNullable = true)]
+    public int? TotalLossMinutes { get; set; }
+
+    /// <summary>PPT / DEMO / PROD。SO-2026-001 = PPT;其余 19 单 = DEMO。</summary>
+    [SugarColumn(ColumnName = "scenario_code", Length = 16)]
+    public string ScenarioCode { get; set; } = "DEMO";
+
+    /// <summary>SEED / IMPORT / AGG。t2a seed 全部为 SEED。</summary>
+    [SugarColumn(ColumnName = "data_source", Length = 16)]
+    public string DataSource { get; set; } = "SEED";
+
+    [SugarColumn(ColumnName = "created_at")]
+    public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+    [SugarColumn(ColumnName = "updated_at", IsNullable = true)]
+    public DateTime? UpdatedAt { get; set; }
+
+    [SugarColumn(ColumnName = "is_deleted", ColumnDataType = "boolean")]
+    public bool IsDeleted { get; set; }
+}

+ 66 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Entity/S8/OrderFlow/AdoS8OrderFlowSnapshot.cs

@@ -0,0 +1,66 @@
+namespace Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
+
+/// <summary>
+/// ORDER-FLOW-S8-INTEGRATED-DOMAIN-RESET-1 t1a:S8 订单执行链路 baseline 聚合快照。
+/// 替代 ado_demo_order_flow_snapshot;同时替代 service 层任何 baseline 硬编码。
+/// service 读取协议:scope_code=BASELINE_PPT → 取本表行;scope_code=CURRENT_FILTERED → 实时聚合明细表。
+/// 任何 baseline 数值(如总订单数 / 平均时长 / 5 阶段聚合)严禁出现在 service 字面量。
+/// </summary>
+[SugarTable("ado_s8_order_flow_snapshot", "S8 订单执行链路聚合快照")]
+[SugarIndex("uk_order_flow_snapshot_code", nameof(TenantId), OrderByType.Asc, nameof(FactoryId), OrderByType.Asc, nameof(SnapshotCode), OrderByType.Asc, IsUnique = true)]
+[SugarIndex("idx_order_flow_snapshot_scope", nameof(TenantId), OrderByType.Asc, nameof(FactoryId), OrderByType.Asc, nameof(ScopeCode), OrderByType.Asc, nameof(IsDeleted), OrderByType.Asc)]
+public class AdoS8OrderFlowSnapshot
+{
+    [SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true, ColumnDataType = "bigint")]
+    public long Id { get; set; }
+
+    [SugarColumn(ColumnName = "tenant_id", ColumnDataType = "bigint")]
+    public long TenantId { get; set; }
+
+    [SugarColumn(ColumnName = "factory_id", ColumnDataType = "bigint")]
+    public long FactoryId { get; set; }
+
+    /// <summary>快照业务键,唯一。t2c seed 首条值固定为 CHAIN_AGGREGATE_BASELINE。</summary>
+    [SugarColumn(ColumnName = "snapshot_code", Length = 64)]
+    public string SnapshotCode { get; set; } = string.Empty;
+
+    /// <summary>BASELINE_PPT / BASELINE_DEMO。t2c seed 首条值固定为 BASELINE_PPT。</summary>
+    [SugarColumn(ColumnName = "scope_code", Length = 32)]
+    public string ScopeCode { get; set; } = string.Empty;
+
+    [SugarColumn(ColumnName = "total_orders")]
+    public int TotalOrders { get; set; }
+
+    [SugarColumn(ColumnName = "total_customers")]
+    public int TotalCustomers { get; set; }
+
+    [SugarColumn(ColumnName = "avg_response_minutes", DecimalDigits = 2, Length = 8)]
+    public decimal AvgResponseMinutes { get; set; }
+
+    [SugarColumn(ColumnName = "avg_processing_minutes", DecimalDigits = 2, Length = 8)]
+    public decimal AvgProcessingMinutes { get; set; }
+
+    [SugarColumn(ColumnName = "avg_loss_minutes", DecimalDigits = 2, Length = 8)]
+    public decimal AvgLossMinutes { get; set; }
+
+    /// <summary>5 阶段聚合 JSON。每项含 orderFlowCode/orderFlowName/kpiAvgDays/actualAvgDays/onTimeRate(int %)/green/yellow/red/pending。t2c seed 写入 BASELINE_PPT 真值。</summary>
+    [SugarColumn(ColumnName = "stage_snapshots_json", ColumnDataType = "longtext")]
+    public string StageSnapshotsJson { get; set; } = string.Empty;
+
+    /// <summary>PPT / DEMO。</summary>
+    [SugarColumn(ColumnName = "scenario_code", Length = 16)]
+    public string ScenarioCode { get; set; } = "PPT";
+
+    /// <summary>SEED / IMPORT / AGG。</summary>
+    [SugarColumn(ColumnName = "data_source", Length = 16)]
+    public string DataSource { get; set; } = "SEED";
+
+    [SugarColumn(ColumnName = "created_at")]
+    public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+    [SugarColumn(ColumnName = "updated_at", IsNullable = true)]
+    public DateTime? UpdatedAt { get; set; }
+
+    [SugarColumn(ColumnName = "is_deleted", ColumnDataType = "boolean")]
+    public bool IsDeleted { get; set; }
+}

+ 84 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Entity/S8/OrderFlow/AdoS8OrderFlowStage.cs

@@ -0,0 +1,84 @@
+namespace Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
+
+/// <summary>
+/// ORDER-FLOW-S8-INTEGRATED-DOMAIN-RESET-1 t1a:S8 订单执行链路五阶段执行明细。
+/// 替代 ado_demo_order_flow_stage;order_flow_code 只承载 UPPER ORDER_FLOW node_code;
+/// order_code / order_flow_name 冗余保留以便聚合与免 join 展示。
+/// </summary>
+[SugarTable("ado_s8_order_flow_stage", "S8 订单执行链路阶段明细")]
+[SugarIndex("uk_order_flow_stage_order_flow", nameof(OrderId), OrderByType.Asc, nameof(OrderFlowCode), OrderByType.Asc, IsUnique = true)]
+[SugarIndex("idx_order_flow_stage_flow_status", nameof(TenantId), OrderByType.Asc, nameof(FactoryId), OrderByType.Asc, nameof(OrderFlowCode), OrderByType.Asc, nameof(Status), OrderByType.Asc)]
+[SugarIndex("idx_order_flow_stage_order_code", nameof(TenantId), OrderByType.Asc, nameof(FactoryId), OrderByType.Asc, nameof(OrderCode), OrderByType.Asc)]
+public class AdoS8OrderFlowStage
+{
+    [SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true, ColumnDataType = "bigint")]
+    public long Id { get; set; }
+
+    /// <summary>外键 → ado_s8_order_flow_order.id。</summary>
+    [SugarColumn(ColumnName = "order_id", ColumnDataType = "bigint")]
+    public long OrderId { get; set; }
+
+    /// <summary>冗余订单业务键,便于按 order_code 聚合。</summary>
+    [SugarColumn(ColumnName = "order_code", Length = 64)]
+    public string OrderCode { get; set; } = string.Empty;
+
+    /// <summary>UPPER ORDER_FLOW node_code(5 选 1)。白名单由 service 层校验。</summary>
+    [SugarColumn(ColumnName = "order_flow_code", Length = 64)]
+    public string OrderFlowCode { get; set; } = string.Empty;
+
+    /// <summary>展示名冗余(评审/排产/测算 等),避免前端每次 join dimension_node。</summary>
+    [SugarColumn(ColumnName = "order_flow_name", Length = 32)]
+    public string OrderFlowName { get; set; } = string.Empty;
+
+    [SugarColumn(ColumnName = "owner_dept", Length = 64, IsNullable = true)]
+    public string? OwnerDept { get; set; }
+
+    [SugarColumn(ColumnName = "sort_no")]
+    public int SortNo { get; set; }
+
+    [SugarColumn(ColumnName = "planned_days", DecimalDigits = 1, Length = 5)]
+    public decimal PlannedDays { get; set; }
+
+    [SugarColumn(ColumnName = "actual_days", DecimalDigits = 1, Length = 5, IsNullable = true)]
+    public decimal? ActualDays { get; set; }
+
+    [SugarColumn(ColumnName = "target_at")]
+    public DateTime TargetAt { get; set; }
+
+    [SugarColumn(ColumnName = "actual_start_at", IsNullable = true)]
+    public DateTime? ActualStartAt { get; set; }
+
+    [SugarColumn(ColumnName = "actual_end_at", IsNullable = true)]
+    public DateTime? ActualEndAt { get; set; }
+
+    /// <summary>green / yellow / red / pending。</summary>
+    [SugarColumn(ColumnName = "status", Length = 16)]
+    public string Status { get; set; } = "pending";
+
+    [SugarColumn(ColumnName = "node_variance_days", DecimalDigits = 1, Length = 5, IsNullable = true)]
+    public decimal? NodeVarianceDays { get; set; }
+
+    [SugarColumn(ColumnName = "cumulative_variance_days", DecimalDigits = 1, Length = 5, IsNullable = true)]
+    public decimal? CumulativeVarianceDays { get; set; }
+
+    [SugarColumn(ColumnName = "scenario_code", Length = 16)]
+    public string ScenarioCode { get; set; } = "DEMO";
+
+    [SugarColumn(ColumnName = "data_source", Length = 16)]
+    public string DataSource { get; set; } = "SEED";
+
+    [SugarColumn(ColumnName = "tenant_id", ColumnDataType = "bigint")]
+    public long TenantId { get; set; }
+
+    [SugarColumn(ColumnName = "factory_id", ColumnDataType = "bigint")]
+    public long FactoryId { get; set; }
+
+    [SugarColumn(ColumnName = "created_at")]
+    public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+    [SugarColumn(ColumnName = "updated_at", IsNullable = true)]
+    public DateTime? UpdatedAt { get; set; }
+
+    [SugarColumn(ColumnName = "is_deleted", ColumnDataType = "boolean")]
+    public bool IsDeleted { get; set; }
+}

+ 4 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Startup.cs

@@ -6,6 +6,7 @@ using Admin.NET.Plugin.AiDOP.Entity.S0.Quality;
 using Admin.NET.Plugin.AiDOP.Entity.S0.Sales;
 using Admin.NET.Plugin.AiDOP.Entity.S0.Supply;
 using Admin.NET.Plugin.AiDOP.Entity.S8;
+using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
 using Admin.NET.Plugin.AiDOP.Order;
 using Admin.NET.Plugin.AiDOP.Infrastructure;
 using Microsoft.AspNetCore.Builder;
@@ -142,6 +143,9 @@ public class Startup : AppStartup
                 typeof(AdoS8ConfigDraft),
                 typeof(AdoS8MonitorObject),
                 typeof(AdoS8MonitorMetric),
+                typeof(AdoS8OrderFlowOrder),
+                typeof(AdoS8OrderFlowStage),
+                typeof(AdoS8OrderFlowSnapshot),
                 typeof(ContractReview),
                 typeof(ContractReviewFlow),
                 typeof(ProductDesign),