T8BaseInboundMdpSyncService.NeutralProjection.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. using SqlSugar;
  2. namespace Admin.NET.Plugin.AiDOP.DataPlatform;
  3. /// <summary>
  4. /// 把 T8 形态标准层投影到中立标准层。厂商枚举只允许出现在本文件(与主服务同属 T8 适配器)。
  5. /// 指标 SQL 只读中立层。
  6. /// </summary>
  7. public sealed partial class T8BaseInboundMdpSyncService
  8. {
  9. /// <summary>中立层来源闸门(字段在主 partial 注入)。</summary>
  10. private MdpNeutralSourceGate NeutralGate => _neutralGate;
  11. public async Task<string> ProjectNeutralAsync(
  12. long tenantId, string batchId, DateTime now, CancellationToken cancellationToken = default)
  13. {
  14. cancellationToken.ThrowIfCancellationRequested();
  15. var ready = await _db.Ado.GetIntAsync(
  16. """
  17. SELECT COUNT(*) FROM information_schema.COLUMNS
  18. WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='mdp_std_inv_trans' AND COLUMN_NAME='src_trans_type_raw'
  19. """);
  20. if (ready == 0)
  21. return "中立层未就绪,已跳过投影";
  22. var ps = new[]
  23. {
  24. new SugarParameter("@tid", tenantId),
  25. new SugarParameter("@batch", batchId),
  26. new SugarParameter("@now", now)
  27. };
  28. var steps = new (string Name, string? Object, string Source, string Sql)[]
  29. {
  30. ("inv_trans", "INV_TRANS", "T8", ProjectInvTransSql),
  31. ("api_inv_trans", "INV_TRANS", "T8", ProjectApiInvTransSql),
  32. ("api_inv_trans_unmapped", null, "T8", ProjectApiInvTransUnmappedSql),
  33. ("work_order_schedule", "WO_SCHEDULE", "T8", ProjectWorkOrderScheduleSql),
  34. ("work_order_line", "WO_LINE", "T8", ProjectWorkOrderLineSql),
  35. ("work_order_bom", "WO_BOM", "T8", ProjectWorkOrderBomSql),
  36. ("employee", "EMPLOYEE", "T8", ProjectEmployeeSql),
  37. ("fqc", "FQC_TASK", "T8", ProjectFqcSql),
  38. ("report_start", "S6_REPORT", "T8", ProjectReportStartSql)
  39. };
  40. var failed = new List<string>();
  41. foreach (var step in steps)
  42. {
  43. cancellationToken.ThrowIfCancellationRequested();
  44. try
  45. {
  46. if (step.Name == "work_order_line")
  47. {
  48. var allowProd = await NeutralGate.AllowsAsync(tenantId, "WO_LINE_PROD", "T8");
  49. var allowSales = await NeutralGate.AllowsAsync(tenantId, "WO_LINE_SALES", "T8");
  50. if (!allowProd && !allowSales)
  51. continue;
  52. var lineSql = ProjectWorkOrderLineSql;
  53. if (allowProd && !allowSales)
  54. lineSql = lineSql.Replace(
  55. "WHERE l.tenant_id=@tid AND h.noid IS NOT NULL AND h.noid<>''",
  56. "WHERE l.tenant_id=@tid AND h.noid IS NOT NULL AND h.noid<>'' AND h.lbs='生产任务'",
  57. StringComparison.Ordinal);
  58. else if (!allowProd && allowSales)
  59. lineSql = lineSql.Replace(
  60. "WHERE l.tenant_id=@tid AND h.noid IS NOT NULL AND h.noid<>''",
  61. "WHERE l.tenant_id=@tid AND h.noid IS NOT NULL AND h.noid<>'' AND h.lbs='销售订单'",
  62. StringComparison.Ordinal);
  63. await _db.Ado.ExecuteCommandAsync(lineSql, ps);
  64. continue;
  65. }
  66. if (step.Object != null
  67. && !await NeutralGate.AllowsAsync(tenantId, step.Object, step.Source))
  68. continue;
  69. if (step.Name == "employee")
  70. await _positionMap.SyncT8Async(tenantId, cancellationToken);
  71. await _db.Ado.ExecuteCommandAsync(step.Sql, ps);
  72. }
  73. catch (Exception ex) when (ex is not OperationCanceledException)
  74. {
  75. failed.Add($"{step.Name}: {ex.Message}");
  76. }
  77. }
  78. return failed.Count == 0 ? "OK" : string.Join(" | ", failed);
  79. }
  80. /// <summary>
  81. /// 表值函数结果落入月度库存金额表。T8 未配置或调用失败时返回 0,不抛出,避免挡住推送现场。
  82. /// </summary>
  83. public async Task<int> TryMaterializeInventoryBalanceAsync(
  84. long tenantId, long factoryId, string domainCode, string periodYm, string batchId, DateTime now)
  85. {
  86. const string sqlTvf = @"
  87. select ckcode as ckcode, ckname as ckname,
  88. code as code, cname as cname,
  89. pcode as pcode, pname as pname,
  90. je3 as je3, je2 as je2
  91. from dbo.Rep_总账_存货_V3(@domainCode, N'普通', N'正常', @startYm, @endYm)";
  92. List<T8InventoryBalanceRow> rows;
  93. try
  94. {
  95. var t8 = await _sourceScope.GetScopeBySystemCodeAsync("T8");
  96. t8.Ado.CommandTimeOut = 60;
  97. rows = await t8.Ado.SqlQueryAsync<T8InventoryBalanceRow>(sqlTvf, new[]
  98. {
  99. new SugarParameter("@domainCode", domainCode),
  100. new SugarParameter("@startYm", periodYm),
  101. new SugarParameter("@endYm", periodYm)
  102. });
  103. }
  104. catch (Exception ex)
  105. {
  106. Console.WriteLine($"[NeutralBalance] TVF skipped: {ex.Message}");
  107. return 0;
  108. }
  109. if (!await NeutralGate.AllowsAsync(tenantId, "INV_BAL_MONTHLY", "T8"))
  110. return 0;
  111. var affected = 0;
  112. foreach (var r in rows)
  113. {
  114. var category = r.pcode ?? "";
  115. var warehouse = r.ckcode ?? "";
  116. var item = r.code ?? "";
  117. affected += await _db.Ado.ExecuteCommandAsync(
  118. """
  119. INSERT INTO mdp_std_inventory_balance_monthly
  120. (tenant_id, factory_id, source_system, domain, period_ym,
  121. category_code, category_name, warehouse_code, warehouse_name, item_code,
  122. avg_balance_amount, issue_cost_amount, source_biz_key, sync_batch_id, sync_time)
  123. VALUES
  124. (@tid, @factoryId, 'T8', @domain, @period,
  125. @category, @categoryName, @warehouse, @warehouseName, @item,
  126. @avgAmt, @issueAmt, @bizKey, @batch, @now)
  127. ON DUPLICATE KEY UPDATE
  128. category_name=VALUES(category_name), warehouse_name=VALUES(warehouse_name),
  129. avg_balance_amount=VALUES(avg_balance_amount),
  130. issue_cost_amount=VALUES(issue_cost_amount),
  131. sync_batch_id=VALUES(sync_batch_id), sync_time=VALUES(sync_time)
  132. """,
  133. new SugarParameter("@tid", tenantId),
  134. new SugarParameter("@factoryId", factoryId),
  135. new SugarParameter("@domain", domainCode),
  136. new SugarParameter("@period", periodYm),
  137. new SugarParameter("@category", category),
  138. new SugarParameter("@categoryName", r.pname),
  139. new SugarParameter("@warehouse", warehouse),
  140. new SugarParameter("@warehouseName", r.ckname),
  141. new SugarParameter("@item", item),
  142. new SugarParameter("@avgAmt", r.je3 ?? 0m),
  143. new SugarParameter("@issueAmt", r.je2 ?? 0m),
  144. new SugarParameter("@bizKey", $"{domainCode}:{periodYm}:{category}:{warehouse}:{item}"),
  145. new SugarParameter("@batch", batchId),
  146. new SugarParameter("@now", now));
  147. }
  148. return affected;
  149. }
  150. private const string BizDocCase = """
  151. CASE h.lbs
  152. WHEN '采购入库' THEN 'PUR_RECEIPT'
  153. WHEN '生产领料' THEN 'PROD_ISSUE'
  154. WHEN '生产入库' THEN 'PROD_RECEIPT'
  155. WHEN '销售出库' THEN 'SALES_SHIP'
  156. WHEN '销售退货' THEN 'SALES_RETURN'
  157. ELSE 'OTHER' END
  158. """;
  159. private static readonly string ProjectInvTransSql = $@"
  160. INSERT INTO mdp_std_inv_trans
  161. (tenant_id, source_system, written_by, domain, src_rec_id, item_num, qty_change, doc_qty,
  162. location, lot_serial, create_user, end_balance,
  163. trans_time, eff_date, approved_time, approved_flag, void_flag, summary_flag,
  164. biz_doc_type, src_biz_doc_type_raw, trans_type, ref_task_no,
  165. line_closed_flag, line_closed_time,
  166. history_from, as_of, sync_batch_id, dimension1, dimension2)
  167. SELECT
  168. l.tenant_id, 'T8', 'DB_SYNC', IFNULL(h.ztid,''), CAST(l.src_id AS CHAR),
  169. l.code, IFNULL(l.slzx,0), l.sl,
  170. COALESCE(NULLIF(l.hw,''), l.ckcode), l.pcnoid, h.zbrname, l.kcsl,
  171. l.addtime, h.date0, IFNULL(h.shtime, l.addtime),
  172. IFNULL(h.shyn,1), IFNULL(h.zfyn,0), IFNULL(h.hzyn,0),
  173. {BizDocCase}, h.lbs,
  174. {NeutralTransTypeCodes.TransTypeLookup("h.lbs", "''", "0", "'T8'")},
  175. l.lynoid,
  176. IFNULL(l.gdyn,0), l.gdtime,
  177. IFNULL(IFNULL(h.shtime, l.addtime), @now), @now, @batch, '', ''
  178. FROM mdp_std_t8_kc_tz_list l
  179. INNER JOIN mdp_std_t8_kc_tz_head h ON h.src_id=l.idid AND h.tenant_id=l.tenant_id
  180. WHERE l.tenant_id=@tid
  181. ON DUPLICATE KEY UPDATE
  182. item_num=VALUES(item_num), qty_change=VALUES(qty_change), doc_qty=VALUES(doc_qty),
  183. location=VALUES(location), lot_serial=VALUES(lot_serial), create_user=VALUES(create_user), end_balance=VALUES(end_balance),
  184. written_by=VALUES(written_by),
  185. trans_time=VALUES(trans_time), eff_date=VALUES(eff_date), approved_time=VALUES(approved_time),
  186. approved_flag=VALUES(approved_flag), void_flag=VALUES(void_flag), summary_flag=VALUES(summary_flag),
  187. biz_doc_type=VALUES(biz_doc_type), src_biz_doc_type_raw=VALUES(src_biz_doc_type_raw),
  188. trans_type=VALUES(trans_type), ref_task_no=VALUES(ref_task_no),
  189. line_closed_flag=VALUES(line_closed_flag), line_closed_time=VALUES(line_closed_time),
  190. sync_batch_id=VALUES(sync_batch_id), as_of=VALUES(as_of)";
  191. private static readonly string ProjectApiInvTransSql = BuildProjectApiInvTransSql();
  192. private static string BuildProjectApiInvTransSql()
  193. {
  194. const string biz = "NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.BizDocType')),'null')";
  195. const string trans = "NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.TransType')),'null')";
  196. const string src = "COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SrcTransType')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.BizDocType')),'null'))";
  197. return $@"
  198. INSERT INTO mdp_std_inv_trans
  199. (tenant_id, source_system, written_by, domain, src_rec_id, item_num, qty_change, location,
  200. lot_serial, create_user, begin_balance, end_balance, doc_qty, line_closed_flag,
  201. trans_time, eff_date, approved_time, approved_flag, void_flag, summary_flag,
  202. biz_doc_type, src_biz_doc_type_raw, trans_type, src_trans_type_raw, ref_task_no,
  203. history_from, as_of, sync_batch_id, dimension1, dimension2)
  204. SELECT
  205. s.tenant_id,
  206. IFNULL(NULLIF(s.source_system,''),''),
  207. 'API_INBOUND',
  208. IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Domain')),'null'),''),
  209. s.source_row_id,
  210. COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ItemCode')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.code')),'null')),
  211. CAST(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Qty')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.sl')),'null')) AS DECIMAL(18,6)),
  212. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Location')),'null'),
  213. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.LotSerial')),'null'),
  214. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.CreateUser')),'null'),
  215. CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.BeginBalance')),'null') AS DECIMAL(18,6)),
  216. CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.EndBalance')),'null') AS DECIMAL(18,6)),
  217. CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DocQty')),'null') AS DECIMAL(18,6)),
  218. IFNULL(CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.LineClosedFlag')),'null') AS SIGNED), 0),
  219. STR_TO_DATE(SUBSTRING_INDEX(REPLACE(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.TransTime')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.addtime')),'null')),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
  220. STR_TO_DATE(SUBSTRING_INDEX(REPLACE(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.DocDate')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.date0')),'null')),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
  221. IFNULL(
  222. STR_TO_DATE(SUBSTRING_INDEX(REPLACE(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ApprovedTime')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.shtime')),'null')),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
  223. STR_TO_DATE(SUBSTRING_INDEX(REPLACE(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.TransTime')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.addtime')),'null')),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s')),
  224. IFNULL(CAST(COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ApprovedFlag')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.shyn')),'null')) AS SIGNED), 1),
  225. IFNULL(CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.VoidFlag')),'null') AS SIGNED), 0),
  226. IFNULL(CAST(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.SummaryFlag')),'null') AS SIGNED), 0),
  227. {NeutralTransTypeCodes.KnownBizDocCase(biz)},
  228. {biz},
  229. {NeutralTransTypeCodes.ApiTransTypeCase(trans, biz)},
  230. {src},
  231. COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.RefTaskNo')),'null'), NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.rwnoid')),'null')),
  232. IFNULL(
  233. STR_TO_DATE(SUBSTRING_INDEX(REPLACE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.ApprovedTime')),'null'),'T',' '),'.',1),'%Y-%m-%d %H:%i:%s'),
  234. @now),
  235. @now, @batch,
  236. IFNULL(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(s.raw_data,'$.Dimension1')),'null'), ''),
  237. ''
  238. FROM mdp_stg_inv_trans_inbound s
  239. WHERE s.tenant_id=@tid
  240. AND s.source_row_id IS NOT NULL AND s.source_row_id<>''
  241. ON DUPLICATE KEY UPDATE
  242. item_num=VALUES(item_num), qty_change=VALUES(qty_change), location=VALUES(location),
  243. lot_serial=VALUES(lot_serial), create_user=VALUES(create_user),
  244. begin_balance=VALUES(begin_balance), end_balance=VALUES(end_balance),
  245. doc_qty=VALUES(doc_qty), line_closed_flag=VALUES(line_closed_flag), dimension1=VALUES(dimension1),
  246. approved_time=VALUES(approved_time), approved_flag=VALUES(approved_flag),
  247. void_flag=VALUES(void_flag), summary_flag=VALUES(summary_flag),
  248. biz_doc_type=VALUES(biz_doc_type), trans_type=VALUES(trans_type),
  249. src_trans_type_raw=VALUES(src_trans_type_raw),
  250. ref_task_no=VALUES(ref_task_no), sync_batch_id=VALUES(sync_batch_id)";
  251. }
  252. private const string ProjectApiInvTransUnmappedSql = @"
  253. INSERT INTO mdp_std_inv_trans_unmapped
  254. (tenant_id, source_system, src_rec_id, src_trans_type_raw, unmapped_reason, location, row_count, first_seen, last_seen)
  255. SELECT tenant_id, source_system, src_rec_id, src_trans_type_raw, 'UNKNOWN_CODE', IFNULL(location,''), 1, NOW(), NOW()
  256. FROM mdp_std_inv_trans
  257. WHERE tenant_id=@tid AND sync_batch_id=@batch
  258. AND trans_type IS NULL AND src_trans_type_raw IS NOT NULL
  259. ON DUPLICATE KEY UPDATE last_seen=NOW(), row_count=row_count+1, unmapped_reason=VALUES(unmapped_reason), location=VALUES(location)";
  260. private const string ProjectWorkOrderScheduleSql = @"
  261. INSERT INTO mdp_std_work_order_schedule
  262. (tenant_id, factory_id, source_system, work_order, doc_type, approved_flag, void_flag,
  263. source_biz_key, sync_batch_id, sync_time)
  264. SELECT
  265. h.tenant_id, 1, 'T8', h.noid,
  266. CASE h.lbs WHEN '生产任务' THEN 'PROD_TASK' WHEN '销售订单' THEN 'SALES_ORDER' ELSE 'OTHER' END,
  267. IFNULL(h.shyn,1), IFNULL(h.zf,0),
  268. CONCAT(IFNULL(h.ztid,''), ':', h.src_id),
  269. @batch, @now
  270. FROM mdp_std_t8_kc_dd_head h
  271. WHERE h.tenant_id=@tid AND h.noid IS NOT NULL AND h.noid<>''
  272. AND NOT EXISTS (
  273. SELECT 1 FROM mdp_std_work_order_schedule w
  274. WHERE w.tenant_id=h.tenant_id AND w.work_order=h.noid AND w.source_system<>'T8'
  275. AND w.doc_type = CASE h.lbs WHEN '销售订单' THEN 'SALES_ORDER' ELSE 'PROD_TASK' END)
  276. ON DUPLICATE KEY UPDATE
  277. approved_flag=VALUES(approved_flag), void_flag=VALUES(void_flag),
  278. source_biz_key=VALUES(source_biz_key), sync_batch_id=VALUES(sync_batch_id), sync_time=VALUES(sync_time)";
  279. private const string ProjectWorkOrderLineSql = @"
  280. INSERT INTO mdp_std_work_order_line
  281. (tenant_id, factory_id, source_system, domain, doc_type, src_doc_type_raw,
  282. order_no, task_no, item_code, qty_planned, qty_completed, plan_finish_date, release_time,
  283. closed_flag, closed_time, approved_flag, void_flag, source_row_id, source_biz_key, sync_batch_id, sync_time)
  284. SELECT
  285. l.tenant_id, 1, 'T8', h.ztid,
  286. CASE h.lbs WHEN '生产任务' THEN 'PROD_TASK' WHEN '销售订单' THEN 'SALES_ORDER' ELSE 'OTHER' END,
  287. h.lbs, h.noid, l.rwnoid, l.code, l.sl, l.slzx, l.jhdate, l.addtime,
  288. IFNULL(l.gdyn,0), l.gdtime, IFNULL(h.shyn,1), IFNULL(h.zf,0),
  289. CAST(l.src_id AS CHAR), CONCAT(IFNULL(h.ztid,''), ':', l.src_id), @batch, @now
  290. FROM mdp_std_t8_kc_dd_list l
  291. INNER JOIN mdp_std_t8_kc_dd_head h ON h.src_id=l.idid AND h.tenant_id=l.tenant_id
  292. WHERE l.tenant_id=@tid AND h.noid IS NOT NULL AND h.noid<>''
  293. ON DUPLICATE KEY UPDATE
  294. doc_type=VALUES(doc_type), task_no=VALUES(task_no), item_code=VALUES(item_code),
  295. qty_planned=VALUES(qty_planned), qty_completed=VALUES(qty_completed),
  296. plan_finish_date=VALUES(plan_finish_date), release_time=VALUES(release_time),
  297. closed_flag=VALUES(closed_flag), closed_time=VALUES(closed_time),
  298. approved_flag=VALUES(approved_flag), void_flag=VALUES(void_flag),
  299. sync_batch_id=VALUES(sync_batch_id), sync_time=VALUES(sync_time)";
  300. private const string ProjectWorkOrderBomSql = @"
  301. INSERT INTO mdp_std_work_order_bom
  302. (tenant_id, factory_id, source_system, domain, order_no, item_code, qty_required,
  303. source_row_id, source_biz_key, sync_batch_id, sync_time)
  304. SELECT
  305. l.tenant_id, 1, 'T8', h.ztid, h.noid, l.code, IFNULL(l.sl, 0),
  306. CAST(l.src_id AS CHAR), CONCAT(IFNULL(h.ztid,''), ':', l.src_id), @batch, @now
  307. FROM mdp_std_t8_kc_dd_list_cllist l
  308. INNER JOIN mdp_std_t8_kc_dd_head h ON h.src_id=l.idid AND h.tenant_id=l.tenant_id
  309. WHERE l.tenant_id=@tid AND h.noid IS NOT NULL AND h.noid<>''
  310. ON DUPLICATE KEY UPDATE
  311. order_no=VALUES(order_no), item_code=VALUES(item_code), qty_required=VALUES(qty_required),
  312. sync_batch_id=VALUES(sync_batch_id), sync_time=VALUES(sync_time)";
  313. private const string ProjectEmployeeSql = @"
  314. INSERT INTO mdp_std_employee
  315. (tenant_id, factory_id, source_system, domain, employee_no, position_code, src_position_raw,
  316. employment_status, src_employment_status_raw, source_row_id, source_biz_key, sync_batch_id, sync_time)
  317. SELECT
  318. p.tenant_id, 1, 'T8', IFNULL(p.ztid,''), CAST(p.src_id AS CHAR),
  319. IFNULL(m.position_code, 'UNKNOWN'),
  320. p.gw,
  321. CASE WHEN p.zzzt='在职' THEN 'ACTIVE' WHEN p.zzzt LIKE '%离职%' THEN 'LEFT' ELSE 'INACTIVE' END,
  322. p.zzzt,
  323. CAST(p.src_id AS CHAR), CONCAT(IFNULL(p.ztid,''), ':', p.src_id), @batch, @now
  324. FROM mdp_std_t8_sys_pelist p
  325. LEFT JOIN mdp_employee_position_map m
  326. ON m.tenant_id=p.tenant_id AND m.source_system='T8'
  327. AND m.domain=IFNULL(p.ztid,'') AND m.src_position_raw=p.gw
  328. WHERE p.tenant_id=@tid AND p.src_id IS NOT NULL
  329. ON DUPLICATE KEY UPDATE
  330. position_code=VALUES(position_code), src_position_raw=VALUES(src_position_raw),
  331. employment_status=VALUES(employment_status), src_employment_status_raw=VALUES(src_employment_status_raw),
  332. sync_batch_id=VALUES(sync_batch_id), sync_time=VALUES(sync_time)";
  333. private const string ProjectFqcSql = @"
  334. INSERT INTO mdp_std_fqc_task
  335. (tenant_id, source_system, domain, apply_time, apply_flag, sales_order_line,
  336. source_row_id, source_biz_key, sync_batch_id, sync_time)
  337. SELECT
  338. z.tenant_id, 'T8', z.ztid, z.shdate, IFNULL(z.zjyn,0), CAST(z.lyid AS CHAR),
  339. CAST(z.src_id AS CHAR), CONCAT(IFNULL(z.ztid,''), ':', z.src_id), @batch, @now
  340. FROM mdp_std_t8_kc_zj_list z
  341. WHERE z.tenant_id=@tid AND z.src_id IS NOT NULL
  342. ON DUPLICATE KEY UPDATE
  343. domain=VALUES(domain), apply_time=VALUES(apply_time), apply_flag=VALUES(apply_flag),
  344. sales_order_line=VALUES(sales_order_line),
  345. sync_batch_id=VALUES(sync_batch_id), sync_time=VALUES(sync_time)";
  346. private const string ProjectReportStartSql = @"
  347. INSERT INTO mdp_std_s6_report
  348. (tenant_id, source_system, work_order_no, start_work_date, domain,
  349. source_row_id, source_biz_key, sync_batch_id, sync_time)
  350. SELECT
  351. r.tenant_id, 'T8', r.noid, r.kgdate, r.ztid,
  352. CAST(r.src_id AS CHAR), CONCAT(IFNULL(r.ztid,''), ':', r.src_id), @batch, @now
  353. FROM mdp_std_t8_cj_bg_head_rep r
  354. WHERE r.tenant_id=@tid AND r.noid IS NOT NULL AND r.noid<>'' AND r.src_id IS NOT NULL
  355. ON DUPLICATE KEY UPDATE
  356. start_work_date=VALUES(start_work_date), domain=VALUES(domain),
  357. sync_batch_id=VALUES(sync_batch_id), sync_time=VALUES(sync_time)";
  358. }
  359. internal sealed class T8InventoryBalanceRow
  360. {
  361. public string? ckcode { get; set; }
  362. public string? ckname { get; set; }
  363. public string? code { get; set; }
  364. public string? cname { get; set; }
  365. public string? pcode { get; set; }
  366. public string? pname { get; set; }
  367. public decimal? je3 { get; set; }
  368. public decimal? je2 { get; set; }
  369. }