using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; using FreeSql; using F9WebAiTest.Application.Interfaces.SnowflakeID; using F9WebAiTest.Domain.Entities.Base; using F9WebAiTest.Domain.Entities.Prod; using F9WebAiTest.Domain.Enums.SYS.Employees; using SysDept = F9WebAiTest.Domain.Entities.SYS.Departments; namespace F9WebAiTest.Infrastructure.Data; /// /// 生产模块基础数据种子(来源于 F9 系统导出): /// 1) biz_prod_qs_jzct —— 机组车台 /// 2) biz_prod_qs_cjbc —— 车间班次 /// 幂等:按「车间 + 机组」/「车间 + 班次」匹配,存在则校正,不存在则新增;已删除的数据不导入。 /// public static class ProdSeedData { private const string JzctResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_prod_qs_jzct.json"; private const string CjbcResource = "F9WebAiTest.Infrastructure.Data.SeedData.biz_prod_qs_cjbc.json"; private static readonly JsonSerializerOptions JsonOpts = new() { PropertyNameCaseInsensitive = true, NumberHandling = JsonNumberHandling.AllowReadingFromString }; public static void Seed(IFreeSql fsql, ISnowflakeIdGenerator snowflake) { SeedJizuChetai(fsql); SeedChejianBanci(fsql); } // ==================== 机组车台 ==================== private static void SeedJizuChetai(IFreeSql fsql) { try { var items = Load(JzctResource); if (items.Count == 0) return; var deptMap = BuildDeptMap(fsql); var existing = fsql.Select().ToList() .GroupBy(x => (x.DepartmentId, x.Jizu)) .ToDictionary(g => g.Key, g => g.First()); int added = 0, updated = 0, skipped = 0; var unmappedDeps = new HashSet(); foreach (var item in items) { if (!string.IsNullOrWhiteSpace(item.DeletedAt)) { skipped++; continue; } if (!deptMap.TryGetValue(item.DepId, out var deptId)) { unmappedDeps.Add(item.DepId); skipped++; continue; } var key = (deptId, item.Jizu); if (existing.TryGetValue(key, out var e)) { if (e.ChetaiStart != item.ChetaiStart || e.ChetaiEnd != item.ChetaiEnd) { e.ChetaiStart = item.ChetaiStart; e.ChetaiEnd = item.ChetaiEnd; fsql.Update().SetSource(e).ExecuteAffrows(); updated++; } } else { fsql.Insert(new JizuChetai { DepartmentId = deptId, Jizu = item.Jizu, ChetaiStart = item.ChetaiStart, ChetaiEnd = item.ChetaiEnd }).ExecuteAffrows(); added++; } } Console.WriteLine($"[ProdSeed] 机组车台:来源 {items.Count} 条,新增 {added} 条,更新 {updated} 条,跳过(已删除/无法映射){skipped} 条"); if (unmappedDeps.Count > 0) Console.WriteLine($"[ProdSeed] 提示:以下 F9 部门 Id 未匹配到本系统部门,已跳过 -> {string.Join(", ", unmappedDeps)}"); } catch (Exception ex) { Console.WriteLine($"[ProdSeed] 机组车台导入跳过:{ex.Message}"); } } // ==================== 车间班次 ==================== private static void SeedChejianBanci(IFreeSql fsql) { try { var items = Load(CjbcResource); if (items.Count == 0) return; var deptMap = BuildDeptMap(fsql); var existing = fsql.Select().ToList() .GroupBy(x => (x.DeptId, x.Banci)) .ToDictionary(g => g.Key, g => g.First()); int added = 0, updated = 0, skipped = 0; var unmappedDeps = new HashSet(); foreach (var item in items) { if (!string.IsNullOrWhiteSpace(item.DeletedAt)) { skipped++; continue; } if (!deptMap.TryGetValue(item.DepId, out var deptId)) { unmappedDeps.Add(item.DepId); skipped++; continue; } var banci = (Prod_Banci_Enum)item.Banci; var key = (deptId, banci); if (existing.TryGetValue(key, out var e)) { if (Math.Abs(e.KaoqinDayhours - item.KaoqinDayhours) > 0.001) { e.KaoqinDayhours = item.KaoqinDayhours; fsql.Update().SetSource(e).ExecuteAffrows(); updated++; } } else { fsql.Insert(new ChejianBanci { DeptId = deptId, Banci = banci, KaoqinDayhours = item.KaoqinDayhours }).ExecuteAffrows(); added++; } } Console.WriteLine($"[ProdSeed] 车间班次:来源 {items.Count} 条,新增 {added} 条,更新 {updated} 条,跳过(已删除/无法映射){skipped} 条"); if (unmappedDeps.Count > 0) Console.WriteLine($"[ProdSeed] 提示:以下 F9 部门 Id 未匹配到本系统部门,已跳过 -> {string.Join(", ", unmappedDeps)}"); } catch (Exception ex) { Console.WriteLine($"[ProdSeed] 车间班次导入跳过:{ex.Message}"); } } // ==================== 公共 ==================== /// 建立 F9 部门 Id → 本系统部门 Id 的映射(以部门名称为桥梁) private static Dictionary BuildDeptMap(IFreeSql fsql) { var f9NameMap = BusinessSeedData.DeptData.ToDictionary(x => x.Id, x => x.Name); var localNameMap = fsql.Select().ToList() .GroupBy(d => d.Name) .ToDictionary(g => g.Key, g => g.First().Id); var map = new Dictionary(); foreach (var (f9Id, name) in f9NameMap) { if (localNameMap.TryGetValue(name, out var localId)) map[f9Id] = localId; } return map; } private static List Load(string resourceName) { var asm = Assembly.GetExecutingAssembly(); using var stream = asm.GetManifestResourceStream(resourceName); if (stream == null) return new List(); return JsonSerializer.Deserialize>(stream, JsonOpts) ?? new List(); } // ---- 数据项 ---- private class JzctItem { [JsonPropertyName("id")] public long Id { get; set; } [JsonPropertyName("deleted_at")] public string? DeletedAt { get; set; } [JsonPropertyName("dep_id")] public long DepId { get; set; } [JsonPropertyName("jizu")] public int Jizu { get; set; } [JsonPropertyName("chetai_start")] public int ChetaiStart { get; set; } [JsonPropertyName("chetai_end")] public int ChetaiEnd { get; set; } } private class CjbcItem { [JsonPropertyName("id")] public long Id { get; set; } [JsonPropertyName("deleted_at")] public string? DeletedAt { get; set; } [JsonPropertyName("dep_id")] public long DepId { get; set; } [JsonPropertyName("banci")] public int Banci { get; set; } [JsonPropertyName("kaoqin_dayhours")] public double KaoqinDayhours { get; set; } } }