SmartDiagnosisEvidenceRegistry.cs 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388
  1. namespace Admin.NET.Plugin.AiDOP.SmartOps;
  2. public enum SmartDiagnosisEvidenceDomain
  3. {
  4. Delivery,
  5. Supply,
  6. Manufacturing,
  7. Quality,
  8. Exception
  9. }
  10. public sealed record SmartDiagnosisEvidenceFilterColumn(string QueryKey, string SqlColumn);
  11. public sealed record SmartDiagnosisEvidenceSource(
  12. string Key,
  13. SmartDiagnosisEvidenceDomain Domain,
  14. IReadOnlyList<string> Modules,
  15. string ObjectType,
  16. string DrillPath,
  17. string CountSql,
  18. string ItemSql,
  19. IReadOnlyList<SmartDiagnosisEvidenceFilterColumn> Filters)
  20. {
  21. public IReadOnlyList<string> MetricCodes { get; init; } = Array.Empty<string>();
  22. public string ContributionUnit { get; init; } = "qty";
  23. public string? DateColumn { get; init; }
  24. public string? DrillQueryKey { get; init; }
  25. }
  26. public static class SmartDiagnosisEvidenceRegistry
  27. {
  28. public const int DefaultLimit = 20;
  29. public const int MaxLimit = 50;
  30. private static readonly SmartDiagnosisEvidenceSource[] Sources =
  31. {
  32. new(
  33. "s1_contract_review_flow",
  34. SmartDiagnosisEvidenceDomain.Delivery,
  35. new[] { "S1" },
  36. "contract_review_flow",
  37. "/aidop/s1/order-mgmt/contract-review",
  38. """
  39. SELECT COUNT(*) FROM mdp_stg_so
  40. WHERE tenant_id=@tenantId
  41. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  42. AND (factory_id IS NULL OR factory_id<>@tenantId)
  43. AND source_table='ado_contract_review_flow'
  44. AND (
  45. (JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StageNo')) =
  46. CASE
  47. WHEN @metricCode IN ('S1_L3_001','S1_L3_101') THEN '1'
  48. WHEN @metricCode IN ('S1_L3_002','S1_L3_102') THEN '2'
  49. WHEN @metricCode IN ('S1_L3_003','S1_L3_103') THEN '3'
  50. WHEN @metricCode IN ('S1_L3_004','S1_L3_104') THEN '4'
  51. WHEN @metricCode IN ('S1_L3_005','S1_L3_105') THEN '5'
  52. ELSE ''
  53. END)
  54. OR
  55. (JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StageNo'))='1'
  56. AND CASE COALESCE(
  57. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.DeptNo')),''),
  58. JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Department'))
  59. )
  60. WHEN '法律事务部' THEN 'LAW'
  61. WHEN '技术售前组' THEN 'PRE_SALES'
  62. WHEN '综合主计划' THEN 'MPS'
  63. WHEN '试验站' THEN 'TEST'
  64. ELSE COALESCE(
  65. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.DeptNo')),''),
  66. JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Department'))
  67. )
  68. END =
  69. CASE
  70. WHEN @metricCode IN ('S1_L4_001','S1_L4_101') THEN 'LAW'
  71. WHEN @metricCode IN ('S1_L4_002','S1_L4_102') THEN 'PRE_SALES'
  72. WHEN @metricCode IN ('S1_L4_003','S1_L4_103') THEN 'MPS'
  73. WHEN @metricCode IN ('S1_L4_004','S1_L4_104') THEN 'TEST'
  74. ELSE ''
  75. END)
  76. )
  77. """,
  78. """
  79. SELECT
  80. COALESCE(
  81. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.FlowNo')),''),
  82. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.ReviewNo')),''),
  83. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.ContractNo')),''),
  84. NULLIF(source_biz_key,''),
  85. source_row_id
  86. ) AS ObjectCode,
  87. CONCAT(
  88. COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Department')),''),'评审环节'),
  89. ' / ',
  90. COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StageName')),''),'阶段 ',
  91. JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StageNo')))
  92. ) AS Title,
  93. COALESCE(
  94. TIMESTAMPDIFF(
  95. HOUR,
  96. STR_TO_DATE(REPLACE(NULLIF(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StartTime')),'null'),''),'T',' '), '%Y-%m-%d %H:%i:%s.%f'),
  97. STR_TO_DATE(REPLACE(NULLIF(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.CompleteTime')),'null'),''),'T',' '), '%Y-%m-%d %H:%i:%s.%f')
  98. ),
  99. CASE
  100. WHEN JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.ActualDays')) REGEXP '^-?[0-9]+(\\.[0-9]+)?$'
  101. THEN CAST(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.ActualDays')) AS DECIMAL(18,6)) * 24
  102. END,
  103. 0
  104. ) AS Contribution,
  105. CASE
  106. WHEN JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Status')) IN ('逾期','超时','REJECTED','FAILED') THEN 'red'
  107. WHEN JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.CompleteTime')) IS NULL THEN 'yellow'
  108. ELSE 'green'
  109. END AS Status,
  110. COALESCE(
  111. STR_TO_DATE(REPLACE(NULLIF(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.CompleteTime')),'null'),''),'T',' '), '%Y-%m-%d %H:%i:%s.%f'),
  112. STR_TO_DATE(REPLACE(NULLIF(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StartTime')),'null'),''),'T',' '), '%Y-%m-%d %H:%i:%s.%f'),
  113. sync_time
  114. ) AS OccurredAt
  115. FROM mdp_stg_so
  116. WHERE tenant_id=@tenantId
  117. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  118. AND (factory_id IS NULL OR factory_id<>@tenantId)
  119. AND source_table='ado_contract_review_flow'
  120. AND (
  121. (JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StageNo')) =
  122. CASE
  123. WHEN @metricCode IN ('S1_L3_001','S1_L3_101') THEN '1'
  124. WHEN @metricCode IN ('S1_L3_002','S1_L3_102') THEN '2'
  125. WHEN @metricCode IN ('S1_L3_003','S1_L3_103') THEN '3'
  126. WHEN @metricCode IN ('S1_L3_004','S1_L3_104') THEN '4'
  127. WHEN @metricCode IN ('S1_L3_005','S1_L3_105') THEN '5'
  128. ELSE ''
  129. END)
  130. OR
  131. (JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.StageNo'))='1'
  132. AND CASE COALESCE(
  133. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.DeptNo')),''),
  134. JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Department'))
  135. )
  136. WHEN '法律事务部' THEN 'LAW'
  137. WHEN '技术售前组' THEN 'PRE_SALES'
  138. WHEN '综合主计划' THEN 'MPS'
  139. WHEN '试验站' THEN 'TEST'
  140. ELSE COALESCE(
  141. NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.DeptNo')),''),
  142. JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Department'))
  143. )
  144. END =
  145. CASE
  146. WHEN @metricCode IN ('S1_L4_001','S1_L4_101') THEN 'LAW'
  147. WHEN @metricCode IN ('S1_L4_002','S1_L4_102') THEN 'PRE_SALES'
  148. WHEN @metricCode IN ('S1_L4_003','S1_L4_103') THEN 'MPS'
  149. WHEN @metricCode IN ('S1_L4_004','S1_L4_104') THEN 'TEST'
  150. ELSE ''
  151. END)
  152. )
  153. ORDER BY Contribution DESC, OccurredAt DESC
  154. LIMIT @limit
  155. """,
  156. Array.Empty<SmartDiagnosisEvidenceFilterColumn>())
  157. {
  158. ContributionUnit = "小时",
  159. MetricCodes = new[]
  160. {
  161. "S1_L3_001", "S1_L3_002", "S1_L3_003", "S1_L3_004", "S1_L3_005",
  162. "S1_L3_101", "S1_L3_102", "S1_L3_103", "S1_L3_104", "S1_L3_105",
  163. "S1_L4_001", "S1_L4_002", "S1_L4_003", "S1_L4_004",
  164. "S1_L4_101", "S1_L4_102", "S1_L4_103", "S1_L4_104",
  165. }
  166. },
  167. new(
  168. "order_schedule",
  169. SmartDiagnosisEvidenceDomain.Manufacturing,
  170. new[] { "S1", "S2", "S6" },
  171. "work_order",
  172. "/aidop/s2/work-order-scheduling",
  173. """
  174. SELECT COUNT(*) FROM dwd_order_schedule_trans
  175. WHERE tenant_id=@tenantId
  176. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  177. AND (factory_id IS NULL OR factory_id<>@tenantId)
  178. AND IFNULL(work_order,'')<>''
  179. """,
  180. """
  181. SELECT work_order AS ObjectCode,
  182. CONCAT(IFNULL(sales_order_no,''),' / ',IFNULL(work_order,''),' / ',IFNULL(item_code,'')) AS Title,
  183. GREATEST(IFNULL(qty_ordered,0)-IFNULL(qty_completed,0),0) AS Contribution,
  184. CASE
  185. WHEN IFNULL(schedule_satisfaction_flag,1)=0 OR (due_date IS NOT NULL AND due_date<CURDATE()) THEN 'red'
  186. WHEN IFNULL(wip_qty,0)>0 THEN 'yellow'
  187. ELSE 'green'
  188. END AS Status,
  189. COALESCE(due_date, stat_date) AS OccurredAt
  190. FROM dwd_order_schedule_trans
  191. WHERE tenant_id=@tenantId
  192. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  193. AND (factory_id IS NULL OR factory_id<>@tenantId)
  194. AND IFNULL(work_order,'')<>''
  195. ORDER BY Contribution DESC, OccurredAt
  196. LIMIT @limit
  197. """,
  198. new[]
  199. {
  200. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order"),
  201. new SmartDiagnosisEvidenceFilterColumn("orderNo", "sales_order_no"),
  202. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  203. new SmartDiagnosisEvidenceFilterColumn("productionLine", "prod_line"),
  204. }),
  205. new(
  206. "supplier_delivery",
  207. SmartDiagnosisEvidenceDomain.Supply,
  208. new[] { "S3", "S4" },
  209. "purchase_order",
  210. "/aidop/s4/purchase-execution",
  211. """
  212. SELECT COUNT(*) FROM dwd_supplier_delivery
  213. WHERE tenant_id=@tenantId
  214. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  215. AND (factory_id IS NULL OR factory_id<>@tenantId)
  216. AND IFNULL(po_no,'')<>''
  217. """,
  218. """
  219. SELECT po_no AS ObjectCode,
  220. CONCAT(IFNULL(supplier_name,supplier_code),' / ',IFNULL(item_code,''),' / ',IFNULL(po_no,'')) AS Title,
  221. GREATEST(IFNULL(remaining_qty,0),0) AS Contribution,
  222. CASE
  223. WHEN UPPER(IFNULL(risk_level,'')) IN ('HIGH','RED')
  224. OR UPPER(IFNULL(delivery_status,'')) IN ('OVERDUE','DELAYED','LATE') THEN 'red'
  225. WHEN IFNULL(remaining_qty,0)>0 THEN 'yellow'
  226. ELSE 'green'
  227. END AS Status,
  228. COALESCE(due_date, stat_date) AS OccurredAt
  229. FROM dwd_supplier_delivery
  230. WHERE tenant_id=@tenantId
  231. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  232. AND (factory_id IS NULL OR factory_id<>@tenantId)
  233. AND IFNULL(po_no,'')<>''
  234. ORDER BY Contribution DESC, OccurredAt
  235. LIMIT @limit
  236. """,
  237. new[]
  238. {
  239. new SmartDiagnosisEvidenceFilterColumn("poNo", "po_no"),
  240. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  241. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  242. }),
  243. new(
  244. "material_readiness",
  245. SmartDiagnosisEvidenceDomain.Supply,
  246. new[] { "S3" },
  247. "work_order",
  248. "/aidop/s3/material-readiness",
  249. """
  250. SELECT COUNT(*) FROM dwd_material_readiness
  251. WHERE tenant_id=@tenantId
  252. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  253. AND (factory_id IS NULL OR factory_id<>@tenantId)
  254. AND IFNULL(shortage_qty,0)>0
  255. """,
  256. """
  257. SELECT work_order AS ObjectCode,
  258. CONCAT('缺料 ',IFNULL(work_order,''),' / ',IFNULL(supplier_code,'')) AS Title,
  259. IFNULL(shortage_qty,0) AS Contribution,
  260. 'red' AS Status,
  261. stat_date AS OccurredAt
  262. FROM dwd_material_readiness
  263. WHERE tenant_id=@tenantId
  264. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  265. AND (factory_id IS NULL OR factory_id<>@tenantId)
  266. AND IFNULL(shortage_qty,0)>0
  267. ORDER BY Contribution DESC, OccurredAt
  268. LIMIT @limit
  269. """,
  270. new[]
  271. {
  272. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order"),
  273. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  274. }),
  275. new(
  276. "s6_report",
  277. SmartDiagnosisEvidenceDomain.Manufacturing,
  278. new[] { "S6" },
  279. "work_order",
  280. "/aidop/s6/report-work",
  281. """
  282. SELECT COUNT(*) FROM mdp_std_s6_report
  283. WHERE tenant_id=@tenantId
  284. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  285. AND (factory_id IS NULL OR factory_id<>@tenantId)
  286. AND IFNULL(source_system,'')<>''
  287. AND IFNULL(work_order_no,'')<>''
  288. AND report_qty IS NOT NULL
  289. """,
  290. """
  291. SELECT work_order_no AS ObjectCode,
  292. CONCAT('报工 ',IFNULL(work_order_no,'')) AS Title,
  293. IFNULL(report_qty,0) AS Contribution,
  294. 'yellow' AS Status,
  295. report_date AS OccurredAt
  296. FROM mdp_std_s6_report
  297. WHERE tenant_id=@tenantId
  298. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  299. AND (factory_id IS NULL OR factory_id<>@tenantId)
  300. AND IFNULL(source_system,'')<>''
  301. AND IFNULL(work_order_no,'')<>''
  302. AND report_qty IS NOT NULL
  303. ORDER BY Contribution DESC, OccurredAt
  304. LIMIT @limit
  305. """,
  306. new[]
  307. {
  308. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order_no"),
  309. }),
  310. new(
  311. "iqc_bill",
  312. SmartDiagnosisEvidenceDomain.Quality,
  313. new[] { "S5" },
  314. "inspection_bill",
  315. "/aidop/s5/iqc",
  316. """
  317. SELECT COUNT(*) FROM qms_qcp_inspbill
  318. WHERE tenant_id=@tenantId AND IFNULL(FBILLNO,'')<>''
  319. """,
  320. """
  321. SELECT FBILLNO AS ObjectCode,
  322. CONCAT('IQC ',IFNULL(FBILLNO,''),' / ',IFNULL(FBILLSTATUS,'')) AS Title,
  323. 1 AS Contribution,
  324. CASE WHEN UPPER(IFNULL(FBILLSTATUS,'')) IN ('NG','REJECT','UNQUALIFIED') THEN 'red' ELSE 'yellow' END AS Status,
  325. NULL AS OccurredAt
  326. FROM qms_qcp_inspbill
  327. WHERE tenant_id=@tenantId AND IFNULL(FBILLNO,'')<>''
  328. ORDER BY id DESC
  329. LIMIT @limit
  330. """,
  331. Array.Empty<SmartDiagnosisEvidenceFilterColumn>()),
  332. new(
  333. "fqc_result",
  334. SmartDiagnosisEvidenceDomain.Quality,
  335. new[] { "S7" },
  336. "inspection_bill",
  337. "/aidop/s7/fqc",
  338. """
  339. SELECT COUNT(*) FROM mdp_std_fqc_result
  340. WHERE tenant_id=@tenantId AND IFNULL(bill_no,'')<>''
  341. """,
  342. """
  343. SELECT bill_no AS ObjectCode,
  344. CONCAT('FQC ',IFNULL(bill_no,''),' / ',IFNULL(material_code,'')) AS Title,
  345. GREATEST(IFNULL(unqualified_qty,0),0) AS Contribution,
  346. CASE WHEN IFNULL(unqualified_qty,0)>0 OR UPPER(IFNULL(judgment,'')) IN ('NG','FAIL','UNQUALIFIED') THEN 'red' ELSE 'green' END AS Status,
  347. inspect_time AS OccurredAt
  348. FROM mdp_std_fqc_result
  349. WHERE tenant_id=@tenantId AND IFNULL(bill_no,'')<>''
  350. ORDER BY Contribution DESC, OccurredAt
  351. LIMIT @limit
  352. """,
  353. new[]
  354. {
  355. new SmartDiagnosisEvidenceFilterColumn("material", "material_code"),
  356. new SmartDiagnosisEvidenceFilterColumn("workOrder", "sap_work_order_no"),
  357. }),
  358. new(
  359. "s2_order_schedule_metric",
  360. SmartDiagnosisEvidenceDomain.Manufacturing,
  361. new[] { "S2" },
  362. "work_order",
  363. "/aidop/s2/production-scheduling/work-order-scheduling",
  364. """
  365. SELECT COUNT(*) FROM dwd_order_schedule_trans
  366. WHERE tenant_id=@tenantId
  367. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  368. AND (factory_id IS NULL OR factory_id<>@tenantId)
  369. AND IFNULL(work_order,'')<>''
  370. AND @metricCode IN ('S2_L1_001','S2_L1_002','S2_L1_003','S2_L1_004','S2_L2_001','S2_L2_002','S2_L2_003')
  371. AND (
  372. (@metricCode IN ('S2_L1_001','S2_L2_001') AND schedule_cycle_days IS NOT NULL)
  373. OR (@metricCode IN ('S2_L1_002','S2_L2_002') AND (IFNULL(schedule_satisfaction_flag,1)=0 OR (due_date IS NOT NULL AND due_date<CURDATE())))
  374. OR (@metricCode IN ('S2_L1_003','S2_L2_003'))
  375. OR (@metricCode='S2_L1_004' AND IFNULL(wip_qty,0)>0)
  376. )
  377. """,
  378. """
  379. SELECT work_order AS ObjectCode,
  380. CONCAT(IFNULL(sales_order_no,''),' / ',IFNULL(work_order,''),' / ',IFNULL(item_code,'')) AS Title,
  381. CASE
  382. WHEN @metricCode IN ('S2_L1_001','S2_L2_001') THEN IFNULL(schedule_cycle_days,0)
  383. WHEN @metricCode='S2_L1_004' THEN GREATEST(IFNULL(wip_qty,0),0)
  384. WHEN @metricCode IN ('S2_L1_003','S2_L2_003') THEN 1
  385. ELSE GREATEST(IFNULL(qty_ordered,0)-IFNULL(qty_completed,0),0)
  386. END AS Contribution,
  387. CASE
  388. WHEN IFNULL(schedule_satisfaction_flag,1)=0 OR (due_date IS NOT NULL AND due_date<CURDATE()) THEN 'red'
  389. WHEN IFNULL(wip_qty,0)>0 THEN 'yellow'
  390. ELSE 'green'
  391. END AS Status,
  392. COALESCE(due_date, stat_date) AS OccurredAt
  393. FROM dwd_order_schedule_trans
  394. WHERE tenant_id=@tenantId
  395. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  396. AND (factory_id IS NULL OR factory_id<>@tenantId)
  397. AND IFNULL(work_order,'')<>''
  398. AND @metricCode IN ('S2_L1_001','S2_L1_002','S2_L1_003','S2_L1_004','S2_L2_001','S2_L2_002','S2_L2_003')
  399. AND (
  400. (@metricCode IN ('S2_L1_001','S2_L2_001') AND schedule_cycle_days IS NOT NULL)
  401. OR (@metricCode IN ('S2_L1_002','S2_L2_002') AND (IFNULL(schedule_satisfaction_flag,1)=0 OR (due_date IS NOT NULL AND due_date<CURDATE())))
  402. OR (@metricCode IN ('S2_L1_003','S2_L2_003'))
  403. OR (@metricCode='S2_L1_004' AND IFNULL(wip_qty,0)>0)
  404. )
  405. ORDER BY Contribution DESC, OccurredAt
  406. LIMIT @limit
  407. """,
  408. new[]
  409. {
  410. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order"),
  411. new SmartDiagnosisEvidenceFilterColumn("orderNo", "sales_order_no"),
  412. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  413. new SmartDiagnosisEvidenceFilterColumn("productionLine", "prod_line"),
  414. })
  415. {
  416. ContributionUnit = "贡献",
  417. DateColumn = "stat_date",
  418. DrillQueryKey = "workOrder",
  419. MetricCodes = new[] { "S2_L1_001", "S2_L1_002", "S2_L1_003", "S2_L1_004", "S2_L2_001", "S2_L2_002", "S2_L2_003" }
  420. },
  421. new(
  422. "s2_operation_schedule_metric",
  423. SmartDiagnosisEvidenceDomain.Manufacturing,
  424. new[] { "S2" },
  425. "operation",
  426. "/aidop/s2/operation-plan/executable-daily-plan",
  427. """
  428. SELECT COUNT(*) FROM mdp_std_operation_schedule
  429. WHERE tenant_id=@tenantId
  430. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  431. AND (factory_id IS NULL OR factory_id<>@tenantId)
  432. AND IFNULL(work_order,'')<>''
  433. AND @metricCode IN ('S2_L3_001','S2_L3_002','S2_L3_003','S2_L3_004','S2_L3_005','S2_L3_006')
  434. AND (
  435. @metricCode IN ('S2_L3_001','S2_L3_002','S2_L3_003')
  436. OR IFNULL(COALESCE(NULLIF(work_center,''), NULLIF(line_code,'')), '')<>''
  437. )
  438. """,
  439. """
  440. SELECT CONCAT(IFNULL(work_order,''),':',IFNULL(op_no,'')) AS ObjectCode,
  441. CONCAT(IFNULL(work_order,''),' / 工序 ',IFNULL(op_no,''),' / ',IFNULL(COALESCE(NULLIF(work_center,''), line_code),'')) AS Title,
  442. CASE
  443. WHEN @metricCode IN ('S2_L3_001','S2_L3_004') THEN COALESCE(
  444. TIMESTAMPDIFF(HOUR, start_time, end_time) / 24,
  445. ABS(TIMESTAMPDIFF(DAY, plan_date, prod_date)),
  446. 0)
  447. ELSE 1
  448. END AS Contribution,
  449. CASE
  450. WHEN plan_date IS NOT NULL AND prod_date IS NOT NULL AND prod_date < plan_date THEN 'red'
  451. WHEN prod_date IS NULL THEN 'yellow'
  452. ELSE 'green'
  453. END AS Status,
  454. COALESCE(prod_date, plan_date, sync_time) AS OccurredAt
  455. FROM mdp_std_operation_schedule
  456. WHERE tenant_id=@tenantId
  457. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  458. AND (factory_id IS NULL OR factory_id<>@tenantId)
  459. AND IFNULL(work_order,'')<>''
  460. AND @metricCode IN ('S2_L3_001','S2_L3_002','S2_L3_003','S2_L3_004','S2_L3_005','S2_L3_006')
  461. AND (
  462. @metricCode IN ('S2_L3_001','S2_L3_002','S2_L3_003')
  463. OR IFNULL(COALESCE(NULLIF(work_center,''), NULLIF(line_code,'')), '')<>''
  464. )
  465. ORDER BY Contribution DESC, OccurredAt
  466. LIMIT @limit
  467. """,
  468. new[]
  469. {
  470. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order"),
  471. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  472. new SmartDiagnosisEvidenceFilterColumn("productionLine", "line_code"),
  473. })
  474. {
  475. ContributionUnit = "贡献",
  476. DateColumn = "plan_date",
  477. DrillQueryKey = "workOrder",
  478. MetricCodes = new[] { "S2_L3_001", "S2_L3_002", "S2_L3_003", "S2_L3_004", "S2_L3_005", "S2_L3_006" }
  479. },
  480. new(
  481. "s3_supplier_delivery_metric",
  482. SmartDiagnosisEvidenceDomain.Supply,
  483. new[] { "S3" },
  484. "purchase_order",
  485. "/aidop/s3/procurement/purchase-order",
  486. """
  487. SELECT COUNT(*) FROM dwd_supplier_delivery
  488. WHERE tenant_id=@tenantId
  489. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  490. AND (factory_id IS NULL OR factory_id<>@tenantId)
  491. AND IFNULL(po_no,'')<>''
  492. AND @metricCode IN ('S3_L1_002','S3_L2_005','S3_L3_005')
  493. AND (IFNULL(remaining_qty,0)>0 OR UPPER(IFNULL(delivery_status,'')) IN ('OVERDUE','DELAYED','LATE'))
  494. """,
  495. """
  496. SELECT po_no AS ObjectCode,
  497. CONCAT(IFNULL(supplier_name,supplier_code),' / ',IFNULL(item_code,''),' / ',IFNULL(po_no,'')) AS Title,
  498. GREATEST(IFNULL(remaining_qty,0),0) AS Contribution,
  499. CASE
  500. WHEN UPPER(IFNULL(risk_level,'')) IN ('HIGH','RED')
  501. OR UPPER(IFNULL(delivery_status,'')) IN ('OVERDUE','DELAYED','LATE') THEN 'red'
  502. WHEN IFNULL(remaining_qty,0)>0 THEN 'yellow'
  503. ELSE 'green'
  504. END AS Status,
  505. COALESCE(due_date, stat_date) AS OccurredAt
  506. FROM dwd_supplier_delivery
  507. WHERE tenant_id=@tenantId
  508. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  509. AND (factory_id IS NULL OR factory_id<>@tenantId)
  510. AND IFNULL(po_no,'')<>''
  511. AND @metricCode IN ('S3_L1_002','S3_L2_005','S3_L3_005')
  512. AND (IFNULL(remaining_qty,0)>0 OR UPPER(IFNULL(delivery_status,'')) IN ('OVERDUE','DELAYED','LATE'))
  513. ORDER BY Contribution DESC, OccurredAt
  514. LIMIT @limit
  515. """,
  516. new[]
  517. {
  518. new SmartDiagnosisEvidenceFilterColumn("poNo", "po_no"),
  519. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  520. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  521. })
  522. {
  523. ContributionUnit = "件",
  524. DateColumn = "stat_date",
  525. DrillQueryKey = "poNo",
  526. MetricCodes = new[] { "S3_L1_002", "S3_L2_005", "S3_L3_005" }
  527. },
  528. new(
  529. "s3_material_readiness_metric",
  530. SmartDiagnosisEvidenceDomain.Supply,
  531. new[] { "S3" },
  532. "work_order",
  533. "/aidop/s3/supply-kanban/work-order-material-readiness",
  534. """
  535. SELECT COUNT(*) FROM dwd_material_readiness
  536. WHERE tenant_id=@tenantId
  537. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  538. AND (factory_id IS NULL OR factory_id<>@tenantId)
  539. AND IFNULL(work_order,'')<>''
  540. AND @metricCode IN ('S3_L3_003','S3_L3_006')
  541. AND (
  542. (@metricCode='S3_L3_003' AND UPPER(IFNULL(ready_status,'')) NOT IN ('READY','SUFFICIENT','OK'))
  543. OR (@metricCode='S3_L3_006' AND IFNULL(shortage_qty,0)>0)
  544. )
  545. """,
  546. """
  547. SELECT work_order AS ObjectCode,
  548. CONCAT(IFNULL(work_order,''),' / ',IFNULL(component_item_code,parent_item_code),' / 缺料 ',IFNULL(shortage_qty,0)) AS Title,
  549. GREATEST(IFNULL(shortage_qty,0),1) AS Contribution,
  550. 'red' AS Status,
  551. COALESCE(need_date, stat_date) AS OccurredAt
  552. FROM dwd_material_readiness
  553. WHERE tenant_id=@tenantId
  554. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  555. AND (factory_id IS NULL OR factory_id<>@tenantId)
  556. AND IFNULL(work_order,'')<>''
  557. AND @metricCode IN ('S3_L3_003','S3_L3_006')
  558. AND (
  559. (@metricCode='S3_L3_003' AND UPPER(IFNULL(ready_status,'')) NOT IN ('READY','SUFFICIENT','OK'))
  560. OR (@metricCode='S3_L3_006' AND IFNULL(shortage_qty,0)>0)
  561. )
  562. ORDER BY Contribution DESC, OccurredAt
  563. LIMIT @limit
  564. """,
  565. new[]
  566. {
  567. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order"),
  568. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  569. new SmartDiagnosisEvidenceFilterColumn("material", "component_item_code"),
  570. })
  571. {
  572. ContributionUnit = "件",
  573. DateColumn = "stat_date",
  574. DrillQueryKey = "workOrder",
  575. MetricCodes = new[] { "S3_L3_003", "S3_L3_006" }
  576. },
  577. new(
  578. "s3_purchase_request_metric",
  579. SmartDiagnosisEvidenceDomain.Supply,
  580. new[] { "S3" },
  581. "purchase_request",
  582. "/aidop/s3/procurement/purchase-request",
  583. """
  584. SELECT COUNT(*) FROM mdp_std_purchase_request
  585. WHERE tenant_id=@tenantId
  586. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  587. AND (factory_id IS NULL OR factory_id<>@tenantId)
  588. AND IFNULL(pr_no,'')<>''
  589. AND @metricCode='S3_L3_001'
  590. """,
  591. """
  592. SELECT pr_no AS ObjectCode,
  593. CONCAT('PR ',IFNULL(pr_no,''),' / ',IFNULL(item_code,'')) AS Title,
  594. GREATEST(IFNULL(request_qty,0),0) AS Contribution,
  595. CASE WHEN send_date IS NULL THEN 'yellow' ELSE 'green' END AS Status,
  596. COALESCE(request_date, sync_time) AS OccurredAt
  597. FROM mdp_std_purchase_request
  598. WHERE tenant_id=@tenantId
  599. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  600. AND (factory_id IS NULL OR factory_id<>@tenantId)
  601. AND IFNULL(pr_no,'')<>''
  602. AND @metricCode='S3_L3_001'
  603. ORDER BY Contribution DESC, OccurredAt
  604. LIMIT @limit
  605. """,
  606. new[]
  607. {
  608. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  609. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  610. })
  611. {
  612. ContributionUnit = "件",
  613. DateColumn = "request_date",
  614. DrillQueryKey = "prNo",
  615. MetricCodes = new[] { "S3_L3_001" }
  616. },
  617. new(
  618. "s3_purchase_order_metric",
  619. SmartDiagnosisEvidenceDomain.Supply,
  620. new[] { "S3" },
  621. "purchase_order",
  622. "/aidop/s3/procurement/purchase-order",
  623. """
  624. SELECT COUNT(*) FROM mdp_std_purchase_order
  625. WHERE tenant_id=@tenantId
  626. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  627. AND (factory_id IS NULL OR factory_id<>@tenantId)
  628. AND IFNULL(po_no,'')<>''
  629. AND @metricCode='S3_L3_002'
  630. """,
  631. """
  632. SELECT po_no AS ObjectCode,
  633. CONCAT('PO ',IFNULL(po_no,''),' / ',IFNULL(item_code,'')) AS Title,
  634. GREATEST(IFNULL(order_qty,0),0) AS Contribution,
  635. CASE WHEN due_date IS NOT NULL AND due_date<CURDATE() AND IFNULL(received_qty,0)<IFNULL(order_qty,0) THEN 'red' ELSE 'yellow' END AS Status,
  636. COALESCE(order_date, due_date, sync_time) AS OccurredAt
  637. FROM mdp_std_purchase_order
  638. WHERE tenant_id=@tenantId
  639. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  640. AND (factory_id IS NULL OR factory_id<>@tenantId)
  641. AND IFNULL(po_no,'')<>''
  642. AND @metricCode='S3_L3_002'
  643. ORDER BY Contribution DESC, OccurredAt
  644. LIMIT @limit
  645. """,
  646. new[]
  647. {
  648. new SmartDiagnosisEvidenceFilterColumn("poNo", "po_no"),
  649. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  650. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  651. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order"),
  652. })
  653. {
  654. ContributionUnit = "件",
  655. DateColumn = "order_date",
  656. DrillQueryKey = "poNo",
  657. MetricCodes = new[] { "S3_L3_002" }
  658. },
  659. new(
  660. "s3_delivery_schedule_metric",
  661. SmartDiagnosisEvidenceDomain.Supply,
  662. new[] { "S3" },
  663. "delivery_schedule",
  664. "/aidop/s3/material-plan/delivery-schedule",
  665. """
  666. SELECT COUNT(*) FROM mdp_std_delivery_schedule
  667. WHERE tenant_id=@tenantId
  668. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  669. AND (factory_id IS NULL OR factory_id<>@tenantId)
  670. AND IFNULL(delivery_plan_no,'')<>''
  671. AND @metricCode IN ('S3_L1_001','S3_L2_004','S3_L3_004')
  672. """,
  673. """
  674. SELECT delivery_plan_no AS ObjectCode,
  675. CONCAT(IFNULL(delivery_plan_no,''),' / ',IFNULL(po_no,''),' / ',IFNULL(item_code,'')) AS Title,
  676. CASE
  677. WHEN @metricCode='S3_L3_004' THEN GREATEST(IFNULL(rest_qty,0),1)
  678. ELSE GREATEST(IFNULL(DATEDIFF(IFNULL(last_sent_date,need_date), request_date),0),0)
  679. END AS Contribution,
  680. CASE
  681. WHEN IFNULL(rest_qty,0)>0 AND need_date IS NOT NULL AND need_date<CURDATE() THEN 'red'
  682. WHEN IFNULL(rest_qty,0)>0 THEN 'yellow'
  683. ELSE 'green'
  684. END AS Status,
  685. COALESCE(need_date, request_date, sync_time) AS OccurredAt
  686. FROM mdp_std_delivery_schedule
  687. WHERE tenant_id=@tenantId
  688. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  689. AND (factory_id IS NULL OR factory_id<>@tenantId)
  690. AND IFNULL(delivery_plan_no,'')<>''
  691. AND @metricCode IN ('S3_L1_001','S3_L2_004','S3_L3_004')
  692. ORDER BY Contribution DESC, OccurredAt
  693. LIMIT @limit
  694. """,
  695. new[]
  696. {
  697. new SmartDiagnosisEvidenceFilterColumn("poNo", "po_no"),
  698. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  699. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  700. })
  701. {
  702. ContributionUnit = "贡献",
  703. DateColumn = "need_date",
  704. DrillQueryKey = "planNo",
  705. MetricCodes = new[] { "S3_L1_001", "S3_L2_004", "S3_L3_004" }
  706. },
  707. new(
  708. "s4_supplier_delivery_metric",
  709. SmartDiagnosisEvidenceDomain.Supply,
  710. new[] { "S4" },
  711. "purchase_order",
  712. "/aidop/s4/delivery/supplier-delivery-management",
  713. """
  714. SELECT COUNT(*) FROM dwd_supplier_delivery
  715. WHERE tenant_id=@tenantId
  716. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  717. AND (factory_id IS NULL OR factory_id<>@tenantId)
  718. AND IFNULL(po_no,'')<>''
  719. AND @metricCode IN ('S4_L1_002','S4_L2_002','S4_L3_002','S4_L1_004')
  720. AND IFNULL(remaining_qty,0)>0
  721. """,
  722. """
  723. SELECT po_no AS ObjectCode,
  724. CONCAT(IFNULL(supplier_name,supplier_code),' / ',IFNULL(item_code,''),' / ',IFNULL(po_no,'')) AS Title,
  725. GREATEST(IFNULL(remaining_qty,0),0) AS Contribution,
  726. CASE
  727. WHEN UPPER(IFNULL(risk_level,'')) IN ('HIGH','RED')
  728. OR UPPER(IFNULL(delivery_status,'')) IN ('OVERDUE','DELAYED','LATE') THEN 'red'
  729. ELSE 'yellow'
  730. END AS Status,
  731. COALESCE(due_date, stat_date) AS OccurredAt
  732. FROM dwd_supplier_delivery
  733. WHERE tenant_id=@tenantId
  734. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  735. AND (factory_id IS NULL OR factory_id<>@tenantId)
  736. AND IFNULL(po_no,'')<>''
  737. AND @metricCode IN ('S4_L1_002','S4_L2_002','S4_L3_002','S4_L1_004')
  738. AND IFNULL(remaining_qty,0)>0
  739. ORDER BY Contribution DESC, OccurredAt
  740. LIMIT @limit
  741. """,
  742. new[]
  743. {
  744. new SmartDiagnosisEvidenceFilterColumn("poNo", "po_no"),
  745. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  746. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  747. })
  748. {
  749. ContributionUnit = "件",
  750. DateColumn = "stat_date",
  751. DrillQueryKey = "poNo",
  752. MetricCodes = new[] { "S4_L1_002", "S4_L2_002", "S4_L3_002", "S4_L1_004" }
  753. },
  754. new(
  755. "s4_delivery_cycle_metric",
  756. SmartDiagnosisEvidenceDomain.Supply,
  757. new[] { "S4" },
  758. "delivery_schedule",
  759. "/aidop/s4/delivery/supplier-shipment",
  760. """
  761. SELECT COUNT(*) FROM mdp_std_delivery_schedule
  762. WHERE tenant_id=@tenantId
  763. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  764. AND (factory_id IS NULL OR factory_id<>@tenantId)
  765. AND IFNULL(delivery_plan_no,'')<>''
  766. AND @metricCode IN ('S4_L1_001','S4_L2_001','S4_L3_001')
  767. """,
  768. """
  769. SELECT delivery_plan_no AS ObjectCode,
  770. CONCAT(IFNULL(delivery_plan_no,''),' / ',IFNULL(po_no,''),' / ',IFNULL(item_code,'')) AS Title,
  771. GREATEST(IFNULL(DATEDIFF(IFNULL(last_sent_date,need_date), request_date),0),0) AS Contribution,
  772. CASE
  773. WHEN need_date IS NOT NULL AND last_sent_date IS NOT NULL AND last_sent_date>need_date THEN 'red'
  774. WHEN last_sent_date IS NULL THEN 'yellow'
  775. ELSE 'green'
  776. END AS Status,
  777. COALESCE(last_sent_date, need_date, sync_time) AS OccurredAt
  778. FROM mdp_std_delivery_schedule
  779. WHERE tenant_id=@tenantId
  780. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  781. AND (factory_id IS NULL OR factory_id<>@tenantId)
  782. AND IFNULL(delivery_plan_no,'')<>''
  783. AND @metricCode IN ('S4_L1_001','S4_L2_001','S4_L3_001')
  784. ORDER BY Contribution DESC, OccurredAt
  785. LIMIT @limit
  786. """,
  787. new[]
  788. {
  789. new SmartDiagnosisEvidenceFilterColumn("poNo", "po_no"),
  790. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  791. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  792. })
  793. {
  794. ContributionUnit = "天",
  795. DateColumn = "need_date",
  796. DrillQueryKey = "planNo",
  797. MetricCodes = new[] { "S4_L1_001", "S4_L2_001", "S4_L3_001" }
  798. },
  799. new(
  800. "s4_purchase_execution_metric",
  801. SmartDiagnosisEvidenceDomain.Supply,
  802. new[] { "S4" },
  803. "purchase_order",
  804. "/aidop/s4/execution-kanban/supplier-shortage-kanban",
  805. """
  806. SELECT COUNT(*) FROM dwd_s4_purchase_execution
  807. WHERE tenant_id=@tenantId
  808. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  809. AND (factory_id IS NULL OR factory_id<>@tenantId)
  810. AND IFNULL(po_no,'')<>''
  811. AND @metricCode IN ('S4_L2_003','S4_L3_003','S4_L2_004','S4_L3_004')
  812. """,
  813. """
  814. SELECT po_no AS ObjectCode,
  815. CONCAT(IFNULL(supplier_code,''),' / ',IFNULL(item_code,''),' / ',IFNULL(po_no,'')) AS Title,
  816. CASE
  817. WHEN @metricCode IN ('S4_L2_004','S4_L3_004') THEN GREATEST(IFNULL(shortage_qty,0), GREATEST(IFNULL(order_qty,0)-IFNULL(received_qty,0),0))
  818. ELSE 1
  819. END AS Contribution,
  820. CASE
  821. WHEN UPPER(IFNULL(risk_level,'')) IN ('HIGH','RED') THEN 'red'
  822. WHEN IFNULL(shortage_qty,0)>0 THEN 'yellow'
  823. ELSE 'green'
  824. END AS Status,
  825. COALESCE(due_date, actual_arrival_date, stat_date) AS OccurredAt
  826. FROM dwd_s4_purchase_execution
  827. WHERE tenant_id=@tenantId
  828. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  829. AND (factory_id IS NULL OR factory_id<>@tenantId)
  830. AND IFNULL(po_no,'')<>''
  831. AND @metricCode IN ('S4_L2_003','S4_L3_003','S4_L2_004','S4_L3_004')
  832. ORDER BY Contribution DESC, OccurredAt
  833. LIMIT @limit
  834. """,
  835. new[]
  836. {
  837. new SmartDiagnosisEvidenceFilterColumn("poNo", "po_no"),
  838. new SmartDiagnosisEvidenceFilterColumn("supplier", "supplier_code"),
  839. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  840. })
  841. {
  842. ContributionUnit = "贡献",
  843. DateColumn = "stat_date",
  844. DrillQueryKey = "poNo",
  845. MetricCodes = new[] { "S4_L2_003", "S4_L3_003", "S4_L2_004", "S4_L3_004" }
  846. },
  847. new(
  848. "s5_material_online_cycle_metric",
  849. SmartDiagnosisEvidenceDomain.Supply,
  850. new[] { "S5" },
  851. "material",
  852. "/aidop/s5/inventory/inout-query",
  853. """
  854. SELECT COUNT(*) FROM dwd_material_online_cycle
  855. WHERE tenant_id=@tenantId
  856. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  857. AND (factory_id IS NULL OR factory_id<>@tenantId)
  858. AND IFNULL(item_code,'')<>''
  859. AND @metricCode='S5_L1_001'
  860. AND cycle_days IS NOT NULL
  861. """,
  862. """
  863. SELECT item_code AS ObjectCode,
  864. CONCAT('物料上线周期 ',IFNULL(item_code,''),' / ',IFNULL(cycle_days,0),'天') AS Title,
  865. IFNULL(cycle_days,0) AS Contribution,
  866. CASE WHEN IFNULL(cycle_days,0)>7 THEN 'red' WHEN IFNULL(cycle_days,0)>3 THEN 'yellow' ELSE 'green' END AS Status,
  867. biz_date AS OccurredAt
  868. FROM dwd_material_online_cycle
  869. WHERE tenant_id=@tenantId
  870. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  871. AND (factory_id IS NULL OR factory_id<>@tenantId)
  872. AND IFNULL(item_code,'')<>''
  873. AND @metricCode='S5_L1_001'
  874. AND cycle_days IS NOT NULL
  875. ORDER BY Contribution DESC, OccurredAt
  876. LIMIT @limit
  877. """,
  878. new[]
  879. {
  880. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  881. })
  882. {
  883. ContributionUnit = "天",
  884. DateColumn = "biz_date",
  885. DrillQueryKey = "material",
  886. MetricCodes = new[] { "S5_L1_001" }
  887. },
  888. new(
  889. "s5_material_online_fulfillment_metric",
  890. SmartDiagnosisEvidenceDomain.Supply,
  891. new[] { "S5" },
  892. "work_order",
  893. "/aidop/s5/warehouse/production-issue",
  894. """
  895. SELECT COUNT(*) FROM dwd_material_online_fulfillment
  896. WHERE tenant_id=@tenantId
  897. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  898. AND (factory_id IS NULL OR factory_id<>@tenantId)
  899. AND IFNULL(work_order_no,'')<>''
  900. AND @metricCode='S5_L1_002'
  901. """,
  902. """
  903. SELECT work_order_no AS ObjectCode,
  904. CONCAT('工单 ',IFNULL(work_order_no,''),' / 上线 ',IFNULL(before_kgdate_rows,0),'/',IFNULL(total_rows,0)) AS Title,
  905. GREATEST(IFNULL(total_rows,0)-IFNULL(before_kgdate_rows,0),0) AS Contribution,
  906. CASE WHEN IFNULL(fulfillment_rate,1)<1 THEN 'red' ELSE 'green' END AS Status,
  907. biz_date AS OccurredAt
  908. FROM dwd_material_online_fulfillment
  909. WHERE tenant_id=@tenantId
  910. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  911. AND (factory_id IS NULL OR factory_id<>@tenantId)
  912. AND IFNULL(work_order_no,'')<>''
  913. AND @metricCode='S5_L1_002'
  914. ORDER BY Contribution DESC, OccurredAt
  915. LIMIT @limit
  916. """,
  917. new[]
  918. {
  919. new SmartDiagnosisEvidenceFilterColumn("workOrder", "work_order_no"),
  920. })
  921. {
  922. ContributionUnit = "行",
  923. DateColumn = "biz_date",
  924. DrillQueryKey = "workOrder",
  925. MetricCodes = new[] { "S5_L1_002" }
  926. },
  927. new(
  928. "s5_iqc_bill_metric",
  929. SmartDiagnosisEvidenceDomain.Quality,
  930. new[] { "S5" },
  931. "inspection_bill",
  932. "/aidop/s5/iqc/result-list",
  933. """
  934. SELECT COUNT(*) FROM qms_qcp_inspbill
  935. WHERE tenant_id=@tenantId AND IFNULL(FBILLNO,'')<>''
  936. AND @metricCode='S5_L2_004'
  937. """,
  938. """
  939. SELECT FBILLNO AS ObjectCode,
  940. CONCAT('IQC ',IFNULL(FBILLNO,''),' / ',IFNULL(FBILLSTATUS,'')) AS Title,
  941. 1 AS Contribution,
  942. CASE WHEN UPPER(IFNULL(FBILLSTATUS,'')) IN ('NG','REJECT','UNQUALIFIED') THEN 'red' ELSE 'yellow' END AS Status,
  943. NULL AS OccurredAt
  944. FROM qms_qcp_inspbill
  945. WHERE tenant_id=@tenantId AND IFNULL(FBILLNO,'')<>''
  946. AND @metricCode='S5_L2_004'
  947. ORDER BY id DESC
  948. LIMIT @limit
  949. """,
  950. Array.Empty<SmartDiagnosisEvidenceFilterColumn>())
  951. {
  952. ContributionUnit = "单",
  953. DrillQueryKey = "billNo",
  954. MetricCodes = new[] { "S5_L2_004" }
  955. },
  956. new(
  957. "s6_work_order_fulfillment_metric",
  958. SmartDiagnosisEvidenceDomain.Manufacturing,
  959. new[] { "S6" },
  960. "work_order",
  961. "/aidop/s6/production-record/order-list",
  962. """
  963. SELECT COUNT(*) FROM dwd_work_order_mfg_fulfillment
  964. WHERE tenant_id=@tenantId
  965. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  966. AND (factory_id IS NULL OR factory_id<>@tenantId)
  967. AND IFNULL(order_no,'')<>''
  968. AND @metricCode IN ('S6_L1_002','S6_L2_002')
  969. """,
  970. """
  971. SELECT COALESCE(NULLIF(task_no,''), order_no) AS ObjectCode,
  972. CONCAT(IFNULL(order_no,''),' / ',IFNULL(task_no,''),' / ',IFNULL(item_code,'')) AS Title,
  973. GREATEST(IFNULL(plan_qty,0)-IFNULL(done_qty_in_window,0),0) AS Contribution,
  974. CASE WHEN IFNULL(fulfillment_rate,1)<1 THEN 'red' ELSE 'green' END AS Status,
  975. biz_date AS OccurredAt
  976. FROM dwd_work_order_mfg_fulfillment
  977. WHERE tenant_id=@tenantId
  978. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  979. AND (factory_id IS NULL OR factory_id<>@tenantId)
  980. AND IFNULL(order_no,'')<>''
  981. AND @metricCode IN ('S6_L1_002','S6_L2_002')
  982. ORDER BY Contribution DESC, OccurredAt
  983. LIMIT @limit
  984. """,
  985. new[]
  986. {
  987. new SmartDiagnosisEvidenceFilterColumn("orderNo", "order_no"),
  988. new SmartDiagnosisEvidenceFilterColumn("workOrder", "task_no"),
  989. new SmartDiagnosisEvidenceFilterColumn("material", "item_code"),
  990. })
  991. {
  992. ContributionUnit = "件",
  993. DateColumn = "biz_date",
  994. DrillQueryKey = "orderNo",
  995. MetricCodes = new[] { "S6_L1_002", "S6_L2_002" }
  996. },
  997. new(
  998. "s7_shipment_cycle_metric",
  999. SmartDiagnosisEvidenceDomain.Delivery,
  1000. new[] { "S7" },
  1001. "sales_order",
  1002. "/aidop/s7/finished-outbound/sales-shipment-notice",
  1003. """
  1004. SELECT COUNT(*) FROM dwd_order_shipment_cycle
  1005. WHERE tenant_id=@tenantId
  1006. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  1007. AND (factory_id IS NULL OR factory_id<>@tenantId)
  1008. AND IFNULL(order_no,'')<>''
  1009. AND @metricCode='S7_L1_001'
  1010. AND cycle_days IS NOT NULL
  1011. """,
  1012. """
  1013. SELECT order_no AS ObjectCode,
  1014. CONCAT('发货周期 ',IFNULL(order_no,''),' / ',IFNULL(cycle_days,0),'天') AS Title,
  1015. IFNULL(cycle_days,0) AS Contribution,
  1016. CASE WHEN IFNULL(cycle_days,0)>7 THEN 'red' WHEN IFNULL(cycle_days,0)>3 THEN 'yellow' ELSE 'green' END AS Status,
  1017. biz_date AS OccurredAt
  1018. FROM dwd_order_shipment_cycle
  1019. WHERE tenant_id=@tenantId
  1020. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  1021. AND (factory_id IS NULL OR factory_id<>@tenantId)
  1022. AND IFNULL(order_no,'')<>''
  1023. AND @metricCode='S7_L1_001'
  1024. AND cycle_days IS NOT NULL
  1025. ORDER BY Contribution DESC, OccurredAt
  1026. LIMIT @limit
  1027. """,
  1028. new[]
  1029. {
  1030. new SmartDiagnosisEvidenceFilterColumn("orderNo", "order_no"),
  1031. })
  1032. {
  1033. ContributionUnit = "天",
  1034. DateColumn = "biz_date",
  1035. DrillQueryKey = "orderNo",
  1036. MetricCodes = new[] { "S7_L1_001" }
  1037. },
  1038. new(
  1039. "s7_shipment_fulfillment_metric",
  1040. SmartDiagnosisEvidenceDomain.Delivery,
  1041. new[] { "S7" },
  1042. "sales_order",
  1043. "/aidop/s7/finished-outbound/sales-shipment-notice",
  1044. """
  1045. SELECT COUNT(*) FROM dwd_order_shipment_fulfillment
  1046. WHERE tenant_id=@tenantId
  1047. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  1048. AND (factory_id IS NULL OR factory_id<>@tenantId)
  1049. AND IFNULL(order_no,'')<>''
  1050. AND @metricCode='S7_L1_002'
  1051. """,
  1052. """
  1053. SELECT order_no AS ObjectCode,
  1054. CONCAT('发货满足 ',IFNULL(order_no,''),' / ',IFNULL(in_window_rows,0),'/',IFNULL(total_rows,0)) AS Title,
  1055. GREATEST(IFNULL(total_rows,0)-IFNULL(in_window_rows,0),0) AS Contribution,
  1056. CASE WHEN IFNULL(fulfillment_rate,100)<100 THEN 'red' ELSE 'green' END AS Status,
  1057. biz_date AS OccurredAt
  1058. FROM dwd_order_shipment_fulfillment
  1059. WHERE tenant_id=@tenantId
  1060. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId)
  1061. AND (factory_id IS NULL OR factory_id<>@tenantId)
  1062. AND IFNULL(order_no,'')<>''
  1063. AND @metricCode='S7_L1_002'
  1064. ORDER BY Contribution DESC, OccurredAt
  1065. LIMIT @limit
  1066. """,
  1067. new[]
  1068. {
  1069. new SmartDiagnosisEvidenceFilterColumn("orderNo", "order_no"),
  1070. })
  1071. {
  1072. ContributionUnit = "行",
  1073. DateColumn = "biz_date",
  1074. DrillQueryKey = "orderNo",
  1075. MetricCodes = new[] { "S7_L1_002" }
  1076. },
  1077. new(
  1078. "s7_fqc_result_metric",
  1079. SmartDiagnosisEvidenceDomain.Quality,
  1080. new[] { "S7" },
  1081. "inspection_bill",
  1082. "/aidop/s7/fqc/result-list",
  1083. """
  1084. SELECT COUNT(*) FROM mdp_std_fqc_result
  1085. WHERE tenant_id=@tenantId AND IFNULL(bill_no,'')<>''
  1086. AND @metricCode='S7_L2_002'
  1087. """,
  1088. """
  1089. SELECT bill_no AS ObjectCode,
  1090. CONCAT('FQC ',IFNULL(bill_no,''),' / ',IFNULL(material_code,'')) AS Title,
  1091. GREATEST(IFNULL(unqualified_qty,0),0) AS Contribution,
  1092. CASE WHEN IFNULL(unqualified_qty,0)>0 OR UPPER(IFNULL(judgment,'')) IN ('NG','FAIL','UNQUALIFIED') THEN 'red' ELSE 'green' END AS Status,
  1093. inspect_time AS OccurredAt
  1094. FROM mdp_std_fqc_result
  1095. WHERE tenant_id=@tenantId AND IFNULL(bill_no,'')<>''
  1096. AND @metricCode='S7_L2_002'
  1097. ORDER BY Contribution DESC, OccurredAt
  1098. LIMIT @limit
  1099. """,
  1100. new[]
  1101. {
  1102. new SmartDiagnosisEvidenceFilterColumn("material", "material_code"),
  1103. new SmartDiagnosisEvidenceFilterColumn("workOrder", "sap_work_order_no"),
  1104. })
  1105. {
  1106. ContributionUnit = "件",
  1107. DateColumn = "inspect_time",
  1108. DrillQueryKey = "billNo",
  1109. MetricCodes = new[] { "S7_L2_002" }
  1110. },
  1111. new(
  1112. "s9_quality_return_txn_metric",
  1113. SmartDiagnosisEvidenceDomain.Quality,
  1114. new[] { "S9" },
  1115. "sales_return",
  1116. "/aidop/s7/finished-outbound/sales-shipment-notice",
  1117. """
  1118. SELECT COUNT(*)
  1119. FROM mdp_std_inv_trans
  1120. WHERE tenant_id=@tenantId
  1121. AND summary_flag=0 AND void_flag=0 AND approved_flag=1
  1122. AND biz_doc_type='SALES_RETURN'
  1123. AND @metricCode='S9_L1_001'
  1124. """,
  1125. """
  1126. SELECT COALESCE(NULLIF(ref_task_no,''), item_num, src_rec_id) AS ObjectCode,
  1127. CONCAT('退货 ',IFNULL(ref_task_no,src_rec_id),' / ',IFNULL(item_num,'')) AS Title,
  1128. ABS(IFNULL(qty_change,0)) AS Contribution,
  1129. 'red' AS Status,
  1130. approved_time AS OccurredAt
  1131. FROM mdp_std_inv_trans
  1132. WHERE tenant_id=@tenantId
  1133. AND summary_flag=0 AND void_flag=0 AND approved_flag=1
  1134. AND biz_doc_type='SALES_RETURN'
  1135. AND @metricCode='S9_L1_001'
  1136. ORDER BY Contribution DESC, OccurredAt
  1137. LIMIT @limit
  1138. """,
  1139. Array.Empty<SmartDiagnosisEvidenceFilterColumn>())
  1140. {
  1141. ContributionUnit = "件",
  1142. DateColumn = "approved_time",
  1143. DrillQueryKey = "orderNo",
  1144. MetricCodes = new[] { "S9_L1_001" }
  1145. },
  1146. new(
  1147. "s9_order_delivery_cycle_metric",
  1148. SmartDiagnosisEvidenceDomain.Delivery,
  1149. new[] { "S9" },
  1150. "segment_cycle",
  1151. "/aidop/smart-ops/grid",
  1152. """
  1153. SELECT COUNT(*)
  1154. FROM ado_s9_kpi_value_l1_day
  1155. WHERE tenant_id=@tenantId AND is_deleted=0 AND metric_value IS NOT NULL
  1156. AND metric_code IN ('S1_L1_001','S2_L1_001','S3_L1_001','S5_L1_001','S6_L1_001','S7_L1_001')
  1157. AND @metricCode='S9_L1_002'
  1158. """,
  1159. """
  1160. SELECT metric_code AS ObjectCode,
  1161. metric_code AS Title,
  1162. metric_value AS Contribution,
  1163. 'blue' AS Status,
  1164. biz_date AS OccurredAt
  1165. FROM ado_s9_kpi_value_l1_day
  1166. WHERE tenant_id=@tenantId AND is_deleted=0 AND metric_value IS NOT NULL
  1167. AND metric_code IN ('S1_L1_001','S2_L1_001','S3_L1_001','S5_L1_001','S6_L1_001','S7_L1_001')
  1168. AND @metricCode='S9_L1_002'
  1169. ORDER BY metric_code
  1170. LIMIT @limit
  1171. """,
  1172. Array.Empty<SmartDiagnosisEvidenceFilterColumn>())
  1173. {
  1174. ContributionUnit = "天",
  1175. DateColumn = "biz_date",
  1176. DrillQueryKey = "metricCode",
  1177. MetricCodes = new[] { "S9_L1_002" }
  1178. },
  1179. new(
  1180. "s9_order_delivery_fulfillment_metric",
  1181. SmartDiagnosisEvidenceDomain.Delivery,
  1182. new[] { "S9" },
  1183. "sales_order_line",
  1184. "/aidop/smart-ops/grid",
  1185. """
  1186. SELECT COUNT(*)
  1187. FROM mdp_std_so
  1188. WHERE tenant_id=@tenantId AND deleted_flag=0
  1189. AND IFNULL(order_qty,0) > 0
  1190. AND IFNULL(delivered_qty,0) >= order_qty
  1191. AND @metricCode='S9_L1_003'
  1192. """,
  1193. """
  1194. SELECT CONCAT(order_no, ':', IFNULL(order_line,'')) AS ObjectCode,
  1195. CONCAT(order_no, ' / ', IFNULL(item_code,'')) AS Title,
  1196. delivered_qty AS Contribution,
  1197. 'blue' AS Status,
  1198. order_date AS OccurredAt
  1199. FROM mdp_std_so
  1200. WHERE tenant_id=@tenantId AND deleted_flag=0
  1201. AND IFNULL(order_qty,0) > 0
  1202. AND IFNULL(delivered_qty,0) >= order_qty
  1203. AND @metricCode='S9_L1_003'
  1204. ORDER BY order_date DESC
  1205. LIMIT @limit
  1206. """,
  1207. Array.Empty<SmartDiagnosisEvidenceFilterColumn>())
  1208. {
  1209. ContributionUnit = "件",
  1210. DateColumn = "order_date",
  1211. DrillQueryKey = "orderNo",
  1212. MetricCodes = new[] { "S9_L1_003" }
  1213. },
  1214. new(
  1215. "s9_production_efficiency_metric",
  1216. SmartDiagnosisEvidenceDomain.Manufacturing,
  1217. new[] { "S9" },
  1218. "line_status",
  1219. "/aidop/smart-ops/grid",
  1220. """
  1221. SELECT COUNT(*)
  1222. FROM mdp_stg_line_status
  1223. WHERE tenant_id=@tenantId
  1224. AND (JSON_EXTRACT(raw_data,'$.RestTime') IS NOT NULL
  1225. OR JSON_EXTRACT(raw_data,'$.ProdDownTime') IS NOT NULL)
  1226. AND @metricCode='S9_L1_004'
  1227. """,
  1228. """
  1229. SELECT source_row_id AS ObjectCode,
  1230. source_biz_key AS Title,
  1231. CAST(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.ProdTime')) AS DECIMAL(18,4)) AS Contribution,
  1232. 'blue' AS Status,
  1233. sync_time AS OccurredAt
  1234. FROM mdp_stg_line_status
  1235. WHERE tenant_id=@tenantId
  1236. AND (JSON_EXTRACT(raw_data,'$.RestTime') IS NOT NULL
  1237. OR JSON_EXTRACT(raw_data,'$.ProdDownTime') IS NOT NULL)
  1238. AND @metricCode='S9_L1_004'
  1239. ORDER BY sync_time DESC
  1240. LIMIT @limit
  1241. """,
  1242. Array.Empty<SmartDiagnosisEvidenceFilterColumn>())
  1243. {
  1244. ContributionUnit = "小时",
  1245. DateColumn = "sync_time",
  1246. DrillQueryKey = "sourceRowId",
  1247. MetricCodes = new[] { "S9_L1_004" }
  1248. },
  1249. new(
  1250. "s9_inventory_turnover_metric",
  1251. SmartDiagnosisEvidenceDomain.Supply,
  1252. new[] { "S9" },
  1253. "turnover_segment",
  1254. "/aidop/smart-ops/grid",
  1255. """
  1256. SELECT COUNT(*)
  1257. FROM ado_s9_kpi_value_l1_day
  1258. WHERE tenant_id=@tenantId AND is_deleted=0 AND metric_value IS NOT NULL
  1259. AND metric_code IN ('S1_L1_004','S2_L1_004','S3_L1_004')
  1260. AND @metricCode='S9_L1_005'
  1261. """,
  1262. """
  1263. SELECT metric_code AS ObjectCode,
  1264. metric_code AS Title,
  1265. metric_value AS Contribution,
  1266. 'blue' AS Status,
  1267. biz_date AS OccurredAt
  1268. FROM ado_s9_kpi_value_l1_day
  1269. WHERE tenant_id=@tenantId AND is_deleted=0 AND metric_value IS NOT NULL
  1270. AND metric_code IN ('S1_L1_004','S2_L1_004','S3_L1_004')
  1271. AND @metricCode='S9_L1_005'
  1272. ORDER BY metric_code
  1273. LIMIT @limit
  1274. """,
  1275. Array.Empty<SmartDiagnosisEvidenceFilterColumn>())
  1276. {
  1277. ContributionUnit = "天",
  1278. DateColumn = "biz_date",
  1279. DrillQueryKey = "metricCode",
  1280. MetricCodes = new[] { "S9_L1_005" }
  1281. },
  1282. new(
  1283. "s8_exception",
  1284. SmartDiagnosisEvidenceDomain.Exception,
  1285. new[] { "S8" },
  1286. "s8_exception",
  1287. "/aidop/s8/exceptions",
  1288. """
  1289. SELECT COUNT(*) FROM ado_s8_exception
  1290. WHERE tenant_id=@tenantId AND IFNULL(is_deleted,0)=0
  1291. AND IFNULL(exception_code,'')<>''
  1292. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId
  1293. OR (@factoryId IN (0,1) AND factory_id<>@tenantId))
  1294. """,
  1295. """
  1296. SELECT exception_code AS ObjectCode,
  1297. CONCAT(IFNULL(exception_code,''),' / ',IFNULL(title,'')) AS Title,
  1298. GREATEST(IFNULL(priority_score,0),0) AS Contribution,
  1299. CASE
  1300. WHEN UPPER(IFNULL(status,'')) IN ('CLOSED','CANCELLED','CANCELED') THEN 'green'
  1301. WHEN UPPER(IFNULL(severity,'')) IN ('SERIOUS','CRITICAL','HIGH') THEN 'red'
  1302. ELSE 'yellow'
  1303. END AS Status,
  1304. created_at AS OccurredAt
  1305. FROM ado_s8_exception
  1306. WHERE tenant_id=@tenantId AND IFNULL(is_deleted,0)=0
  1307. AND IFNULL(exception_code,'')<>''
  1308. AND (factory_id IS NULL OR factory_id=0 OR factory_id=1 OR factory_id=@factoryId
  1309. OR (@factoryId IN (0,1) AND factory_id<>@tenantId))
  1310. ORDER BY Contribution DESC, OccurredAt
  1311. LIMIT @limit
  1312. """,
  1313. new[]
  1314. {
  1315. new SmartDiagnosisEvidenceFilterColumn("orderNo", "related_object_code"),
  1316. }),
  1317. };
  1318. public static IReadOnlyList<SmartDiagnosisEvidenceSource> All => Sources;
  1319. public static IReadOnlyList<SmartDiagnosisEvidenceSource> Resolve(string moduleCode)
  1320. {
  1321. var mc = (moduleCode ?? "").Trim().ToUpperInvariant();
  1322. if (mc == "S9")
  1323. return Sources.Where(x => x.Key != "s8_exception" && x.MetricCodes.Count == 0).ToList();
  1324. return Sources
  1325. .Where(x => x.MetricCodes.Count == 0
  1326. && x.Modules.Contains(mc, StringComparer.OrdinalIgnoreCase))
  1327. .ToList();
  1328. }
  1329. public static IReadOnlyList<SmartDiagnosisEvidenceSource> ResolveMetric(
  1330. string moduleCode,
  1331. string metricCode)
  1332. {
  1333. var mc = (moduleCode ?? "").Trim().ToUpperInvariant();
  1334. var metric = (metricCode ?? "").Trim().ToUpperInvariant();
  1335. if (mc.Length == 0 || metric.Length == 0)
  1336. return Array.Empty<SmartDiagnosisEvidenceSource>();
  1337. return Sources
  1338. .Where(x => x.Modules.Contains(mc, StringComparer.OrdinalIgnoreCase)
  1339. && x.MetricCodes.Contains(metric, StringComparer.OrdinalIgnoreCase))
  1340. .ToList();
  1341. }
  1342. public static SmartDiagnosisEvidenceSource? Get(string key) =>
  1343. Sources.FirstOrDefault(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase));
  1344. }
  1345. public sealed class SmartDiagnosisEvidenceItem
  1346. {
  1347. public string ObjectType { get; set; } = "";
  1348. public string ObjectCode { get; set; } = "";
  1349. public string Title { get; set; } = "";
  1350. public decimal? Contribution { get; set; }
  1351. public string ContributionUnit { get; set; } = "";
  1352. public string Status { get; set; } = "green";
  1353. public string? OccurredAt { get; set; }
  1354. public string? DrillPath { get; set; }
  1355. }
  1356. public sealed class SmartDiagnosisEvidenceResult
  1357. {
  1358. public string Scope { get; set; } = "no_data";
  1359. public string? MetricCode { get; set; }
  1360. public string MatchScope { get; set; } = "module";
  1361. public string? AsOf { get; set; }
  1362. public string Domain { get; set; } = "";
  1363. public int Total { get; set; }
  1364. public int Returned { get; set; }
  1365. public bool Truncated { get; set; }
  1366. public List<string> Sources { get; set; } = new();
  1367. public List<SmartDiagnosisEvidenceItem> Items { get; set; } = new();
  1368. }
  1369. internal sealed class SmartDiagnosisEvidenceSqlRow
  1370. {
  1371. public string? ObjectCode { get; set; }
  1372. public string? Title { get; set; }
  1373. public decimal? Contribution { get; set; }
  1374. public string? Status { get; set; }
  1375. public DateTime? OccurredAt { get; set; }
  1376. }