feat: initialize manufacturing progress dashboard

This commit is contained in:
czc
2026-07-13 18:07:59 +08:00
commit 658a23b630
87 changed files with 19195 additions and 0 deletions
@@ -0,0 +1,172 @@
using DongfangHydro.Dashboard.Api.Domain;
using Microsoft.EntityFrameworkCore;
namespace DongfangHydro.Dashboard.Api.Data;
public sealed class DashboardDbContext(DbContextOptions<DashboardDbContext> options)
: DbContext(options)
{
public DbSet<ProductionOrder> ProductionOrders => Set<ProductionOrder>();
public DbSet<ProductionNode> ProductionNodes => Set<ProductionNode>();
public DbSet<ProductionTrendPoint> ProductionTrendPoints => Set<ProductionTrendPoint>();
public DbSet<RiskEvent> RiskEvents => Set<RiskEvent>();
public DbSet<ProductionLine> ProductionLines => Set<ProductionLine>();
public DbSet<Partner> Partners => Set<Partner>();
public DbSet<MaterialQuota> MaterialQuotas => Set<MaterialQuota>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProductionOrder>(entity =>
{
entity.ToTable("ProductionOrders");
entity.HasKey(order => order.Id);
entity.HasIndex(order => order.Code);
entity.HasIndex(order => new { order.Status, order.RiskLevel, order.PlannedEnd });
entity.Property(order => order.Code).HasMaxLength(40);
entity.Property(order => order.ProductName).HasMaxLength(200);
entity.Property(order => order.DataSource).HasMaxLength(32);
entity.Property(order => order.SourceDocumentCode).HasMaxLength(80);
entity.Property(order => order.ProjectName).HasMaxLength(200);
entity.Property(order => order.DrawingProductName).HasMaxLength(240);
entity.Property(order => order.SourceFileName).HasMaxLength(260);
entity.Property(order => order.SourceFileHash).HasMaxLength(64);
entity.HasIndex(order => order.SourceDocumentCode)
.IsUnique()
.HasFilter("[SourceDocumentCode] <> ''");
entity.Property(order => order.Status).HasMaxLength(32);
entity.Property(order => order.RiskLevel).HasMaxLength(32);
entity.Property(order => order.LineName).HasMaxLength(80);
entity.Property(order => order.Owner).HasMaxLength(80);
entity.Property(order => order.ThumbnailKey).HasMaxLength(40);
entity.Property(order => order.RowVersion).IsRowVersion();
entity.HasOne<ProductionLine>()
.WithMany()
.HasForeignKey(order => order.LineId)
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity<ProductionNode>(entity =>
{
entity.ToTable("ProductionNodes");
entity.HasKey(node => node.Id);
entity.HasIndex(node => new { node.OrderId, node.ParentNodeId, node.SortOrder });
entity.HasIndex(node => new { node.OrderId, node.NodeType, node.RiskLevel, node.Status });
entity.Property(node => node.Code).HasMaxLength(60);
entity.Property(node => node.OperationCode).HasMaxLength(60);
entity.Property(node => node.MaterialCode).HasMaxLength(80);
entity.Property(node => node.Name).HasMaxLength(240);
entity.Property(node => node.SourceSequence).HasMaxLength(40);
entity.Property(node => node.Specification).HasMaxLength(240);
entity.Property(node => node.Material).HasMaxLength(120);
entity.Property(node => node.UnitWeight).HasPrecision(18, 4);
entity.Property(node => node.TotalWeight).HasPrecision(18, 4);
entity.Property(node => node.UnitWeightText).HasMaxLength(80);
entity.Property(node => node.TotalWeightText).HasMaxLength(80);
entity.Property(node => node.BomQuantity).HasPrecision(18, 4);
entity.Property(node => node.BomQuantityText).HasMaxLength(80);
entity.Property(node => node.Remark).HasMaxLength(500);
entity.Property(node => node.SourceSheet).HasMaxLength(40);
entity.Property(node => node.NodeType).HasMaxLength(32);
entity.Property(node => node.SupplyType).HasMaxLength(32);
entity.Property(node => node.Status).HasMaxLength(32);
entity.Property(node => node.RiskLevel).HasMaxLength(32);
entity.Property(node => node.DelayReason).HasMaxLength(500);
entity.Property(node => node.Owner).HasMaxLength(100);
entity.Property(node => node.Vendor).HasMaxLength(120);
entity.Property(node => node.StationName).HasMaxLength(120);
entity.Property(node => node.VisualKey).HasMaxLength(40);
entity.Property(node => node.RowVersion).IsRowVersion();
entity.HasAlternateKey(node => new { node.OrderId, node.Id });
entity.HasOne<ProductionOrder>()
.WithMany()
.HasForeignKey(node => node.OrderId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasOne<ProductionNode>()
.WithMany()
.HasForeignKey(node => new { node.OrderId, node.ParentNodeId })
.HasPrincipalKey(node => new { node.OrderId, node.Id })
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<ProductionTrendPoint>(entity =>
{
entity.ToTable("ProductionTrendPoints");
entity.HasKey(point => point.Id);
entity.HasIndex(point => new { point.OrderId, point.SampleTime }).IsDescending(false, true);
entity.HasOne<ProductionOrder>()
.WithMany()
.HasForeignKey(point => point.OrderId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<RiskEvent>(entity =>
{
entity.ToTable("RiskEvents");
entity.HasKey(riskEvent => riskEvent.Id);
entity.HasIndex(riskEvent => new { riskEvent.OrderId, riskEvent.OccurredAt }).IsDescending(false, true);
entity.Property(riskEvent => riskEvent.OrderCode).HasMaxLength(40);
entity.Property(riskEvent => riskEvent.NodeName).HasMaxLength(240);
entity.Property(riskEvent => riskEvent.RiskLevel).HasMaxLength(32);
entity.Property(riskEvent => riskEvent.Message).HasMaxLength(500);
entity.Property(riskEvent => riskEvent.HandlingStatus).HasMaxLength(32);
entity.HasOne<ProductionOrder>()
.WithMany()
.HasForeignKey(riskEvent => riskEvent.OrderId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasOne<ProductionNode>()
.WithMany()
.HasForeignKey(riskEvent => new { riskEvent.OrderId, riskEvent.NodeId })
.HasPrincipalKey(node => new { node.OrderId, node.Id })
.OnDelete(DeleteBehavior.NoAction);
});
modelBuilder.Entity<MaterialQuota>(entity =>
{
entity.ToTable("MaterialQuotas");
entity.HasKey(item => item.Id);
entity.HasIndex(item => new { item.OrderId, item.SourceSheet, item.SourceRow }).IsUnique();
entity.HasIndex(item => new { item.OrderId, item.Category, item.MaterialCode });
entity.Property(item => item.Category).HasMaxLength(80);
entity.Property(item => item.SourceSequence).HasMaxLength(40);
entity.Property(item => item.MaterialCode).HasMaxLength(80);
entity.Property(item => item.MaterialName).HasMaxLength(240);
entity.Property(item => item.Specification).HasMaxLength(240);
entity.Property(item => item.Unit).HasMaxLength(24);
entity.Property(item => item.Quantity).HasPrecision(18, 4);
entity.Property(item => item.NetWeight).HasPrecision(18, 4);
entity.Property(item => item.ConsumptionQuota).HasPrecision(18, 4);
entity.Property(item => item.QuantityText).HasMaxLength(80);
entity.Property(item => item.NetWeightText).HasMaxLength(80);
entity.Property(item => item.ConsumptionQuotaText).HasMaxLength(80);
entity.Property(item => item.Brand).HasMaxLength(120);
entity.Property(item => item.Remark).HasMaxLength(500);
entity.Property(item => item.SourceSheet).HasMaxLength(40);
entity.HasOne<ProductionOrder>()
.WithMany()
.HasForeignKey(item => item.OrderId)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<ProductionLine>(entity =>
{
entity.ToTable("ProductionLines");
entity.HasKey(line => line.Id);
entity.HasIndex(line => line.Code).IsUnique();
entity.Property(line => line.Code).HasMaxLength(40);
entity.Property(line => line.Name).HasMaxLength(80);
entity.Property(line => line.Owner).HasMaxLength(80);
});
modelBuilder.Entity<Partner>(entity =>
{
entity.ToTable("Partners");
entity.HasKey(partner => partner.Id);
entity.HasIndex(partner => partner.Code).IsUnique();
entity.Property(partner => partner.Code).HasMaxLength(40);
entity.Property(partner => partner.Name).HasMaxLength(120);
entity.Property(partner => partner.PartnerType).HasMaxLength(32);
entity.Property(partner => partner.ContactName).HasMaxLength(80);
entity.Property(partner => partner.ContactPhone).HasMaxLength(32);
});
}
}
@@ -0,0 +1,368 @@
using DongfangHydro.Dashboard.Api.Domain;
using DongfangHydro.Dashboard.Api.Services;
using Microsoft.EntityFrameworkCore;
namespace DongfangHydro.Dashboard.Api.Data;
public sealed class DashboardSeeder(
DashboardDbContext dbContext,
ProgressAggregationService aggregationService)
{
private static readonly string[] ProcessNames = ["备料齐套", "生产装配", "检验入库"];
private static readonly OrderBlueprint[] Orders =
[
new("MO-260708-001", "青峪口尾水单向门机 2×160/10", 1200, "总装一线", "周敏", 68, 4.3, "industrial-pc"),
new("MO-260708-002", "电站尾水2×160kN/100kN单向门式启闭机", 860, "总装二线", "李澈", 82, 2.8, "workstation"),
new("MO-260708-003", "主起升机构", 420, "高配小批线", "陈嘉", 54, -1.2, "workstation"),
new("MO-260708-004", "100kN回转吊", 1500, "总装三线", "罗岚", 43, -3.1, "aio"),
new("MO-260708-005", "门架", 2100, "柔性装配线", "宋一", 76, 1.6, "industrial-pc"),
new("MO-260708-006", "大车行走机构", 640, "精密装配线", "韩策", 61, -0.8, "edge-box"),
];
private static readonly PartBlueprint[] Parts =
[
new("主起升机构", "self_made", "重装车间", "自产工段", "fixture",
[
new("卷扬机构", "self_made", "起升装配组", "自产工段", "chassis"),
new("滑轮组", "outsourced", "机加协作组", "东方重工协作厂", "thermal"),
new("制动装置", "purchased", "采购一组", "华东液压", "power"),
]),
new("100kN回转吊", "outsourced", "回转装配组", "西南重装", "chassis",
[
new("回转支承", "purchased", "采购二组", "洛轴供应链", "chassis"),
new("起升卷筒", "self_made", "卷筒制造组", "自产工段", "fixture"),
new("吊钩组", "outsourced", "外协质检组", "川重锻造", "generic"),
]),
new("门架", "self_made", "结构车间", "自产工段", "mainboard",
[
new("主梁结构", "self_made", "铆焊一组", "自产工段", "mainboard"),
new("支腿结构", "self_made", "铆焊二组", "自产工段", "mainboard"),
new("连接平台", "outsourced", "结构外协组", "青峪钢构", "generic"),
]),
new("大车行走机构", "self_made", "行走机构组", "自产工段", "chassis",
[
new("行走台车", "self_made", "台车装配组", "自产工段", "chassis"),
new("轨道夹持器", "purchased", "采购三组", "水工制动", "fixture"),
new("驱动减速机", "purchased", "传动采购组", "国机传动", "power"),
]),
new("门机电气控制系统", "purchased", "电气车间", "东方电控", "power",
[
new("PLC控制柜", "self_made", "电控装配组", "自产工段", "power"),
new("电缆卷筒", "outsourced", "电缆协作组", "长江电缆", "cable"),
new("限位与监测装置", "purchased", "仪控采购组", "水工智控", "chip"),
]),
];
public async Task SeedAsync(CancellationToken cancellationToken)
{
if (await dbContext.ProductionOrders.AnyAsync(cancellationToken))
{
return;
}
var lines = Orders
.Select((order, index) => new ProductionLine
{
Id = Guid.NewGuid(),
Code = $"LINE-{index + 1:00}",
Name = order.LineName,
Owner = order.Owner,
})
.ToList();
dbContext.ProductionLines.AddRange(lines);
dbContext.Partners.AddRange(
new Partner { Id = Guid.NewGuid(), Code = "SUP-001", Name = "东方重工协作厂", PartnerType = "outsourcer" },
new Partner { Id = Guid.NewGuid(), Code = "SUP-002", Name = "华东液压", PartnerType = "supplier" },
new Partner { Id = Guid.NewGuid(), Code = "SUP-003", Name = "水工智控", PartnerType = "supplier" });
var now = DateTimeOffset.UtcNow;
for (var orderIndex = 0; orderIndex < Orders.Length; orderIndex++)
{
var blueprint = Orders[orderIndex];
var order = new ProductionOrder
{
Id = Guid.NewGuid(),
Code = blueprint.Code,
ProductName = blueprint.ProductName,
DataSource = "demo",
BatchQty = blueprint.BatchQty,
RequiredQty = blueprint.BatchQty,
PlannedStart = new DateTime(2026, 7, 1).AddDays(orderIndex % 4),
PlannedEnd = new DateTime(2026, 7, 14).AddDays(orderIndex),
LineId = lines[orderIndex].Id,
LineName = blueprint.LineName,
Owner = blueprint.Owner,
DailyDelta = blueprint.DailyDelta,
ThumbnailKey = blueprint.ThumbnailKey,
CreatedAt = now.AddDays(-10 - orderIndex),
UpdatedAt = now,
RowVersion = Guid.NewGuid().ToByteArray(),
};
var nodes = BuildNodes(order, blueprint, orderIndex, now);
aggregationService.Recalculate(order, nodes);
order.PlanAchievement = Math.Clamp(order.Progress + 8 - order.DelayDays * 1.5, 0, 120);
dbContext.ProductionOrders.Add(order);
dbContext.ProductionNodes.AddRange(nodes);
dbContext.ProductionTrendPoints.AddRange(BuildTrend(order, orderIndex, now));
dbContext.RiskEvents.AddRange(BuildRiskEvents(order, nodes, now));
}
await dbContext.SaveChangesAsync(cancellationToken);
}
private static List<ProductionNode> BuildNodes(
ProductionOrder order,
OrderBlueprint blueprint,
int orderIndex,
DateTimeOffset now)
{
var nodes = new List<ProductionNode>();
var root = CreateNode(
order,
null,
"ROOT",
order.ProductName,
0,
"order",
"self_made",
order.BatchQty,
0,
order.Owner,
"东方水利",
blueprint.ThumbnailKey,
0,
order.PlannedStart!.Value,
order.PlannedEnd!.Value,
now);
nodes.Add(root);
for (var partIndex = 0; partIndex < Parts.Length; partIndex++)
{
var part = Parts[partIndex];
var partNode = CreateNode(
order,
root.Id,
$"P-{partIndex + 1:00}",
part.Name,
1,
"part",
part.SupplyType,
order.BatchQty,
partIndex,
part.Owner,
part.Vendor,
part.VisualKey,
partIndex,
order.PlannedStart!.Value.AddDays(partIndex),
order.PlannedEnd!.Value.AddDays(partIndex - Parts.Length),
now);
nodes.Add(partNode);
for (var componentIndex = 0; componentIndex < part.Components.Length; componentIndex++)
{
var component = part.Components[componentIndex];
var componentNode = CreateNode(
order,
partNode.Id,
$"C-{partIndex + 1:00}-{componentIndex + 1:00}",
component.Name,
2,
"component",
component.SupplyType,
order.BatchQty,
componentIndex,
component.Owner,
component.Vendor,
component.VisualKey,
componentIndex,
partNode.PlannedStart!.Value.AddDays(componentIndex),
partNode.PlannedEnd!.Value.AddDays(componentIndex - 2),
now);
nodes.Add(componentNode);
for (var processIndex = 0; processIndex < ProcessNames.Length; processIndex++)
{
var signature = orderIndex * 17 + partIndex * 11 + componentIndex * 7 + processIndex * 5;
var progress = Math.Clamp(blueprint.BaseProgress + signature % 29 - 14 - processIndex * 4, 3, 100);
var critical = signature % 13 == 0;
var warning = !critical && (signature % 5 == 0 || progress < 45);
var delayDays = critical ? 3 + signature % 4 : warning ? 1 : 0;
var status = progress >= 100
? "done"
: critical && processIndex == 2
? "blocked"
: delayDays > 0
? "delayed"
: "in_progress";
var risk = critical ? "critical" : warning ? "warning" : "normal";
var requiredQty = order.BatchQty;
var completedQty = (int)Math.Round(requiredQty * progress / 100d, MidpointRounding.AwayFromZero);
var processNode = CreateNode(
order,
componentNode.Id,
$"OP-{(processIndex + 1) * 10:00}",
$"{component.Name} - {ProcessNames[processIndex]}",
3,
"process",
component.SupplyType,
requiredQty,
processIndex,
component.Owner,
component.Vendor,
processIndex == 2 ? "package" : component.VisualKey,
processIndex,
componentNode.PlannedStart!.Value.AddDays(processIndex),
componentNode.PlannedEnd!.Value.AddDays(processIndex - 2),
now);
processNode.CompletedQty = completedQty;
processNode.DefectQty = Math.Min(completedQty, risk == "critical" ? Math.Max(1, completedQty / 50) : completedQty / 250);
processNode.Progress = progress;
processNode.Status = status;
processNode.RiskLevel = risk;
processNode.DelayDays = delayDays;
processNode.DelayReason = DelayReason(risk, component.SupplyType, ProcessNames[processIndex]);
processNode.ActualStart = progress > 0 ? processNode.PlannedStart : null;
processNode.ActualEnd = progress >= 100 ? processNode.PlannedEnd : null;
nodes.Add(processNode);
}
}
}
return nodes;
}
private static ProductionNode CreateNode(
ProductionOrder order,
Guid? parentId,
string code,
string name,
int level,
string nodeType,
string supplyType,
int requiredQty,
int codeIndex,
string owner,
string vendor,
string visualKey,
int sortOrder,
DateTime plannedStart,
DateTime plannedEnd,
DateTimeOffset now)
{
return new ProductionNode
{
Id = Guid.NewGuid(),
OrderId = order.Id,
ParentNodeId = parentId,
Code = code,
OperationCode = code,
MaterialCode = $"MAT-{order.Code[^3..]}-{level}{codeIndex + 1:00}",
Name = name,
Level = level,
NodeType = nodeType,
SupplyType = supplyType,
RequiredQty = requiredQty,
Owner = owner,
Vendor = vendor,
StationName = $"{owner}-{sortOrder + 1}",
VisualKey = visualKey,
SortOrder = sortOrder,
PlannedStart = plannedStart,
PlannedEnd = plannedEnd,
UpdatedAt = now,
RowVersion = Guid.NewGuid().ToByteArray(),
};
}
private static IEnumerable<ProductionTrendPoint> BuildTrend(
ProductionOrder order,
int orderIndex,
DateTimeOffset now)
{
for (var index = 0; index < 12; index++)
{
var completion = Math.Clamp(order.Progress - (11 - index) * 2 + (index + orderIndex) % 3, 0, 100);
var actual = (int)Math.Round(order.RequiredQty * completion / 100d);
var planned = Math.Max(actual, (int)Math.Round(order.RequiredQty * Math.Min(100, completion + 8) / 100d));
yield return new ProductionTrendPoint
{
Id = Guid.NewGuid(),
OrderId = order.Id,
SampleTime = now.AddMinutes((index - 11) * 8),
Completion = completion,
Risk = Math.Max(1, order.DelayDays + 11 - index),
PlannedQty = planned,
ActualQty = actual,
Achievement = planned == 0 ? 0 : Math.Min(120, actual * 100d / planned),
};
}
}
private static IEnumerable<RiskEvent> BuildRiskEvents(
ProductionOrder order,
IReadOnlyCollection<ProductionNode> nodes,
DateTimeOffset now)
{
return nodes
.Where(node => node.RiskLevel != "normal" || node.DelayDays > 0)
.OrderByDescending(node => node.RiskLevel == "critical")
.ThenByDescending(node => node.DelayDays)
.Take(8)
.Select((node, index) => new RiskEvent
{
Id = Guid.NewGuid(),
OrderId = order.Id,
NodeId = node.Id,
OrderCode = order.Code,
NodeName = node.Name,
RiskLevel = node.RiskLevel,
Message = string.IsNullOrWhiteSpace(node.DelayReason)
? $"计划偏差 {Math.Max(1, node.DelayDays)} 天,需要复核节拍"
: node.DelayReason,
HandlingStatus = "processing",
OccurredAt = now.AddMinutes(-index),
});
}
private static string DelayReason(string riskLevel, string supplyType, string processName)
{
if (riskLevel == "normal")
{
return string.Empty;
}
return supplyType switch
{
"outsourced" => $"{processName}外协回货节拍低于计划",
"purchased" => $"{processName}供应到料存在批次差异",
_ => $"{processName}工序良率波动,需要复检",
};
}
private sealed record OrderBlueprint(
string Code,
string ProductName,
int BatchQty,
string LineName,
string Owner,
int BaseProgress,
double DailyDelta,
string ThumbnailKey);
private sealed record PartBlueprint(
string Name,
string SupplyType,
string Owner,
string Vendor,
string VisualKey,
ComponentBlueprint[] Components);
private sealed record ComponentBlueprint(
string Name,
string SupplyType,
string Owner,
string Vendor,
string VisualKey);
}
@@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore;
namespace DongfangHydro.Dashboard.Api.Data;
public static class DatabaseInitializer
{
public static async Task InitializeAsync(WebApplication app)
{
var autoMigrate = app.Configuration.GetValue("Database:AutoMigrate", false);
var seed = app.Configuration.GetValue("Database:Seed", false);
if (!autoMigrate && !seed)
{
return;
}
await using var scope = app.Services.CreateAsyncScope();
var dbContext = scope.ServiceProvider.GetRequiredService<DashboardDbContext>();
if (autoMigrate)
{
if (dbContext.Database.IsRelational())
{
await dbContext.Database.MigrateAsync();
}
else
{
await dbContext.Database.EnsureCreatedAsync();
}
}
if (seed)
{
await scope.ServiceProvider.GetRequiredService<DashboardSeeder>().SeedAsync(CancellationToken.None);
}
}
}
@@ -0,0 +1,457 @@
// <auto-generated />
using System;
using DongfangHydro.Dashboard.Api.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace DongfangHydro.Dashboard.Api.Data.Migrations
{
[DbContext(typeof(DashboardDbContext))]
[Migration("20260710025438_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.20")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.Partner", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("ContactName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("ContactPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("PartnerType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("Partners", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionLine", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ProductionLines", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("ActualEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("ActualStart")
.HasColumnType("datetime2");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<int>("DefectQty")
.HasColumnType("int");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<string>("DelayReason")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<string>("MaterialCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("NodeType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("OperationCode")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ParentNodeId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime>("PlannedStart")
.HasColumnType("datetime2");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<int>("SortOrder")
.HasColumnType("int");
b.Property<string>("StationName")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("SupplyType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Vendor")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("VisualKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.HasKey("Id");
b.HasIndex("OrderId", "ParentNodeId", "SortOrder");
b.HasIndex("OrderId", "NodeType", "RiskLevel", "Status");
b.ToTable("ProductionNodes", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<int>("BatchQty")
.HasColumnType("int");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<double>("DailyDelta")
.HasColumnType("float");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<Guid?>("LineId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LineName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<double>("PlanAchievement")
.HasColumnType("float");
b.Property<DateTime>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime>("PlannedStart")
.HasColumnType("datetime2");
b.Property<string>("ProductName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("ThumbnailKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.HasIndex("LineId");
b.HasIndex("Status", "RiskLevel", "PlannedEnd");
b.ToTable("ProductionOrders", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<double>("Achievement")
.HasColumnType("float");
b.Property<int>("ActualQty")
.HasColumnType("int");
b.Property<int>("Completion")
.HasColumnType("int");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<int>("PlannedQty")
.HasColumnType("int");
b.Property<int>("Risk")
.HasColumnType("int");
b.Property<DateTimeOffset>("SampleTime")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("OrderId", "SampleTime")
.IsDescending(false, true);
b.ToTable("ProductionTrendPoints", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("HandlingStatus")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Message")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid>("NodeId")
.HasColumnType("uniqueidentifier");
b.Property<string>("NodeName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<DateTimeOffset>("OccurredAt")
.HasColumnType("datetimeoffset");
b.Property<string>("OrderCode")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("OrderId", "NodeId");
b.HasIndex("OrderId", "OccurredAt")
.IsDescending(false, true);
b.ToTable("RiskEvents", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "ParentNodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionLine", null)
.WithMany()
.HasForeignKey("LineId")
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "NodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,266 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DongfangHydro.Dashboard.Api.Data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Partners",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Code = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
Name = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false),
PartnerType = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
ContactName = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
ContactPhone = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Partners", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ProductionLines",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Code = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
Name = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
Owner = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductionLines", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ProductionOrders",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Code = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
ProductName = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
BatchQty = table.Column<int>(type: "int", nullable: false),
RequiredQty = table.Column<int>(type: "int", nullable: false),
CompletedQty = table.Column<int>(type: "int", nullable: false),
Progress = table.Column<int>(type: "int", nullable: false),
Status = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
RiskLevel = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
DelayDays = table.Column<int>(type: "int", nullable: false),
PlannedStart = table.Column<DateTime>(type: "datetime2", nullable: false),
PlannedEnd = table.Column<DateTime>(type: "datetime2", nullable: false),
LineId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LineName = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
Owner = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
PlanAchievement = table.Column<double>(type: "float", nullable: false),
DailyDelta = table.Column<double>(type: "float", nullable: false),
ThumbnailKey = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
UpdatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
RowVersion = table.Column<byte[]>(type: "rowversion", rowVersion: true, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductionOrders", x => x.Id);
table.ForeignKey(
name: "FK_ProductionOrders_ProductionLines_LineId",
column: x => x.LineId,
principalTable: "ProductionLines",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
});
migrationBuilder.CreateTable(
name: "ProductionNodes",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
OrderId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ParentNodeId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Code = table.Column<string>(type: "nvarchar(60)", maxLength: 60, nullable: false),
OperationCode = table.Column<string>(type: "nvarchar(60)", maxLength: 60, nullable: false),
MaterialCode = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
Name = table.Column<string>(type: "nvarchar(240)", maxLength: 240, nullable: false),
Level = table.Column<int>(type: "int", nullable: false),
NodeType = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
SupplyType = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
RequiredQty = table.Column<int>(type: "int", nullable: false),
CompletedQty = table.Column<int>(type: "int", nullable: false),
DefectQty = table.Column<int>(type: "int", nullable: false),
Progress = table.Column<int>(type: "int", nullable: false),
Status = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
RiskLevel = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
DelayDays = table.Column<int>(type: "int", nullable: false),
DelayReason = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
PlannedStart = table.Column<DateTime>(type: "datetime2", nullable: false),
PlannedEnd = table.Column<DateTime>(type: "datetime2", nullable: false),
ActualStart = table.Column<DateTime>(type: "datetime2", nullable: true),
ActualEnd = table.Column<DateTime>(type: "datetime2", nullable: true),
Owner = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Vendor = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false),
StationName = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false),
VisualKey = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
SortOrder = table.Column<int>(type: "int", nullable: false),
UpdatedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
RowVersion = table.Column<byte[]>(type: "rowversion", rowVersion: true, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductionNodes", x => x.Id);
table.UniqueConstraint("AK_ProductionNodes_OrderId_Id", x => new { x.OrderId, x.Id });
table.ForeignKey(
name: "FK_ProductionNodes_ProductionNodes_OrderId_ParentNodeId",
columns: x => new { x.OrderId, x.ParentNodeId },
principalTable: "ProductionNodes",
principalColumns: new[] { "OrderId", "Id" },
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_ProductionNodes_ProductionOrders_OrderId",
column: x => x.OrderId,
principalTable: "ProductionOrders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ProductionTrendPoints",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
OrderId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
SampleTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
Completion = table.Column<int>(type: "int", nullable: false),
Risk = table.Column<int>(type: "int", nullable: false),
PlannedQty = table.Column<int>(type: "int", nullable: false),
ActualQty = table.Column<int>(type: "int", nullable: false),
Achievement = table.Column<double>(type: "float", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductionTrendPoints", x => x.Id);
table.ForeignKey(
name: "FK_ProductionTrendPoints_ProductionOrders_OrderId",
column: x => x.OrderId,
principalTable: "ProductionOrders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RiskEvents",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
OrderId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
NodeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
OrderCode = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
NodeName = table.Column<string>(type: "nvarchar(240)", maxLength: 240, nullable: false),
RiskLevel = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
Message = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
HandlingStatus = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
OccurredAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RiskEvents", x => x.Id);
table.ForeignKey(
name: "FK_RiskEvents_ProductionNodes_OrderId_NodeId",
columns: x => new { x.OrderId, x.NodeId },
principalTable: "ProductionNodes",
principalColumns: new[] { "OrderId", "Id" });
table.ForeignKey(
name: "FK_RiskEvents_ProductionOrders_OrderId",
column: x => x.OrderId,
principalTable: "ProductionOrders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Partners_Code",
table: "Partners",
column: "Code",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ProductionLines_Code",
table: "ProductionLines",
column: "Code",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ProductionNodes_OrderId_NodeType_RiskLevel_Status",
table: "ProductionNodes",
columns: new[] { "OrderId", "NodeType", "RiskLevel", "Status" });
migrationBuilder.CreateIndex(
name: "IX_ProductionNodes_OrderId_ParentNodeId_SortOrder",
table: "ProductionNodes",
columns: new[] { "OrderId", "ParentNodeId", "SortOrder" });
migrationBuilder.CreateIndex(
name: "IX_ProductionOrders_Code",
table: "ProductionOrders",
column: "Code",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ProductionOrders_LineId",
table: "ProductionOrders",
column: "LineId");
migrationBuilder.CreateIndex(
name: "IX_ProductionOrders_Status_RiskLevel_PlannedEnd",
table: "ProductionOrders",
columns: new[] { "Status", "RiskLevel", "PlannedEnd" });
migrationBuilder.CreateIndex(
name: "IX_ProductionTrendPoints_OrderId_SampleTime",
table: "ProductionTrendPoints",
columns: new[] { "OrderId", "SampleTime" },
descending: new[] { false, true });
migrationBuilder.CreateIndex(
name: "IX_RiskEvents_OrderId_NodeId",
table: "RiskEvents",
columns: new[] { "OrderId", "NodeId" });
migrationBuilder.CreateIndex(
name: "IX_RiskEvents_OrderId_OccurredAt",
table: "RiskEvents",
columns: new[] { "OrderId", "OccurredAt" },
descending: new[] { false, true });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Partners");
migrationBuilder.DropTable(
name: "ProductionTrendPoints");
migrationBuilder.DropTable(
name: "RiskEvents");
migrationBuilder.DropTable(
name: "ProductionNodes");
migrationBuilder.DropTable(
name: "ProductionOrders");
migrationBuilder.DropTable(
name: "ProductionLines");
}
}
}
@@ -0,0 +1,652 @@
// <auto-generated />
using System;
using DongfangHydro.Dashboard.Api.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace DongfangHydro.Dashboard.Api.Data.Migrations
{
[DbContext(typeof(DashboardDbContext))]
[Migration("20260710095939_ImportRealBom")]
partial class ImportRealBom
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.20")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.MaterialQuota", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Brand")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("Category")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<decimal?>("ConsumptionQuota")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("ConsumptionQuotaText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("MaterialCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("MaterialName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<decimal?>("NetWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("NetWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<decimal?>("Quantity")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("QuantityText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Remark")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("SourceRow")
.HasColumnType("int");
b.Property<string>("SourceSequence")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("SourceSheet")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("Specification")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("Unit")
.IsRequired()
.HasMaxLength(24)
.HasColumnType("nvarchar(24)");
b.HasKey("Id");
b.HasIndex("OrderId", "Category", "MaterialCode");
b.HasIndex("OrderId", "SourceSheet", "SourceRow")
.IsUnique();
b.ToTable("MaterialQuotas", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.Partner", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("ContactName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("ContactPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("PartnerType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("Partners", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionLine", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ProductionLines", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("ActualEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("ActualStart")
.HasColumnType("datetime2");
b.Property<decimal?>("BomQuantity")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("BomQuantityText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<int>("DefectQty")
.HasColumnType("int");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<string>("DelayReason")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<string>("Material")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("MaterialCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("NodeType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("OperationCode")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ParentNodeId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("PlannedStart")
.HasColumnType("datetime2");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<string>("Remark")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<int>("SortOrder")
.HasColumnType("int");
b.Property<int>("SourceRow")
.HasColumnType("int");
b.Property<string>("SourceSequence")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("SourceSheet")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("Specification")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("StationName")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("SupplyType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<decimal?>("TotalWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("TotalWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<decimal?>("UnitWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("UnitWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Vendor")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("VisualKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.HasKey("Id");
b.HasIndex("OrderId", "ParentNodeId", "SortOrder");
b.HasIndex("OrderId", "NodeType", "RiskLevel", "Status");
b.ToTable("ProductionNodes", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<int>("BatchQty")
.HasColumnType("int");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<double>("DailyDelta")
.HasColumnType("float");
b.Property<string>("DataSource")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<string>("DrawingProductName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<DateTimeOffset?>("ImportedAt")
.HasColumnType("datetimeoffset");
b.Property<Guid?>("LineId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LineName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<double>("PlanAchievement")
.HasColumnType("float");
b.Property<DateTime?>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("PlannedStart")
.HasColumnType("datetime2");
b.Property<string>("ProductName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<string>("ProjectName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<string>("SourceDocumentCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("SourceFileHash")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("SourceFileName")
.IsRequired()
.HasMaxLength(260)
.HasColumnType("nvarchar(260)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("ThumbnailKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.HasIndex("LineId");
b.HasIndex("SourceDocumentCode")
.IsUnique()
.HasFilter("[SourceDocumentCode] <> ''");
b.HasIndex("Status", "RiskLevel", "PlannedEnd");
b.ToTable("ProductionOrders", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<double>("Achievement")
.HasColumnType("float");
b.Property<int>("ActualQty")
.HasColumnType("int");
b.Property<int>("Completion")
.HasColumnType("int");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<int>("PlannedQty")
.HasColumnType("int");
b.Property<int>("Risk")
.HasColumnType("int");
b.Property<DateTimeOffset>("SampleTime")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("OrderId", "SampleTime")
.IsDescending(false, true);
b.ToTable("ProductionTrendPoints", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("HandlingStatus")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Message")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid>("NodeId")
.HasColumnType("uniqueidentifier");
b.Property<string>("NodeName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<DateTimeOffset>("OccurredAt")
.HasColumnType("datetimeoffset");
b.Property<string>("OrderCode")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("OrderId", "NodeId");
b.HasIndex("OrderId", "OccurredAt")
.IsDescending(false, true);
b.ToTable("RiskEvents", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.MaterialQuota", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "ParentNodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionLine", null)
.WithMany()
.HasForeignKey("LineId")
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "NodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,378 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DongfangHydro.Dashboard.Api.Data.Migrations
{
/// <inheritdoc />
public partial class ImportRealBom : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedStart",
table: "ProductionOrders",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedEnd",
table: "ProductionOrders",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
migrationBuilder.AddColumn<string>(
name: "DataSource",
table: "ProductionOrders",
type: "nvarchar(32)",
maxLength: 32,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "DrawingProductName",
table: "ProductionOrders",
type: "nvarchar(240)",
maxLength: 240,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<DateTimeOffset>(
name: "ImportedAt",
table: "ProductionOrders",
type: "datetimeoffset",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "ProjectName",
table: "ProductionOrders",
type: "nvarchar(200)",
maxLength: 200,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "SourceDocumentCode",
table: "ProductionOrders",
type: "nvarchar(80)",
maxLength: 80,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "SourceFileHash",
table: "ProductionOrders",
type: "nvarchar(64)",
maxLength: 64,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "SourceFileName",
table: "ProductionOrders",
type: "nvarchar(260)",
maxLength: 260,
nullable: false,
defaultValue: "");
migrationBuilder.Sql(
"UPDATE [ProductionOrders] SET [DataSource] = 'demo' WHERE [Code] LIKE 'MO-260708-%';");
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedStart",
table: "ProductionNodes",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedEnd",
table: "ProductionNodes",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
migrationBuilder.AddColumn<decimal>(
name: "BomQuantity",
table: "ProductionNodes",
type: "decimal(18,4)",
precision: 18,
scale: 4,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "BomQuantityText",
table: "ProductionNodes",
type: "nvarchar(80)",
maxLength: 80,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Material",
table: "ProductionNodes",
type: "nvarchar(120)",
maxLength: 120,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Remark",
table: "ProductionNodes",
type: "nvarchar(500)",
maxLength: 500,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<int>(
name: "SourceRow",
table: "ProductionNodes",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "SourceSequence",
table: "ProductionNodes",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "SourceSheet",
table: "ProductionNodes",
type: "nvarchar(40)",
maxLength: 40,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Specification",
table: "ProductionNodes",
type: "nvarchar(240)",
maxLength: 240,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<decimal>(
name: "TotalWeight",
table: "ProductionNodes",
type: "decimal(18,4)",
precision: 18,
scale: 4,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "TotalWeightText",
table: "ProductionNodes",
type: "nvarchar(80)",
maxLength: 80,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<decimal>(
name: "UnitWeight",
table: "ProductionNodes",
type: "decimal(18,4)",
precision: 18,
scale: 4,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "UnitWeightText",
table: "ProductionNodes",
type: "nvarchar(80)",
maxLength: 80,
nullable: false,
defaultValue: "");
migrationBuilder.CreateTable(
name: "MaterialQuotas",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
OrderId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Category = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
SourceSequence = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
MaterialCode = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
MaterialName = table.Column<string>(type: "nvarchar(240)", maxLength: 240, nullable: false),
Specification = table.Column<string>(type: "nvarchar(240)", maxLength: 240, nullable: false),
Unit = table.Column<string>(type: "nvarchar(24)", maxLength: 24, nullable: false),
Quantity = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
NetWeight = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
ConsumptionQuota = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
QuantityText = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
NetWeightText = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
ConsumptionQuotaText = table.Column<string>(type: "nvarchar(80)", maxLength: 80, nullable: false),
Brand = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false),
Remark = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
SourceSheet = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
SourceRow = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_MaterialQuotas", x => x.Id);
table.ForeignKey(
name: "FK_MaterialQuotas_ProductionOrders_OrderId",
column: x => x.OrderId,
principalTable: "ProductionOrders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ProductionOrders_SourceDocumentCode",
table: "ProductionOrders",
column: "SourceDocumentCode",
unique: true,
filter: "[SourceDocumentCode] <> ''");
migrationBuilder.CreateIndex(
name: "IX_MaterialQuotas_OrderId_Category_MaterialCode",
table: "MaterialQuotas",
columns: new[] { "OrderId", "Category", "MaterialCode" });
migrationBuilder.CreateIndex(
name: "IX_MaterialQuotas_OrderId_SourceSheet_SourceRow",
table: "MaterialQuotas",
columns: new[] { "OrderId", "SourceSheet", "SourceRow" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "MaterialQuotas");
migrationBuilder.DropIndex(
name: "IX_ProductionOrders_SourceDocumentCode",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "DataSource",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "DrawingProductName",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "ImportedAt",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "ProjectName",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "SourceDocumentCode",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "SourceFileHash",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "SourceFileName",
table: "ProductionOrders");
migrationBuilder.DropColumn(
name: "BomQuantity",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "BomQuantityText",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "Material",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "Remark",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "SourceRow",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "SourceSequence",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "SourceSheet",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "Specification",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "TotalWeight",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "TotalWeightText",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "UnitWeight",
table: "ProductionNodes");
migrationBuilder.DropColumn(
name: "UnitWeightText",
table: "ProductionNodes");
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedStart",
table: "ProductionOrders",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedEnd",
table: "ProductionOrders",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedStart",
table: "ProductionNodes",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "PlannedEnd",
table: "ProductionNodes",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
}
}
}
@@ -0,0 +1,651 @@
// <auto-generated />
using System;
using DongfangHydro.Dashboard.Api.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace DongfangHydro.Dashboard.Api.Data.Migrations
{
[DbContext(typeof(DashboardDbContext))]
[Migration("20260710103033_AllowRepeatedWorkOrderCodes")]
partial class AllowRepeatedWorkOrderCodes
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.20")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.MaterialQuota", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Brand")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("Category")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<decimal?>("ConsumptionQuota")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("ConsumptionQuotaText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("MaterialCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("MaterialName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<decimal?>("NetWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("NetWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<decimal?>("Quantity")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("QuantityText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Remark")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("SourceRow")
.HasColumnType("int");
b.Property<string>("SourceSequence")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("SourceSheet")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("Specification")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("Unit")
.IsRequired()
.HasMaxLength(24)
.HasColumnType("nvarchar(24)");
b.HasKey("Id");
b.HasIndex("OrderId", "Category", "MaterialCode");
b.HasIndex("OrderId", "SourceSheet", "SourceRow")
.IsUnique();
b.ToTable("MaterialQuotas", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.Partner", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("ContactName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("ContactPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("PartnerType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("Partners", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionLine", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ProductionLines", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("ActualEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("ActualStart")
.HasColumnType("datetime2");
b.Property<decimal?>("BomQuantity")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("BomQuantityText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<int>("DefectQty")
.HasColumnType("int");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<string>("DelayReason")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<string>("Material")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("MaterialCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("NodeType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("OperationCode")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ParentNodeId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("PlannedStart")
.HasColumnType("datetime2");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<string>("Remark")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<int>("SortOrder")
.HasColumnType("int");
b.Property<int>("SourceRow")
.HasColumnType("int");
b.Property<string>("SourceSequence")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("SourceSheet")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("Specification")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("StationName")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("SupplyType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<decimal?>("TotalWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("TotalWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<decimal?>("UnitWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("UnitWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Vendor")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("VisualKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.HasKey("Id");
b.HasIndex("OrderId", "ParentNodeId", "SortOrder");
b.HasIndex("OrderId", "NodeType", "RiskLevel", "Status");
b.ToTable("ProductionNodes", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<int>("BatchQty")
.HasColumnType("int");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<double>("DailyDelta")
.HasColumnType("float");
b.Property<string>("DataSource")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<string>("DrawingProductName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<DateTimeOffset?>("ImportedAt")
.HasColumnType("datetimeoffset");
b.Property<Guid?>("LineId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LineName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<double>("PlanAchievement")
.HasColumnType("float");
b.Property<DateTime?>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("PlannedStart")
.HasColumnType("datetime2");
b.Property<string>("ProductName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<string>("ProjectName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<string>("SourceDocumentCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("SourceFileHash")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("SourceFileName")
.IsRequired()
.HasMaxLength(260)
.HasColumnType("nvarchar(260)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("ThumbnailKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Code");
b.HasIndex("LineId");
b.HasIndex("SourceDocumentCode")
.IsUnique()
.HasFilter("[SourceDocumentCode] <> ''");
b.HasIndex("Status", "RiskLevel", "PlannedEnd");
b.ToTable("ProductionOrders", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<double>("Achievement")
.HasColumnType("float");
b.Property<int>("ActualQty")
.HasColumnType("int");
b.Property<int>("Completion")
.HasColumnType("int");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<int>("PlannedQty")
.HasColumnType("int");
b.Property<int>("Risk")
.HasColumnType("int");
b.Property<DateTimeOffset>("SampleTime")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("OrderId", "SampleTime")
.IsDescending(false, true);
b.ToTable("ProductionTrendPoints", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("HandlingStatus")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Message")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid>("NodeId")
.HasColumnType("uniqueidentifier");
b.Property<string>("NodeName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<DateTimeOffset>("OccurredAt")
.HasColumnType("datetimeoffset");
b.Property<string>("OrderCode")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("OrderId", "NodeId");
b.HasIndex("OrderId", "OccurredAt")
.IsDescending(false, true);
b.ToTable("RiskEvents", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.MaterialQuota", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "ParentNodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionLine", null)
.WithMany()
.HasForeignKey("LineId")
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "NodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,37 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DongfangHydro.Dashboard.Api.Data.Migrations
{
/// <inheritdoc />
public partial class AllowRepeatedWorkOrderCodes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_ProductionOrders_Code",
table: "ProductionOrders");
migrationBuilder.CreateIndex(
name: "IX_ProductionOrders_Code",
table: "ProductionOrders",
column: "Code");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_ProductionOrders_Code",
table: "ProductionOrders");
migrationBuilder.CreateIndex(
name: "IX_ProductionOrders_Code",
table: "ProductionOrders",
column: "Code",
unique: true);
}
}
}
@@ -0,0 +1,648 @@
// <auto-generated />
using System;
using DongfangHydro.Dashboard.Api.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace DongfangHydro.Dashboard.Api.Data.Migrations
{
[DbContext(typeof(DashboardDbContext))]
partial class DashboardDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.20")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.MaterialQuota", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Brand")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("Category")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<decimal?>("ConsumptionQuota")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("ConsumptionQuotaText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("MaterialCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("MaterialName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<decimal?>("NetWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("NetWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<decimal?>("Quantity")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("QuantityText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Remark")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("SourceRow")
.HasColumnType("int");
b.Property<string>("SourceSequence")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("SourceSheet")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("Specification")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("Unit")
.IsRequired()
.HasMaxLength(24)
.HasColumnType("nvarchar(24)");
b.HasKey("Id");
b.HasIndex("OrderId", "Category", "MaterialCode");
b.HasIndex("OrderId", "SourceSheet", "SourceRow")
.IsUnique();
b.ToTable("MaterialQuotas", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.Partner", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("ContactName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("ContactPhone")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("PartnerType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("Partners", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionLine", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.HasKey("Id");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ProductionLines", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("ActualEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("ActualStart")
.HasColumnType("datetime2");
b.Property<decimal?>("BomQuantity")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("BomQuantityText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<int>("DefectQty")
.HasColumnType("int");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<string>("DelayReason")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<string>("Material")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("MaterialCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("NodeType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("OperationCode")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ParentNodeId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("PlannedStart")
.HasColumnType("datetime2");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<string>("Remark")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<int>("SortOrder")
.HasColumnType("int");
b.Property<int>("SourceRow")
.HasColumnType("int");
b.Property<string>("SourceSequence")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("SourceSheet")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<string>("Specification")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<string>("StationName")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("SupplyType")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<decimal?>("TotalWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("TotalWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<decimal?>("UnitWeight")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("UnitWeightText")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("Vendor")
.IsRequired()
.HasMaxLength(120)
.HasColumnType("nvarchar(120)");
b.Property<string>("VisualKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.HasKey("Id");
b.HasIndex("OrderId", "ParentNodeId", "SortOrder");
b.HasIndex("OrderId", "NodeType", "RiskLevel", "Status");
b.ToTable("ProductionNodes", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<int>("BatchQty")
.HasColumnType("int");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<int>("CompletedQty")
.HasColumnType("int");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetimeoffset");
b.Property<double>("DailyDelta")
.HasColumnType("float");
b.Property<string>("DataSource")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<int>("DelayDays")
.HasColumnType("int");
b.Property<string>("DrawingProductName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<DateTimeOffset?>("ImportedAt")
.HasColumnType("datetimeoffset");
b.Property<Guid?>("LineId")
.HasColumnType("uniqueidentifier");
b.Property<string>("LineName")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("Owner")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<double>("PlanAchievement")
.HasColumnType("float");
b.Property<DateTime?>("PlannedEnd")
.HasColumnType("datetime2");
b.Property<DateTime?>("PlannedStart")
.HasColumnType("datetime2");
b.Property<string>("ProductName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("Progress")
.HasColumnType("int");
b.Property<string>("ProjectName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("RequiredQty")
.HasColumnType("int");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
b.Property<string>("SourceDocumentCode")
.IsRequired()
.HasMaxLength(80)
.HasColumnType("nvarchar(80)");
b.Property<string>("SourceFileHash")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("SourceFileName")
.IsRequired()
.HasMaxLength(260)
.HasColumnType("nvarchar(260)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("ThumbnailKey")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<DateTimeOffset>("UpdatedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Code");
b.HasIndex("LineId");
b.HasIndex("SourceDocumentCode")
.IsUnique()
.HasFilter("[SourceDocumentCode] <> ''");
b.HasIndex("Status", "RiskLevel", "PlannedEnd");
b.ToTable("ProductionOrders", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<double>("Achievement")
.HasColumnType("float");
b.Property<int>("ActualQty")
.HasColumnType("int");
b.Property<int>("Completion")
.HasColumnType("int");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<int>("PlannedQty")
.HasColumnType("int");
b.Property<int>("Risk")
.HasColumnType("int");
b.Property<DateTimeOffset>("SampleTime")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("OrderId", "SampleTime")
.IsDescending(false, true);
b.ToTable("ProductionTrendPoints", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("HandlingStatus")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<string>("Message")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid>("NodeId")
.HasColumnType("uniqueidentifier");
b.Property<string>("NodeName")
.IsRequired()
.HasMaxLength(240)
.HasColumnType("nvarchar(240)");
b.Property<DateTimeOffset>("OccurredAt")
.HasColumnType("datetimeoffset");
b.Property<string>("OrderCode")
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)");
b.Property<Guid>("OrderId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RiskLevel")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("OrderId", "NodeId");
b.HasIndex("OrderId", "OccurredAt")
.IsDescending(false, true);
b.ToTable("RiskEvents", (string)null);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.MaterialQuota", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionNode", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "ParentNodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionLine", null)
.WithMany()
.HasForeignKey("LineId")
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.ProductionTrendPoint", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("DongfangHydro.Dashboard.Api.Domain.RiskEvent", b =>
{
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionOrder", null)
.WithMany()
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("DongfangHydro.Dashboard.Api.Domain.ProductionNode", null)
.WithMany()
.HasForeignKey("OrderId", "NodeId")
.HasPrincipalKey("OrderId", "Id")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,266 @@
IF OBJECT_ID(N'[__EFMigrationsHistory]') IS NULL
BEGIN
CREATE TABLE [__EFMigrationsHistory] (
[MigrationId] nvarchar(150) NOT NULL,
[ProductVersion] nvarchar(32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
);
END;
GO
BEGIN TRANSACTION;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE TABLE [Partners] (
[Id] uniqueidentifier NOT NULL,
[Code] nvarchar(40) NOT NULL,
[Name] nvarchar(120) NOT NULL,
[PartnerType] nvarchar(32) NOT NULL,
[ContactName] nvarchar(80) NOT NULL,
[ContactPhone] nvarchar(32) NOT NULL,
CONSTRAINT [PK_Partners] PRIMARY KEY ([Id])
);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE TABLE [ProductionLines] (
[Id] uniqueidentifier NOT NULL,
[Code] nvarchar(40) NOT NULL,
[Name] nvarchar(80) NOT NULL,
[Owner] nvarchar(80) NOT NULL,
[IsActive] bit NOT NULL,
CONSTRAINT [PK_ProductionLines] PRIMARY KEY ([Id])
);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE TABLE [ProductionOrders] (
[Id] uniqueidentifier NOT NULL,
[Code] nvarchar(40) NOT NULL,
[ProductName] nvarchar(200) NOT NULL,
[BatchQty] int NOT NULL,
[RequiredQty] int NOT NULL,
[CompletedQty] int NOT NULL,
[Progress] int NOT NULL,
[Status] nvarchar(32) NOT NULL,
[RiskLevel] nvarchar(32) NOT NULL,
[DelayDays] int NOT NULL,
[PlannedStart] datetime2 NOT NULL,
[PlannedEnd] datetime2 NOT NULL,
[LineId] uniqueidentifier NULL,
[LineName] nvarchar(80) NOT NULL,
[Owner] nvarchar(80) NOT NULL,
[PlanAchievement] float NOT NULL,
[DailyDelta] float NOT NULL,
[ThumbnailKey] nvarchar(40) NOT NULL,
[CreatedAt] datetimeoffset NOT NULL,
[UpdatedAt] datetimeoffset NOT NULL,
[RowVersion] rowversion NOT NULL,
CONSTRAINT [PK_ProductionOrders] PRIMARY KEY ([Id]),
CONSTRAINT [FK_ProductionOrders_ProductionLines_LineId] FOREIGN KEY ([LineId]) REFERENCES [ProductionLines] ([Id]) ON DELETE SET NULL
);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE TABLE [ProductionNodes] (
[Id] uniqueidentifier NOT NULL,
[OrderId] uniqueidentifier NOT NULL,
[ParentNodeId] uniqueidentifier NULL,
[Code] nvarchar(60) NOT NULL,
[OperationCode] nvarchar(60) NOT NULL,
[MaterialCode] nvarchar(80) NOT NULL,
[Name] nvarchar(240) NOT NULL,
[Level] int NOT NULL,
[NodeType] nvarchar(32) NOT NULL,
[SupplyType] nvarchar(32) NOT NULL,
[RequiredQty] int NOT NULL,
[CompletedQty] int NOT NULL,
[DefectQty] int NOT NULL,
[Progress] int NOT NULL,
[Status] nvarchar(32) NOT NULL,
[RiskLevel] nvarchar(32) NOT NULL,
[DelayDays] int NOT NULL,
[DelayReason] nvarchar(500) NOT NULL,
[PlannedStart] datetime2 NOT NULL,
[PlannedEnd] datetime2 NOT NULL,
[ActualStart] datetime2 NULL,
[ActualEnd] datetime2 NULL,
[Owner] nvarchar(100) NOT NULL,
[Vendor] nvarchar(120) NOT NULL,
[StationName] nvarchar(120) NOT NULL,
[VisualKey] nvarchar(40) NOT NULL,
[SortOrder] int NOT NULL,
[UpdatedAt] datetimeoffset NOT NULL,
[RowVersion] rowversion NOT NULL,
CONSTRAINT [PK_ProductionNodes] PRIMARY KEY ([Id]),
CONSTRAINT [AK_ProductionNodes_OrderId_Id] UNIQUE ([OrderId], [Id]),
CONSTRAINT [FK_ProductionNodes_ProductionNodes_OrderId_ParentNodeId] FOREIGN KEY ([OrderId], [ParentNodeId]) REFERENCES [ProductionNodes] ([OrderId], [Id]) ON DELETE NO ACTION,
CONSTRAINT [FK_ProductionNodes_ProductionOrders_OrderId] FOREIGN KEY ([OrderId]) REFERENCES [ProductionOrders] ([Id]) ON DELETE CASCADE
);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE TABLE [ProductionTrendPoints] (
[Id] uniqueidentifier NOT NULL,
[OrderId] uniqueidentifier NOT NULL,
[SampleTime] datetimeoffset NOT NULL,
[Completion] int NOT NULL,
[Risk] int NOT NULL,
[PlannedQty] int NOT NULL,
[ActualQty] int NOT NULL,
[Achievement] float NOT NULL,
CONSTRAINT [PK_ProductionTrendPoints] PRIMARY KEY ([Id]),
CONSTRAINT [FK_ProductionTrendPoints_ProductionOrders_OrderId] FOREIGN KEY ([OrderId]) REFERENCES [ProductionOrders] ([Id]) ON DELETE CASCADE
);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE TABLE [RiskEvents] (
[Id] uniqueidentifier NOT NULL,
[OrderId] uniqueidentifier NOT NULL,
[NodeId] uniqueidentifier NOT NULL,
[OrderCode] nvarchar(40) NOT NULL,
[NodeName] nvarchar(240) NOT NULL,
[RiskLevel] nvarchar(32) NOT NULL,
[Message] nvarchar(500) NOT NULL,
[HandlingStatus] nvarchar(32) NOT NULL,
[OccurredAt] datetimeoffset NOT NULL,
CONSTRAINT [PK_RiskEvents] PRIMARY KEY ([Id]),
CONSTRAINT [FK_RiskEvents_ProductionNodes_OrderId_NodeId] FOREIGN KEY ([OrderId], [NodeId]) REFERENCES [ProductionNodes] ([OrderId], [Id]),
CONSTRAINT [FK_RiskEvents_ProductionOrders_OrderId] FOREIGN KEY ([OrderId]) REFERENCES [ProductionOrders] ([Id]) ON DELETE CASCADE
);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE UNIQUE INDEX [IX_Partners_Code] ON [Partners] ([Code]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE UNIQUE INDEX [IX_ProductionLines_Code] ON [ProductionLines] ([Code]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE INDEX [IX_ProductionNodes_OrderId_NodeType_RiskLevel_Status] ON [ProductionNodes] ([OrderId], [NodeType], [RiskLevel], [Status]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE INDEX [IX_ProductionNodes_OrderId_ParentNodeId_SortOrder] ON [ProductionNodes] ([OrderId], [ParentNodeId], [SortOrder]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE UNIQUE INDEX [IX_ProductionOrders_Code] ON [ProductionOrders] ([Code]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE INDEX [IX_ProductionOrders_LineId] ON [ProductionOrders] ([LineId]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE INDEX [IX_ProductionOrders_Status_RiskLevel_PlannedEnd] ON [ProductionOrders] ([Status], [RiskLevel], [PlannedEnd]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE INDEX [IX_ProductionTrendPoints_OrderId_SampleTime] ON [ProductionTrendPoints] ([OrderId], [SampleTime] DESC);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE INDEX [IX_RiskEvents_OrderId_NodeId] ON [RiskEvents] ([OrderId], [NodeId]);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
CREATE INDEX [IX_RiskEvents_OrderId_OccurredAt] ON [RiskEvents] ([OrderId], [OccurredAt] DESC);
END;
GO
IF NOT EXISTS (
SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'20260710025438_InitialCreate'
)
BEGIN
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20260710025438_InitialCreate', N'8.0.20');
END;
GO
COMMIT;
GO