AidopS0ExcelColumnMigration.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. using System.Data;
  2. using System.Diagnostics;
  3. using System.Text;
  4. using Admin.NET.Plugin.AiDOP.Entity.S0.Sales;
  5. using SqlSugar;
  6. namespace Admin.NET.Plugin.AiDOP.Infrastructure;
  7. /// <summary>
  8. /// S0 Excel 字段口径迁移:将现有旧列名重命名为 Excel 字段名。
  9. /// 仅处理文档中已确认映射的字段,不自动补 Excel 独有字段。
  10. /// </summary>
  11. public static class AidopS0ExcelColumnMigration
  12. {
  13. private sealed record ColumnRename(string TableName, string OldColumnName, string NewColumnName);
  14. private sealed record PrimaryKeyRepair(string TableName, string PkColumnName, bool IsIdentity, string PkComment, params string[] ShadowColumns);
  15. private sealed record MySqlColumnMeta(
  16. string ColumnName,
  17. string ColumnType,
  18. string IsNullable,
  19. string? ColumnDefault,
  20. string? Extra,
  21. string? ColumnComment,
  22. string? CollationName,
  23. string? CharacterSetName);
  24. private static readonly ColumnRename[] Renames =
  25. [
  26. new("CostCtrMaster", "cost_ctr", "CostCtr"),
  27. new("CostCtrMaster", "create_time", "CreateTime"),
  28. new("CostCtrMaster", "create_user", "CreateUser"),
  29. new("CostCtrMaster", "descr", "Descr"),
  30. new("CostCtrMaster", "domain_code", "Domain"),
  31. new("CostCtrMaster", "eff_time", "EffTime"),
  32. new("CostCtrMaster", "rec_id", "RecID"),
  33. new("CostCtrMaster", "ufld1", "Ufld1"),
  34. new("CostCtrMaster", "update_time", "UpdateTime"),
  35. new("CostCtrMaster", "update_user", "UpdateUser"),
  36. new("CustMaster", "create_time", "CreateTime"),
  37. new("CustMaster", "create_user", "CreateUser"),
  38. new("CustMaster", "credit_rating", "CreditRating"),
  39. new("CustMaster", "curr", "Curr"),
  40. new("CustMaster", "cust", "Cust"),
  41. new("CustMaster", "domain_code", "Domain"),
  42. new("CustMaster", "is_active", "IsActive"),
  43. new("CustMaster", "is_confirm", "IsConfirm"),
  44. new("CustMaster", "rec_id", "RecID"),
  45. new("CustMaster", "remarks", "Remarks"),
  46. new("CustMaster", "ship_to", "ShipTo"),
  47. new("CustMaster", "slspsn1", "Slspsn1"),
  48. new("CustMaster", "slspsn2", "Slspsn2"),
  49. new("CustMaster", "sort_name", "SortName"),
  50. new("CustMaster", "tax_class", "TaxClass"),
  51. new("CustMaster", "tax_in", "TaxIn"),
  52. new("CustMaster", "update_time", "UpdateTime"),
  53. new("CustMaster", "update_user", "UpdateUser"),
  54. new("DepartmentMaster", "create_time", "CreateTime"),
  55. new("DepartmentMaster", "create_user", "CreateUser"),
  56. new("DepartmentMaster", "department", "Department"),
  57. new("DepartmentMaster", "descr", "Descr"),
  58. new("DepartmentMaster", "domain_code", "Domain"),
  59. new("DepartmentMaster", "is_active", "IsActive"),
  60. new("DepartmentMaster", "rec_id", "RecID"),
  61. new("DepartmentMaster", "update_time", "UpdateTime"),
  62. new("DepartmentMaster", "update_user", "UpdateUser"),
  63. new("DevMonitor", "code_descr", "CodeDescr"),
  64. new("DevMonitor", "code_type", "CodeType"),
  65. new("DevMonitor", "create_time", "CreateTime"),
  66. new("DevMonitor", "create_user", "CreateUser"),
  67. new("DevMonitor", "device_descr", "DeviceDescr"),
  68. new("DevMonitor", "device_number", "DeviceNumber"),
  69. new("DevMonitor", "domain", "Domain"),
  70. new("DevMonitor", "id", "RecID"),
  71. new("DevMonitor", "low_limit", "LowLimit"),
  72. new("DevMonitor", "message_code", "MessageCode"),
  73. new("DevMonitor", "std_value", "StdValue"),
  74. new("DevMonitor", "top_limit", "TopLimit"),
  75. new("DevMonitor", "ufld1", "Ufld1"),
  76. new("DevMonitor", "um", "UM"),
  77. new("DevMonitor", "update_time", "UpdateTime"),
  78. new("DevMonitor", "update_user", "UpdateUser"),
  79. new("DevMonitor", "value_type", "ValueType"),
  80. new("EmpSkills", "create_time", "CreateTime"),
  81. new("EmpSkills", "create_user", "CreateUser"),
  82. new("EmpSkills", "domain", "Domain"),
  83. new("EmpSkills", "efficiency_coefficient", "EfficiencyCoefficient"),
  84. new("EmpSkills", "employee", "Employee"),
  85. new("EmpSkills", "employee_id", "EmployeeID"),
  86. new("EmpSkills", "employee_name", "EmployeeName"),
  87. new("EmpSkills", "id", "RecID"),
  88. new("EmpSkills", "site", "Site"),
  89. new("EmpSkills", "skill_description", "SkillDescription"),
  90. new("EmpSkills", "skill_level", "SkillLevel"),
  91. new("EmpSkills", "skill_no", "SkillNo"),
  92. new("EmpSkills", "update_time", "UpdateTime"),
  93. new("EmpSkills", "update_user", "UpdateUser"),
  94. new("EmpWorkDutyMaster", "create_time", "CreateTime"),
  95. new("EmpWorkDutyMaster", "create_user", "CreateUser"),
  96. new("EmpWorkDutyMaster", "domain_code", "Domain"),
  97. new("EmpWorkDutyMaster", "duty", "Duty"),
  98. new("EmpWorkDutyMaster", "emp_type", "EmpType"),
  99. new("EmpWorkDutyMaster", "employee", "Employee"),
  100. new("EmpWorkDutyMaster", "item_num1", "ItemNum1"),
  101. new("EmpWorkDutyMaster", "item_num2", "ItemNum2"),
  102. new("EmpWorkDutyMaster", "location", "Location"),
  103. new("EmpWorkDutyMaster", "prod_line", "ProdLine"),
  104. new("EmpWorkDutyMaster", "rec_id", "RecID"),
  105. new("EmpWorkDutyMaster", "ufld2", "Ufld2"),
  106. new("EmpWorkDutyMaster", "update_time", "UpdateTime"),
  107. new("EmpWorkDutyMaster", "update_user", "UpdateUser"),
  108. new("EmployeeMaster", "birth_date", "BirthDate"),
  109. new("EmployeeMaster", "car_id", "CarId"),
  110. new("EmployeeMaster", "create_time", "CreateTime"),
  111. new("EmployeeMaster", "create_user", "CreateUser"),
  112. new("EmployeeMaster", "date_employed", "DateEmployed"),
  113. new("EmployeeMaster", "date_terminated", "DateTerminated"),
  114. new("EmployeeMaster", "default_work_location", "DefaultWorkLocation"),
  115. new("EmployeeMaster", "department", "Department"),
  116. new("EmployeeMaster", "domain_code", "Domain"),
  117. new("EmployeeMaster", "email", "Email"),
  118. new("EmployeeMaster", "employee", "Employee"),
  119. new("EmployeeMaster", "employment_status", "EmploymentStatus"),
  120. new("EmployeeMaster", "is_active", "IsActive"),
  121. new("EmployeeMaster", "job_title", "JobTitle"),
  122. new("EmployeeMaster", "marital_status", "MaritalStatus"),
  123. new("EmployeeMaster", "name", "Name"),
  124. new("EmployeeMaster", "phone", "Phone"),
  125. new("EmployeeMaster", "rec_id", "RecID"),
  126. new("EmployeeMaster", "sex", "Sex"),
  127. new("EmployeeMaster", "update_time", "UpdateTime"),
  128. new("EmployeeMaster", "update_user", "UpdateUser"),
  129. new("EmployeeMaster", "work_ctr", "WorkCtr"),
  130. new("ItemMaster", "allocate_single_lot", "AllocateSingleLot"),
  131. new("ItemMaster", "auto_lot_nums", "AutoLotNums"),
  132. new("ItemMaster", "commodity_code", "CommodityCode"),
  133. new("ItemMaster", "create_time", "CreateTime"),
  134. new("ItemMaster", "create_user", "CreateUser"),
  135. new("ItemMaster", "days_between_pm", "DaysBetweenPM"),
  136. new("ItemMaster", "default_shelf", "DefaultShelf"),
  137. new("ItemMaster", "descr", "Descr"),
  138. new("ItemMaster", "descr1", "Descr1"),
  139. new("ItemMaster", "domain_code", "Domain"),
  140. new("ItemMaster", "drawing", "Drawing"),
  141. new("ItemMaster", "emt_type", "EMTType"),
  142. new("ItemMaster", "ins_lt", "InsLT"),
  143. new("ItemMaster", "inspect", "Inspect"),
  144. new("ItemMaster", "install", "Install"),
  145. new("ItemMaster", "is_active", "IsActive"),
  146. new("ItemMaster", "is_confirm", "IsConfirm"),
  147. new("ItemMaster", "is_main_mas", "IsMainMas"),
  148. new("ItemMaster", "issue_policy", "IssuePolicy"),
  149. new("ItemMaster", "item_num", "ItemNum"),
  150. new("ItemMaster", "item_type", "ItemType"),
  151. new("ItemMaster", "key_item", "KeyItem"),
  152. new("ItemMaster", "length", "Length"),
  153. new("ItemMaster", "location", "Location"),
  154. new("ItemMaster", "location_type", "LocationType"),
  155. new("ItemMaster", "lot_serial_control", "LotSerialControl"),
  156. new("ItemMaster", "max_ord", "MaxOrd"),
  157. new("ItemMaster", "mfg_lt", "MfgLT"),
  158. new("ItemMaster", "mfgmttr", "MFGMTTR"),
  159. new("ItemMaster", "min_ord", "MinOrd"),
  160. new("ItemMaster", "min_ord_sales", "MinOrdSales"),
  161. new("ItemMaster", "net_weight", "NetWeight"),
  162. new("ItemMaster", "net_weight_um", "NetWeightUM"),
  163. new("ItemMaster", "ord_mult", "OrdMult"),
  164. new("ItemMaster", "owner_application", "OwnerApplication"),
  165. new("ItemMaster", "pkg_code", "PkgCode"),
  166. new("ItemMaster", "planner", "Planner"),
  167. new("ItemMaster", "pur_lt", "PurLT"),
  168. new("ItemMaster", "pur_mfg", "PurMfg"),
  169. new("ItemMaster", "rec_id", "RecID"),
  170. new("ItemMaster", "remark", "Remark"),
  171. new("ItemMaster", "rev", "Rev"),
  172. new("ItemMaster", "safety_stk", "SafetyStk"),
  173. new("ItemMaster", "size", "Size"),
  174. new("ItemMaster", "size_um", "SizeUM"),
  175. new("ItemMaster", "status", "Status"),
  176. new("ItemMaster", "stock_turn_over", "StockTurnOver"),
  177. new("ItemMaster", "trace_detail", "TraceDetail"),
  178. new("ItemMaster", "um", "UM"),
  179. new("ItemMaster", "update_time", "UpdateTime"),
  180. new("ItemMaster", "update_user", "UpdateUser"),
  181. new("ItemOpCondition", "code_type", "CodeType"),
  182. new("ItemOpCondition", "create_time", "CreateTime"),
  183. new("ItemOpCondition", "create_user", "CreateUser"),
  184. new("ItemOpCondition", "descr", "Descr"),
  185. new("ItemOpCondition", "domain", "Domain"),
  186. new("ItemOpCondition", "id", "RecID"),
  187. new("ItemOpCondition", "is_main", "IsMain"),
  188. new("ItemOpCondition", "item_code", "ItemCode"),
  189. new("ItemOpCondition", "item_num", "ItemNum"),
  190. new("ItemOpCondition", "line", "Line"),
  191. new("ItemOpCondition", "op", "Op"),
  192. new("ItemOpCondition", "typed", "Typed"),
  193. new("ItemOpCondition", "update_time", "UpdateTime"),
  194. new("ItemOpCondition", "update_user", "UpdateUser"),
  195. new("ItemPackMaster", "create_time", "CreateTime"),
  196. new("ItemPackMaster", "create_user", "CreateUser"),
  197. new("ItemPackMaster", "cust_item", "CustItem"),
  198. new("ItemPackMaster", "domain_code", "Domain"),
  199. new("ItemPackMaster", "high", "High"),
  200. new("ItemPackMaster", "is_active", "IsActive"),
  201. new("ItemPackMaster", "iss_specific", "IssSpecific"),
  202. new("ItemPackMaster", "item_num", "ItemNum"),
  203. new("ItemPackMaster", "length", "Length"),
  204. new("ItemPackMaster", "net_weight", "NetWeight"),
  205. new("ItemPackMaster", "packing_qty", "PackingQty"),
  206. new("ItemPackMaster", "packing_type", "PackingType"),
  207. new("ItemPackMaster", "rec_id", "RecID"),
  208. new("ItemPackMaster", "remark", "Remark"),
  209. new("ItemPackMaster", "small_packing_qty", "SmallPackingQty"),
  210. new("ItemPackMaster", "update_time", "UpdateTime"),
  211. new("ItemPackMaster", "update_user", "UpdateUser"),
  212. new("ItemPackMaster", "weight_um", "WeightUM"),
  213. new("ItemPackMaster", "width", "Width"),
  214. new("ItemSubstituteDetail", "create_time", "CreateTime"),
  215. new("ItemSubstituteDetail", "create_user", "CreateUser"),
  216. new("ItemSubstituteDetail", "domain", "Domain"),
  217. new("ItemSubstituteDetail", "id", "RecID"),
  218. new("ItemSubstituteDetail", "item_num", "ItemNum"),
  219. new("ItemSubstituteDetail", "parent_item", "ParentItem"),
  220. new("ItemSubstituteDetail", "remark", "Remark"),
  221. new("ItemSubstituteDetail", "substitute_item", "SubstituteItem"),
  222. new("ItemSubstituteDetail", "substitute_qty", "SubstituteQty"),
  223. new("ItemSubstituteDetail", "update_time", "UpdateTime"),
  224. new("ItemSubstituteDetail", "update_user", "UpdateUser"),
  225. new("LineMaster", "create_time", "CreateTime"),
  226. new("LineMaster", "create_user", "CreateUser"),
  227. new("LineMaster", "domain", "Domain"),
  228. new("LineMaster", "id", "RecID"),
  229. new("LineMaster", "is_active", "IsActive"),
  230. new("LineMaster", "line", "Line"),
  231. new("LineMaster", "line_category", "LineCategory"),
  232. new("LineMaster", "line_type", "LineType"),
  233. new("LineMaster", "location", "Location"),
  234. new("LineMaster", "mid_location", "MidLocation"),
  235. new("LineMaster", "picking_location", "PickingLocation"),
  236. new("LineMaster", "update_time", "UpdateTime"),
  237. new("LineMaster", "update_user", "UpdateUser"),
  238. new("LineMaster", "v_location", "VLocation"),
  239. new("LineMaster", "workshop", "Workshop"),
  240. new("LineSkillDetail", "create_time", "CreateTime"),
  241. new("LineSkillMaster", "create_time", "CreateTime"),
  242. new("LineSkillMaster", "create_user", "CreateUser"),
  243. new("LineSkillMaster", "domain", "Domain"),
  244. new("LineSkillMaster", "id", "RecID"),
  245. new("LineSkillMaster", "job_descr", "JOBDescr"),
  246. new("LineSkillMaster", "job_no", "JOBNo"),
  247. new("LineSkillMaster", "prod_line", "ProdLine"),
  248. new("LineSkillMaster", "update_time", "UpdateTime"),
  249. new("LineSkillMaster", "update_user", "UpdateUser"),
  250. new("PriorityCode", "create_time", "CreateTime"),
  251. new("PriorityCode", "create_user", "CreateUser"),
  252. new("PriorityCode", "descr", "Descr"),
  253. new("PriorityCode", "domain_code", "Domain"),
  254. new("PriorityCode", "is_active", "IsActive"),
  255. new("PriorityCode", "priority", "Priority"),
  256. new("PriorityCode", "rec_id", "RecID"),
  257. new("PriorityCode", "source_column", "SourceColumn"),
  258. new("PriorityCode", "source_id", "SourceID"),
  259. new("PriorityCode", "source_table", "SourceTable"),
  260. new("PriorityCode", "source_type", "SourceType"),
  261. new("PriorityCode", "update_time", "UpdateTime"),
  262. new("PriorityCode", "update_user", "UpdateUser"),
  263. new("PriorityCode", "value", "Value"),
  264. new("PriorityCode", "value_id", "ValueID"),
  265. new("PriorityCode", "value_type", "ValueType"),
  266. new("ProdLineDetail", "create_time", "CreateTime"),
  267. new("ProdLineDetail", "create_user", "CreateUser"),
  268. new("ProdLineDetail", "domain", "Domain"),
  269. new("ProdLineDetail", "id", "RecID"),
  270. new("ProdLineDetail", "is_active", "IsActive"),
  271. new("ProdLineDetail", "is_confirm", "IsConfirm"),
  272. new("ProdLineDetail", "line", "Line"),
  273. new("ProdLineDetail", "mold_type_code", "MoldTypeCode"),
  274. new("ProdLineDetail", "op", "Op"),
  275. new("ProdLineDetail", "part", "Part"),
  276. new("ProdLineDetail", "rate", "Rate"),
  277. new("ProdLineDetail", "setup_time", "SetupTime"),
  278. new("ProdLineDetail", "site", "Site"),
  279. new("ProdLineDetail", "skill_no", "SkillNo"),
  280. new("ProdLineDetail", "standard_staff_count", "StandardStaffCount"),
  281. new("ProdLineDetail", "start", "Start"),
  282. new("ProdLineDetail", "update_time", "UpdateTime"),
  283. new("ProdLineDetail", "update_user", "UpdateUser"),
  284. new("ProductStructureMaster", "end_eff", "EndEff"),
  285. new("ProductStructureMaster", "id", "RecID"),
  286. new("ProductStructureMaster", "qty", "Qty"),
  287. new("ProductStructureMaster", "qty_consumed", "QtyConsumed"),
  288. new("ProductStructureMaster", "refs", "Refs"),
  289. new("ProductStructureMaster", "remark", "Remark"),
  290. new("ProductStructureMaster", "scrap", "Scrap"),
  291. new("ProductStructureMaster", "start_eff", "StartEff"),
  292. new("ProductStructureMaster", "structure_type", "StructureType"),
  293. new("ProductStructureMaster", "um", "UM"),
  294. new("ProductStructureOp", "id", "RecID"),
  295. new("ProductStructureOp", "op", "Op"),
  296. new("RoutingOpDetail", "comment_index", "CommentIndex"),
  297. new("RoutingOpDetail", "create_user", "CreateUser"),
  298. new("RoutingOpDetail", "id", "RecID"),
  299. new("RoutingOpDetail", "is_confirm", "IsConfirm"),
  300. new("RoutingOpDetail", "u_deci1", "UDeci1"),
  301. new("RoutingOpDetail", "u_deci2", "UDeci2"),
  302. new("RoutingOpDetail", "u_deci3", "UDeci3"),
  303. new("RoutingOpDetail", "u_deci4", "UDeci4"),
  304. new("RoutingOpDetail", "u_deci5", "UDeci5"),
  305. new("RoutingOpDetail", "ufld1", "Ufld1"),
  306. new("RoutingOpDetail", "ufld2", "Ufld2"),
  307. new("RoutingOpDetail", "ufld3", "Ufld3"),
  308. new("RoutingOpDetail", "ufld4", "Ufld4"),
  309. new("RoutingOpDetail", "ufld5", "Ufld5"),
  310. new("RoutingOpDetail", "ufld6", "Ufld6"),
  311. new("RoutingOpDetail", "ufld7", "Ufld7"),
  312. new("RoutingOpDetail", "ufld8", "Ufld8"),
  313. new("RoutingOpDetail", "ufld9", "Ufld9"),
  314. new("RoutingOpDetail", "update_user", "UpdateUser"),
  315. new("SuppMaster", "ap_end_day1", "APEndDay1"),
  316. new("SuppMaster", "ap_end_day2", "APEndDay2"),
  317. new("SuppMaster", "ap_start_day1", "APStartDay1"),
  318. new("SuppMaster", "ap_start_day2", "APStartDay2"),
  319. new("SuppMaster", "cr_terms", "CrTerms"),
  320. new("SuppMaster", "create_time", "CreateTime"),
  321. new("SuppMaster", "create_user", "CreateUser"),
  322. new("SuppMaster", "curr", "Curr"),
  323. new("SuppMaster", "domain_code", "Domain"),
  324. new("SuppMaster", "is_active", "IsActive"),
  325. new("SuppMaster", "pur_contact", "PurContact"),
  326. new("SuppMaster", "rec_id", "RecID"),
  327. new("SuppMaster", "remark", "Remark"),
  328. new("SuppMaster", "sort_name", "SortName"),
  329. new("SuppMaster", "supp", "Supp"),
  330. new("SuppMaster", "tax_class", "TaxClass"),
  331. new("SuppMaster", "tax_in", "TaxIn"),
  332. new("SuppMaster", "type", "Type"),
  333. new("SuppMaster", "update_time", "UpdateTime"),
  334. new("SuppMaster", "update_user", "UpdateUser"),
  335. new("WorkCtrMaster", "create_time", "CreateTime"),
  336. new("WorkCtrMaster", "create_user", "CreateUser"),
  337. new("WorkCtrMaster", "department", "Department"),
  338. new("WorkCtrMaster", "descr", "Descr"),
  339. new("WorkCtrMaster", "domain", "Domain"),
  340. new("WorkCtrMaster", "id", "RecID"),
  341. new("WorkCtrMaster", "is_active", "IsActive"),
  342. new("WorkCtrMaster", "update_time", "UpdateTime"),
  343. new("WorkCtrMaster", "update_user", "UpdateUser"),
  344. new("WorkCtrMaster", "work_ctr", "WorkCtr"),
  345. new("ic_substitute", "id", "Id"),
  346. new("ic_substitute", "is_deleted", "IsDeleted"),
  347. new("srm_purchase", "id", "Id"),
  348. new("srm_purchase", "is_require_goods", "IsRequireGoods"),
  349. ];
  350. private static readonly PrimaryKeyRepair[] PrimaryKeyRepairs =
  351. [
  352. new("ItemSubstituteDetail", "RecID", true, "物料替代关系主键", "Id"),
  353. new("CostCtrMaster", "RecID", true, "主键"),
  354. new("CustMaster", "RecID", true, "主键"),
  355. new("DepartmentMaster", "RecID", true, "主键"),
  356. new("DevMonitor", "RecID", true, "主键", "Id"),
  357. new("EmpSkills", "RecID", true, "主键", "Id"),
  358. new("EmpWorkDutyMaster", "RecID", true, "主键"),
  359. new("EmployeeMaster", "RecID", true, "主键"),
  360. new("ItemMaster", "RecID", true, "主键"),
  361. new("ItemOpCondition", "RecID", true, "物料工序生产要素主键", "Id"),
  362. new("ItemPackMaster", "RecID", true, "主键"),
  363. new("LineMaster", "RecID", true, "生产线主键", "Id"),
  364. new("LineSkillMaster", "RecID", true, "产线岗位主键", "Id"),
  365. new("PriorityCode", "RecID", true, "主键"),
  366. new("ProdLineDetail", "RecID", true, "生产线物料主键"),
  367. new("ProductStructureMaster", "RecID", true, "主键", "Id"),
  368. new("ProductStructureOp", "RecID", true, "主键", "Id"),
  369. new("RoutingOpDetail", "RecID", true, "主键", "Id"),
  370. new("SuppMaster", "RecID", true, "主键"),
  371. new("WorkCtrMaster", "RecID", true, "工作中心主键"),
  372. new("ic_substitute", "Id", false, "主键"),
  373. new("srm_purchase", "Id", true, "货源清单主键")
  374. ];
  375. public static void Migrate(ISqlSugarClient db)
  376. {
  377. var databaseName = db.Ado.SqlQuerySingle<string>("SELECT DATABASE();");
  378. foreach (var group in Renames.GroupBy(x => x.TableName))
  379. {
  380. var tableName = group.Key;
  381. var tables = db.DbMaintenance.GetTableInfoList(false);
  382. if (!tables.Any(t => t.Name.Equals(tableName, StringComparison.OrdinalIgnoreCase)))
  383. continue;
  384. try
  385. {
  386. var columns = db.DbMaintenance.GetColumnInfosByTableName(tableName, false) ?? [];
  387. foreach (var rename in group)
  388. {
  389. var oldColumn = columns.FirstOrDefault(c => c.DbColumnName.Equals(rename.OldColumnName, StringComparison.Ordinal));
  390. var newColumn = columns.FirstOrDefault(c => c.DbColumnName.Equals(rename.NewColumnName, StringComparison.Ordinal));
  391. if (oldColumn == null)
  392. continue;
  393. if (newColumn != null)
  394. {
  395. if (oldColumn.IsPrimarykey)
  396. {
  397. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` DROP COLUMN `{rename.NewColumnName}`");
  398. Trace.TraceInformation($"Ai-DOP S0 drop duplicate new PK shadow column: {tableName}.{rename.NewColumnName}");
  399. RenameColumnMySql(db, databaseName, tableName, rename.OldColumnName, rename.NewColumnName);
  400. Trace.TraceInformation($"Ai-DOP S0 rename PK column: {tableName}.{rename.OldColumnName} -> {rename.NewColumnName}");
  401. }
  402. else
  403. {
  404. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` DROP COLUMN `{rename.OldColumnName}`");
  405. Trace.TraceInformation($"Ai-DOP S0 drop duplicate old column: {tableName}.{rename.OldColumnName}");
  406. }
  407. columns = db.DbMaintenance.GetColumnInfosByTableName(tableName, false) ?? [];
  408. continue;
  409. }
  410. RenameColumnMySql(db, databaseName, tableName, rename.OldColumnName, rename.NewColumnName);
  411. Trace.TraceInformation($"Ai-DOP S0 rename column: {tableName}.{rename.OldColumnName} -> {rename.NewColumnName}");
  412. columns = db.DbMaintenance.GetColumnInfosByTableName(tableName, false) ?? [];
  413. }
  414. }
  415. catch (Exception ex)
  416. {
  417. Trace.TraceError($"Ai-DOP S0 rename columns failed for {tableName}: {ex}");
  418. throw;
  419. }
  420. }
  421. RepairPrimaryKeys(db, databaseName);
  422. EnsureS0SalesAddonColumnsAndSeeds(db, databaseName);
  423. }
  424. /// <summary>
  425. /// 产销扩展列(客户全称、优先级业务维度、订单评审订单类型)及示范合同评审五阶段种子。
  426. /// </summary>
  427. private static void EnsureS0SalesAddonColumnsAndSeeds(ISqlSugarClient db, string databaseName)
  428. {
  429. EnsureColumn(db, databaseName, "CustMaster", "CustFullName",
  430. "varchar(500) NULL COMMENT '客户全称/正式名称'");
  431. EnsureColumn(db, databaseName, "StdOpMaster", "std_op_code",
  432. "varchar(100) NULL COMMENT '标准工序编码'");
  433. EnsureColumn(db, databaseName, "ItemSubstituteDetail", "SubstituteType",
  434. "varchar(20) NULL COMMENT '替代关系类型(替代/取代)'");
  435. EnsureColumn(db, databaseName, "SuppMaster", "address",
  436. "varchar(500) NULL COMMENT '地址'");
  437. EnsureColumn(db, databaseName, "SuppMaster", "contact",
  438. "varchar(200) NULL COMMENT '联系人'");
  439. EnsureColumn(db, databaseName, "SuppMaster", "position",
  440. "varchar(200) NULL COMMENT '职务'");
  441. EnsureColumn(db, databaseName, "SuppMaster", "contact_info",
  442. "varchar(200) NULL COMMENT '联系方式'");
  443. EnsureColumn(db, databaseName, "SuppMaster", "certification_level",
  444. "varchar(100) NULL COMMENT '认证等级'");
  445. EnsureColumn(db, databaseName, "EmpWorkDutyMaster", "ItemNum",
  446. "varchar(100) NULL COMMENT '单物料编码'");
  447. EnsureColumn(db, databaseName, "qms_sampscheme", "FFIXEDRATE",
  448. "decimal(10,4) NULL COMMENT '固定抽样比例(%)'");
  449. EnsureColumn(db, databaseName, "qms_lymjbmd", "wlbm",
  450. "varchar(255) NULL COMMENT '物料编码'");
  451. EnsureColumn(db, databaseName, "qms_lymjbmd", "wlmc",
  452. "varchar(255) NULL COMMENT '物料名称'");
  453. EnsureColumn(db, databaseName, "qms_lymjbmd", "dim_type",
  454. "varchar(50) NULL COMMENT '维度类型(supplier/material/material_supplier)'");
  455. EnsureColumn(db, databaseName, "qms_inspectioninstru", "gauge_category",
  456. "varchar(255) NULL COMMENT '计量器具分类'");
  457. EnsureColumn(db, databaseName, "qms_inspectioninstru", "calibration_cycle_days",
  458. "int NULL COMMENT '校准周期(天)'");
  459. EnsureColumn(db, databaseName, "qms_inspectioninstru", "next_calibration_date",
  460. "varchar(50) NULL COMMENT '下次校准日期'");
  461. EnsureColumn(db, databaseName, "PriorityCode", "ScopeCustClass",
  462. "varchar(100) NULL COMMENT '业务维度:客户类型/级别(可空=不限)'");
  463. EnsureColumn(db, databaseName, "PriorityCode", "ScopeOrderType",
  464. "varchar(100) NULL COMMENT '业务维度:订单类型(可空=不限)'");
  465. EnsureColumn(db, databaseName, "PriorityCode", "ScopeDueDaysMax",
  466. "int NULL COMMENT '业务维度:承诺交期上限天数(可空=不限)'");
  467. var hasOrderReviewTable = db.DbMaintenance.GetTableInfoList(false)
  468. .Any(t => t.Name.Equals("S0OrderReviewCycle", StringComparison.OrdinalIgnoreCase));
  469. if (hasOrderReviewTable)
  470. {
  471. EnsureColumn(db, databaseName, "S0OrderReviewCycle", "order_type",
  472. "varchar(100) NOT NULL DEFAULT '' COMMENT '订单类型;空字符串=默认/不限'");
  473. db.Ado.ExecuteCommand("UPDATE `S0OrderReviewCycle` SET `order_type` = '' WHERE `order_type` IS NULL");
  474. TryDropIndex(db, databaseName, "S0OrderReviewCycle", "uk_S0OrderReviewCycle_factory");
  475. EnsureUniqueIndex(db, databaseName, "S0OrderReviewCycle", "uk_S0OrderReviewCycle_factory_ordertype",
  476. "`factory_ref_id`, `order_type`");
  477. }
  478. EnsureContractReviewCycleDemoStages(db);
  479. }
  480. private static void EnsureColumn(ISqlSugarClient db, string databaseName, string tableName, string columnName, string columnDefinitionTail)
  481. {
  482. var tables = db.DbMaintenance.GetTableInfoList(false);
  483. if (!tables.Any(t => t.Name.Equals(tableName, StringComparison.OrdinalIgnoreCase)))
  484. return;
  485. var dbLit = databaseName.Replace("'", "''", StringComparison.Ordinal);
  486. var tblLit = tableName.Replace("'", "''", StringComparison.Ordinal);
  487. var colLit = columnName.Replace("'", "''", StringComparison.Ordinal);
  488. var count = db.Ado.SqlQuerySingle<int>(
  489. $"""
  490. SELECT COUNT(*) FROM information_schema.COLUMNS
  491. WHERE TABLE_SCHEMA = '{dbLit}' AND TABLE_NAME = '{tblLit}' AND COLUMN_NAME = '{colLit}'
  492. """);
  493. if (count > 0)
  494. return;
  495. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` ADD COLUMN `{columnName}` {columnDefinitionTail}");
  496. Trace.TraceInformation($"Ai-DOP S0 add column: {tableName}.{columnName}");
  497. }
  498. private static void TryDropIndex(ISqlSugarClient db, string databaseName, string tableName, string indexName)
  499. {
  500. var tables = db.DbMaintenance.GetTableInfoList(false);
  501. if (!tables.Any(t => t.Name.Equals(tableName, StringComparison.OrdinalIgnoreCase)))
  502. return;
  503. var dbLit = databaseName.Replace("'", "''", StringComparison.Ordinal);
  504. var tblLit = tableName.Replace("'", "''", StringComparison.Ordinal);
  505. var idxLit = indexName.Replace("'", "''", StringComparison.Ordinal);
  506. var count = db.Ado.SqlQuerySingle<int>(
  507. $"""
  508. SELECT COUNT(*) FROM information_schema.STATISTICS
  509. WHERE TABLE_SCHEMA = '{dbLit}' AND TABLE_NAME = '{tblLit}' AND INDEX_NAME = '{idxLit}'
  510. """);
  511. if (count == 0)
  512. return;
  513. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` DROP INDEX `{indexName}`");
  514. Trace.TraceInformation($"Ai-DOP S0 drop index: {tableName}.{indexName}");
  515. }
  516. private static void EnsureUniqueIndex(ISqlSugarClient db, string databaseName, string tableName, string indexName, string columnListSql)
  517. {
  518. var tables = db.DbMaintenance.GetTableInfoList(false);
  519. if (!tables.Any(t => t.Name.Equals(tableName, StringComparison.OrdinalIgnoreCase)))
  520. return;
  521. var dbLit = databaseName.Replace("'", "''", StringComparison.Ordinal);
  522. var tblLit = tableName.Replace("'", "''", StringComparison.Ordinal);
  523. var idxLit = indexName.Replace("'", "''", StringComparison.Ordinal);
  524. var count = db.Ado.SqlQuerySingle<int>(
  525. $"""
  526. SELECT COUNT(*) FROM information_schema.STATISTICS
  527. WHERE TABLE_SCHEMA = '{dbLit}' AND TABLE_NAME = '{tblLit}' AND INDEX_NAME = '{idxLit}'
  528. """);
  529. if (count > 0)
  530. return;
  531. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` ADD UNIQUE INDEX `{indexName}` ({columnListSql})");
  532. Trace.TraceInformation($"Ai-DOP S0 add unique index: {tableName}.{indexName}");
  533. }
  534. private static void EnsureContractReviewCycleDemoStages(ISqlSugarClient db)
  535. {
  536. const long s0CompanyId = 1329900200001L;
  537. const long s0Factory1Id = 1329900200002L;
  538. const long s0Factory2Id = 1329900200003L;
  539. var tables = db.DbMaintenance.GetTableInfoList(false);
  540. if (!tables.Any(t => t.Name.Equals("S0ContractReviewCycle", StringComparison.OrdinalIgnoreCase)))
  541. return;
  542. var stages = new (string Code, string Name, int Order)[]
  543. {
  544. ("CR1", "意见评审", 1),
  545. ("CR2", "意见反馈", 2),
  546. ("CR3", "二次评审", 3),
  547. ("CR4", "领导意见", 4),
  548. ("CR5", "合同盖章", 5),
  549. };
  550. foreach (var factoryId in new[] { s0Factory1Id, s0Factory2Id })
  551. {
  552. var hasAny = db.Queryable<AdoS0ContractReviewCycle>()
  553. .Where(x => x.FactoryRefId == factoryId)
  554. .Any();
  555. if (hasAny)
  556. continue;
  557. var now = DateTime.Now;
  558. foreach (var s in stages)
  559. {
  560. db.Insertable(new AdoS0ContractReviewCycle
  561. {
  562. CompanyRefId = s0CompanyId,
  563. FactoryRefId = factoryId,
  564. DomainCode = null,
  565. StageCode = s.Code,
  566. StageName = s.Name,
  567. StdHours = 0,
  568. OrderNo = s.Order,
  569. IsActive = true,
  570. CreateTime = now,
  571. }).ExecuteCommand();
  572. }
  573. Trace.TraceInformation($"Ai-DOP S0 seeded contract review stages for factory {factoryId}");
  574. }
  575. }
  576. private static void RenameColumnMySql(ISqlSugarClient db, string databaseName, string tableName, string oldColumnName, string newColumnName)
  577. {
  578. var meta = GetMySqlColumnMeta(db, databaseName, tableName, oldColumnName);
  579. if (meta == null)
  580. return;
  581. var ddl = $"ALTER TABLE `{tableName}` CHANGE COLUMN `{oldColumnName}` `{newColumnName}` {BuildColumnDefinition(meta)}";
  582. db.Ado.ExecuteCommand(ddl);
  583. }
  584. private static void RepairPrimaryKeys(ISqlSugarClient db, string databaseName)
  585. {
  586. var tableList = db.DbMaintenance.GetTableInfoList(false);
  587. foreach (var repair in PrimaryKeyRepairs)
  588. {
  589. var tableName = tableList.FirstOrDefault(t => t.Name.Equals(repair.TableName, StringComparison.OrdinalIgnoreCase))?.Name;
  590. if (string.IsNullOrEmpty(tableName))
  591. continue;
  592. var tableColumns = db.DbMaintenance.GetColumnInfosByTableName(tableName, false) ?? [];
  593. if (tableColumns.Count == 0)
  594. continue;
  595. foreach (var shadowColumn in repair.ShadowColumns)
  596. {
  597. if (tableColumns.Any(c => c.DbColumnName.Equals(shadowColumn, StringComparison.Ordinal)))
  598. {
  599. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` DROP COLUMN `{shadowColumn}`");
  600. }
  601. }
  602. SugarParameter[] pkParameters =
  603. [
  604. new SugarParameter("@db", databaseName),
  605. new SugarParameter("@table", tableName)
  606. ];
  607. var pkTable = db.Ado.GetDataTable(
  608. """
  609. SELECT COLUMN_NAME
  610. FROM information_schema.KEY_COLUMN_USAGE
  611. WHERE TABLE_SCHEMA = @db
  612. AND TABLE_NAME = @table
  613. AND CONSTRAINT_NAME = 'PRIMARY'
  614. ORDER BY ORDINAL_POSITION;
  615. """,
  616. pkParameters);
  617. var primaryKeyColumns = pkTable.Rows.Cast<DataRow>()
  618. .Select(r => r["COLUMN_NAME"]?.ToString())
  619. .Where(x => !string.IsNullOrWhiteSpace(x))
  620. .ToList();
  621. if (primaryKeyColumns.Count == 0)
  622. {
  623. primaryKeyColumns = tableColumns
  624. .Where(c => c.IsPrimarykey)
  625. .OrderBy(c => c.DbColumnName)
  626. .Select(c => c.DbColumnName)
  627. .Where(x => !string.IsNullOrWhiteSpace(x))
  628. .Select(x => (string?)x)
  629. .ToList();
  630. }
  631. var pkMatches = primaryKeyColumns.Count == 1
  632. && primaryKeyColumns[0]!.Equals(repair.PkColumnName, StringComparison.OrdinalIgnoreCase);
  633. if (!pkMatches)
  634. {
  635. if (primaryKeyColumns.Count > 0)
  636. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` DROP PRIMARY KEY");
  637. db.Ado.ExecuteCommand($"ALTER TABLE `{tableName}` ADD PRIMARY KEY(`{repair.PkColumnName}`)");
  638. }
  639. if (!repair.IsIdentity)
  640. continue;
  641. var meta = GetMySqlColumnMeta(db, databaseName, tableName, repair.PkColumnName)
  642. ?? GetMySqlColumnMeta(db, databaseName, tableName, primaryKeyColumns.FirstOrDefault() ?? repair.PkColumnName);
  643. if (meta == null || ContainsToken(meta.Extra, "auto_increment"))
  644. continue;
  645. var ddl = $"ALTER TABLE `{tableName}` MODIFY COLUMN `{meta.ColumnName}` {BuildColumnDefinition(meta, forceNotNull: true, forceAutoIncrement: true, skipDefault: true, commentOverride: repair.PkComment)}";
  646. db.Ado.ExecuteCommand(ddl);
  647. }
  648. }
  649. private static MySqlColumnMeta? GetMySqlColumnMeta(ISqlSugarClient db, string databaseName, string tableName, string columnName)
  650. {
  651. var sql = """
  652. SELECT
  653. COLUMN_NAME AS ColumnName,
  654. COLUMN_TYPE AS ColumnType,
  655. IS_NULLABLE AS IsNullable,
  656. COLUMN_DEFAULT AS ColumnDefault,
  657. EXTRA AS Extra,
  658. COLUMN_COMMENT AS ColumnComment,
  659. COLLATION_NAME AS CollationName,
  660. CHARACTER_SET_NAME AS CharacterSetName
  661. FROM information_schema.COLUMNS
  662. WHERE TABLE_SCHEMA = @db
  663. AND TABLE_NAME = @table
  664. AND BINARY COLUMN_NAME = @column
  665. LIMIT 1;
  666. """;
  667. SugarParameter[] parameters =
  668. [
  669. new SugarParameter("@db", databaseName),
  670. new SugarParameter("@table", tableName),
  671. new SugarParameter("@column", columnName)
  672. ];
  673. var table = db.Ado.GetDataTable(sql, parameters);
  674. if (table.Rows.Count == 0)
  675. return null;
  676. var row = table.Rows[0];
  677. return new MySqlColumnMeta(
  678. row["ColumnName"]?.ToString() ?? columnName,
  679. row["ColumnType"]?.ToString() ?? throw new InvalidOperationException($"Missing ColumnType for {tableName}.{columnName}"),
  680. row["IsNullable"]?.ToString() ?? "YES",
  681. row["ColumnDefault"] == DBNull.Value ? null : row["ColumnDefault"]?.ToString(),
  682. row["Extra"] == DBNull.Value ? null : row["Extra"]?.ToString(),
  683. row["ColumnComment"] == DBNull.Value ? null : row["ColumnComment"]?.ToString(),
  684. row["CollationName"] == DBNull.Value ? null : row["CollationName"]?.ToString(),
  685. row["CharacterSetName"] == DBNull.Value ? null : row["CharacterSetName"]?.ToString());
  686. }
  687. private static string BuildColumnDefinition(MySqlColumnMeta meta, bool forceNotNull = false, bool forceAutoIncrement = false, bool skipDefault = false, string? commentOverride = null)
  688. {
  689. var builder = new StringBuilder();
  690. builder.Append(meta.ColumnType);
  691. if (!string.IsNullOrWhiteSpace(meta.CharacterSetName))
  692. builder.Append($" CHARACTER SET {meta.CharacterSetName}");
  693. if (!string.IsNullOrWhiteSpace(meta.CollationName))
  694. builder.Append($" COLLATE {meta.CollationName}");
  695. var isNullable = !forceNotNull && meta.IsNullable.Equals("YES", StringComparison.OrdinalIgnoreCase);
  696. builder.Append(isNullable ? " NULL" : " NOT NULL");
  697. if (!skipDefault && meta.ColumnDefault != null)
  698. {
  699. builder.Append(" DEFAULT ");
  700. builder.Append(FormatDefaultValue(meta.ColumnType, meta.ColumnDefault));
  701. }
  702. else if (!skipDefault && isNullable &&
  703. !ContainsToken(meta.Extra, "auto_increment") &&
  704. !ContainsToken(meta.Extra, "DEFAULT_GENERATED"))
  705. {
  706. builder.Append(" DEFAULT NULL");
  707. }
  708. if (forceAutoIncrement || ContainsToken(meta.Extra, "auto_increment"))
  709. builder.Append(" AUTO_INCREMENT");
  710. if (ContainsToken(meta.Extra, "on update CURRENT_TIMESTAMP"))
  711. builder.Append(" ON UPDATE CURRENT_TIMESTAMP");
  712. var comment = commentOverride ?? meta.ColumnComment;
  713. if (!string.IsNullOrWhiteSpace(comment))
  714. builder.Append($" COMMENT '{EscapeSqlLiteral(comment)}'");
  715. return builder.ToString();
  716. }
  717. private static string FormatDefaultValue(string columnType, string columnDefault)
  718. {
  719. if (columnDefault.Equals("NULL", StringComparison.OrdinalIgnoreCase))
  720. return "NULL";
  721. if (columnDefault.StartsWith("CURRENT_TIMESTAMP", StringComparison.OrdinalIgnoreCase))
  722. return columnDefault;
  723. return IsNumericLikeType(columnType)
  724. ? columnDefault
  725. : $"'{EscapeSqlLiteral(columnDefault)}'";
  726. }
  727. private static bool IsNumericLikeType(string columnType)
  728. {
  729. var normalized = columnType.ToLowerInvariant();
  730. return normalized.StartsWith("tinyint") ||
  731. normalized.StartsWith("smallint") ||
  732. normalized.StartsWith("mediumint") ||
  733. normalized.StartsWith("int") ||
  734. normalized.StartsWith("bigint") ||
  735. normalized.StartsWith("decimal") ||
  736. normalized.StartsWith("numeric") ||
  737. normalized.StartsWith("float") ||
  738. normalized.StartsWith("double") ||
  739. normalized.StartsWith("real") ||
  740. normalized.StartsWith("bit") ||
  741. normalized.StartsWith("bool") ||
  742. normalized.StartsWith("boolean");
  743. }
  744. private static bool ContainsToken(string? value, string token)
  745. => !string.IsNullOrWhiteSpace(value) && value.Contains(token, StringComparison.OrdinalIgnoreCase);
  746. private static string EscapeSqlLiteral(string value)
  747. => value.Replace("\\", "\\\\").Replace("'", "\\'");
  748. }