@things-factory/ops-master 10.1.248 → 10.1.250

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/dist-client/bootstrap.d.ts +19 -0
  2. package/dist-client/bootstrap.js +66 -0
  3. package/dist-client/bootstrap.js.map +1 -0
  4. package/dist-client/index.d.ts +17 -0
  5. package/dist-client/index.js +21 -0
  6. package/dist-client/index.js.map +1 -0
  7. package/dist-client/master-change-approval.d.ts +14 -0
  8. package/dist-client/master-change-approval.js +36 -0
  9. package/dist-client/master-change-approval.js.map +1 -0
  10. package/dist-client/master-change-policy-axes.d.ts +37 -0
  11. package/dist-client/master-change-policy-axes.js +29 -0
  12. package/dist-client/master-change-policy-axes.js.map +1 -0
  13. package/dist-client/master-change-policy-panel.d.ts +59 -0
  14. package/dist-client/master-change-policy-panel.js +454 -0
  15. package/dist-client/master-change-policy-panel.js.map +1 -0
  16. package/dist-client/master-change-providers.d.ts +4 -0
  17. package/dist-client/master-change-providers.js +91 -0
  18. package/dist-client/master-change-providers.js.map +1 -0
  19. package/dist-client/pages/master/applied-when-dialog.d.ts +48 -0
  20. package/dist-client/pages/master/applied-when-dialog.js +137 -0
  21. package/dist-client/pages/master/applied-when-dialog.js.map +1 -0
  22. package/dist-client/pages/master/assignment-fields.d.ts +27 -0
  23. package/dist-client/pages/master/assignment-fields.js +62 -0
  24. package/dist-client/pages/master/assignment-fields.js.map +1 -0
  25. package/dist-client/pages/master/equipment-class.d.ts +12 -0
  26. package/dist-client/pages/master/equipment-class.js +42 -0
  27. package/dist-client/pages/master/equipment-class.js.map +1 -0
  28. package/dist-client/pages/master/equipment.d.ts +12 -0
  29. package/dist-client/pages/master/equipment.js +58 -0
  30. package/dist-client/pages/master/equipment.js.map +1 -0
  31. package/dist-client/pages/master/grist-iso-duration.d.ts +20 -0
  32. package/dist-client/pages/master/grist-iso-duration.js +70 -0
  33. package/dist-client/pages/master/grist-iso-duration.js.map +1 -0
  34. package/dist-client/pages/master/grist-reference.d.ts +91 -0
  35. package/dist-client/pages/master/grist-reference.js +419 -0
  36. package/dist-client/pages/master/grist-reference.js.map +1 -0
  37. package/dist-client/pages/master/import-rows.d.ts +35 -0
  38. package/dist-client/pages/master/import-rows.js +66 -0
  39. package/dist-client/pages/master/import-rows.js.map +1 -0
  40. package/dist-client/pages/master/iso-duration.d.ts +34 -0
  41. package/dist-client/pages/master/iso-duration.js +76 -0
  42. package/dist-client/pages/master/iso-duration.js.map +1 -0
  43. package/dist-client/pages/master/master-options.d.ts +40 -0
  44. package/dist-client/pages/master/master-options.js +54 -0
  45. package/dist-client/pages/master/master-options.js.map +1 -0
  46. package/dist-client/pages/master/master-page-base.d.ts +369 -0
  47. package/dist-client/pages/master/master-page-base.js +657 -0
  48. package/dist-client/pages/master/master-page-base.js.map +1 -0
  49. package/dist-client/pages/master/material-class.d.ts +12 -0
  50. package/dist-client/pages/master/material-class.js +42 -0
  51. package/dist-client/pages/master/material-class.js.map +1 -0
  52. package/dist-client/pages/master/material-definition.d.ts +5 -0
  53. package/dist-client/pages/master/material-definition.js +14 -0
  54. package/dist-client/pages/master/material-definition.js.map +1 -0
  55. package/dist-client/pages/master/material-revision-fields.d.ts +2 -0
  56. package/dist-client/pages/master/material-revision-fields.js +43 -0
  57. package/dist-client/pages/master/material-revision-fields.js.map +1 -0
  58. package/dist-client/pages/master/operation-definition.d.ts +12 -0
  59. package/dist-client/pages/master/operation-definition.js +49 -0
  60. package/dist-client/pages/master/operation-definition.js.map +1 -0
  61. package/dist-client/pages/master/operational-location.d.ts +84 -0
  62. package/dist-client/pages/master/operational-location.js +432 -0
  63. package/dist-client/pages/master/operational-location.js.map +1 -0
  64. package/dist-client/pages/master/person.d.ts +12 -0
  65. package/dist-client/pages/master/person.js +41 -0
  66. package/dist-client/pages/master/person.js.map +1 -0
  67. package/dist-client/pages/master/personnel-class.d.ts +12 -0
  68. package/dist-client/pages/master/personnel-class.js +43 -0
  69. package/dist-client/pages/master/personnel-class.js.map +1 -0
  70. package/dist-client/pages/master/physical-asset-class.d.ts +12 -0
  71. package/dist-client/pages/master/physical-asset-class.js +40 -0
  72. package/dist-client/pages/master/physical-asset-class.js.map +1 -0
  73. package/dist-client/pages/master/physical-asset.d.ts +12 -0
  74. package/dist-client/pages/master/physical-asset.js +41 -0
  75. package/dist-client/pages/master/physical-asset.js.map +1 -0
  76. package/dist-client/pages/master/recipe-definition.d.ts +5 -0
  77. package/dist-client/pages/master/recipe-definition.js +14 -0
  78. package/dist-client/pages/master/recipe-definition.js.map +1 -0
  79. package/dist-client/pages/master/reference-targets.d.ts +42 -0
  80. package/dist-client/pages/master/reference-targets.js +82 -0
  81. package/dist-client/pages/master/reference-targets.js.map +1 -0
  82. package/dist-client/pages/master/revision-comparison.d.ts +49 -0
  83. package/dist-client/pages/master/revision-comparison.js +560 -0
  84. package/dist-client/pages/master/revision-comparison.js.map +1 -0
  85. package/dist-client/pages/master/revision-view.d.ts +34 -0
  86. package/dist-client/pages/master/revision-view.js +145 -0
  87. package/dist-client/pages/master/revision-view.js.map +1 -0
  88. package/dist-client/pages/master/revision-workspace.d.ts +50 -0
  89. package/dist-client/pages/master/revision-workspace.js +763 -0
  90. package/dist-client/pages/master/revision-workspace.js.map +1 -0
  91. package/dist-client/pages/master/route-definition.d.ts +19 -0
  92. package/dist-client/pages/master/route-definition.js +40 -0
  93. package/dist-client/pages/master/route-definition.js.map +1 -0
  94. package/dist-client/pages/master/stop-reason.d.ts +12 -0
  95. package/dist-client/pages/master/stop-reason.js +48 -0
  96. package/dist-client/pages/master/stop-reason.js.map +1 -0
  97. package/dist-client/pages/master/test-specification.d.ts +5 -0
  98. package/dist-client/pages/master/test-specification.js +14 -0
  99. package/dist-client/pages/master/test-specification.js.map +1 -0
  100. package/dist-client/pages/master-axes.d.ts +24 -0
  101. package/dist-client/pages/master-axes.js +39 -0
  102. package/dist-client/pages/master-axes.js.map +1 -0
  103. package/dist-client/route.d.ts +1 -0
  104. package/dist-client/route.js +81 -0
  105. package/dist-client/route.js.map +1 -0
  106. package/dist-client/tsconfig.tsbuildinfo +1 -0
  107. package/dist-server/index.d.ts +1 -0
  108. package/dist-server/index.js +19 -0
  109. package/dist-server/index.js.map +1 -0
  110. package/dist-server/service/ai-entry/master-entry-rules.d.ts +175 -0
  111. package/dist-server/service/ai-entry/master-entry-rules.js +302 -0
  112. package/dist-server/service/ai-entry/master-entry-rules.js.map +1 -0
  113. package/dist-server/service/ai-entry/master-entry-targets.d.ts +23 -0
  114. package/dist-server/service/ai-entry/master-entry-targets.js +293 -0
  115. package/dist-server/service/ai-entry/master-entry-targets.js.map +1 -0
  116. package/dist-server/service/approval-route.d.ts +37 -0
  117. package/dist-server/service/approval-route.js +34 -0
  118. package/dist-server/service/approval-route.js.map +1 -0
  119. package/dist-server/service/asset/asset-lifecycle.d.ts +106 -0
  120. package/dist-server/service/asset/asset-lifecycle.js +126 -0
  121. package/dist-server/service/asset/asset-lifecycle.js.map +1 -0
  122. package/dist-server/service/asset/asset-master-resolver.d.ts +53 -0
  123. package/dist-server/service/asset/asset-master-resolver.js +185 -0
  124. package/dist-server/service/asset/asset-master-resolver.js.map +1 -0
  125. package/dist-server/service/asset/asset-master.d.ts +21 -0
  126. package/dist-server/service/asset/asset-master.js +25 -0
  127. package/dist-server/service/asset/asset-master.js.map +1 -0
  128. package/dist-server/service/asset/asset-query.d.ts +16 -0
  129. package/dist-server/service/asset/asset-query.js +72 -0
  130. package/dist-server/service/asset/asset-query.js.map +1 -0
  131. package/dist-server/service/asset/index.d.ts +6 -0
  132. package/dist-server/service/asset/index.js +10 -0
  133. package/dist-server/service/asset/index.js.map +1 -0
  134. package/dist-server/service/asset/physical-asset-class.d.ts +34 -0
  135. package/dist-server/service/asset/physical-asset-class.js +104 -0
  136. package/dist-server/service/asset/physical-asset-class.js.map +1 -0
  137. package/dist-server/service/asset/physical-asset.d.ts +66 -0
  138. package/dist-server/service/asset/physical-asset.js +123 -0
  139. package/dist-server/service/asset/physical-asset.js.map +1 -0
  140. package/dist-server/service/assignment/applied-when.d.ts +24 -0
  141. package/dist-server/service/assignment/applied-when.js +16 -0
  142. package/dist-server/service/assignment/applied-when.js.map +1 -0
  143. package/dist-server/service/assignment/assignment-history.d.ts +92 -0
  144. package/dist-server/service/assignment/assignment-history.js +289 -0
  145. package/dist-server/service/assignment/assignment-history.js.map +1 -0
  146. package/dist-server/service/assignment/assignment-write.d.ts +42 -0
  147. package/dist-server/service/assignment/assignment-write.js +101 -0
  148. package/dist-server/service/assignment/assignment-write.js.map +1 -0
  149. package/dist-server/service/assignment/master-value-claim.d.ts +135 -0
  150. package/dist-server/service/assignment/master-value-claim.js +174 -0
  151. package/dist-server/service/assignment/master-value-claim.js.map +1 -0
  152. package/dist-server/service/equipment/equipment-class.d.ts +34 -0
  153. package/dist-server/service/equipment/equipment-class.js +104 -0
  154. package/dist-server/service/equipment/equipment-class.js.map +1 -0
  155. package/dist-server/service/equipment/equipment-master-resolver.d.ts +77 -0
  156. package/dist-server/service/equipment/equipment-master-resolver.js +266 -0
  157. package/dist-server/service/equipment/equipment-master-resolver.js.map +1 -0
  158. package/dist-server/service/equipment/equipment-master.d.ts +30 -0
  159. package/dist-server/service/equipment/equipment-master.js +53 -0
  160. package/dist-server/service/equipment/equipment-master.js.map +1 -0
  161. package/dist-server/service/equipment/equipment-query.d.ts +16 -0
  162. package/dist-server/service/equipment/equipment-query.js +72 -0
  163. package/dist-server/service/equipment/equipment-query.js.map +1 -0
  164. package/dist-server/service/equipment/equipment.d.ts +71 -0
  165. package/dist-server/service/equipment/equipment.js +138 -0
  166. package/dist-server/service/equipment/equipment.js.map +1 -0
  167. package/dist-server/service/equipment/index.d.ts +8 -0
  168. package/dist-server/service/equipment/index.js +12 -0
  169. package/dist-server/service/equipment/index.js.map +1 -0
  170. package/dist-server/service/equipment/state-period-rules.d.ts +95 -0
  171. package/dist-server/service/equipment/state-period-rules.js +122 -0
  172. package/dist-server/service/equipment/state-period-rules.js.map +1 -0
  173. package/dist-server/service/equipment/stop-reason-query.d.ts +11 -0
  174. package/dist-server/service/equipment/stop-reason-query.js +39 -0
  175. package/dist-server/service/equipment/stop-reason-query.js.map +1 -0
  176. package/dist-server/service/equipment/stop-reason.d.ts +58 -0
  177. package/dist-server/service/equipment/stop-reason.js +114 -0
  178. package/dist-server/service/equipment/stop-reason.js.map +1 -0
  179. package/dist-server/service/index.d.ts +82 -0
  180. package/dist-server/service/index.js +145 -0
  181. package/dist-server/service/index.js.map +1 -0
  182. package/dist-server/service/location/index.d.ts +5 -0
  183. package/dist-server/service/location/index.js +9 -0
  184. package/dist-server/service/location/index.js.map +1 -0
  185. package/dist-server/service/location/location-master-resolver.d.ts +60 -0
  186. package/dist-server/service/location/location-master-resolver.js +313 -0
  187. package/dist-server/service/location/location-master-resolver.js.map +1 -0
  188. package/dist-server/service/location/location-master.d.ts +26 -0
  189. package/dist-server/service/location/location-master.js +28 -0
  190. package/dist-server/service/location/location-master.js.map +1 -0
  191. package/dist-server/service/location/location-query.d.ts +15 -0
  192. package/dist-server/service/location/location-query.js +56 -0
  193. package/dist-server/service/location/location-query.js.map +1 -0
  194. package/dist-server/service/location/operational-location.d.ts +116 -0
  195. package/dist-server/service/location/operational-location.js +157 -0
  196. package/dist-server/service/location/operational-location.js.map +1 -0
  197. package/dist-server/service/master-axis.d.ts +40 -0
  198. package/dist-server/service/master-axis.js +57 -0
  199. package/dist-server/service/master-axis.js.map +1 -0
  200. package/dist-server/service/master-change-approval/approval-input.d.ts +17 -0
  201. package/dist-server/service/master-change-approval/approval-input.js +35 -0
  202. package/dist-server/service/master-change-approval/approval-input.js.map +1 -0
  203. package/dist-server/service/master-change-approval/builtin-axes.d.ts +4 -0
  204. package/dist-server/service/master-change-approval/builtin-axes.js +96 -0
  205. package/dist-server/service/master-change-approval/builtin-axes.js.map +1 -0
  206. package/dist-server/service/master-change-approval/index.d.ts +14 -0
  207. package/dist-server/service/master-change-approval/index.js +37 -0
  208. package/dist-server/service/master-change-approval/index.js.map +1 -0
  209. package/dist-server/service/master-change-approval/master-change-axis.d.ts +54 -0
  210. package/dist-server/service/master-change-approval/master-change-axis.js +17 -0
  211. package/dist-server/service/master-change-approval/master-change-axis.js.map +1 -0
  212. package/dist-server/service/master-change-approval/master-change-flow.d.ts +65 -0
  213. package/dist-server/service/master-change-approval/master-change-flow.js +125 -0
  214. package/dist-server/service/master-change-approval/master-change-flow.js.map +1 -0
  215. package/dist-server/service/master-change-approval/master-change-resolver.d.ts +18 -0
  216. package/dist-server/service/master-change-approval/master-change-resolver.js +58 -0
  217. package/dist-server/service/master-change-approval/master-change-resolver.js.map +1 -0
  218. package/dist-server/service/master-change-policy.d.ts +122 -0
  219. package/dist-server/service/master-change-policy.js +304 -0
  220. package/dist-server/service/master-change-policy.js.map +1 -0
  221. package/dist-server/service/master-conformance-resolver.d.ts +34 -0
  222. package/dist-server/service/master-conformance-resolver.js +153 -0
  223. package/dist-server/service/master-conformance-resolver.js.map +1 -0
  224. package/dist-server/service/master-conformance.d.ts +80 -0
  225. package/dist-server/service/master-conformance.js +266 -0
  226. package/dist-server/service/master-conformance.js.map +1 -0
  227. package/dist-server/service/master-crud.d.ts +55 -0
  228. package/dist-server/service/master-crud.js +93 -0
  229. package/dist-server/service/master-crud.js.map +1 -0
  230. package/dist-server/service/master-list.d.ts +12 -0
  231. package/dist-server/service/master-list.js +30 -0
  232. package/dist-server/service/master-list.js.map +1 -0
  233. package/dist-server/service/master-page-query.d.ts +33 -0
  234. package/dist-server/service/master-page-query.js +55 -0
  235. package/dist-server/service/master-page-query.js.map +1 -0
  236. package/dist-server/service/master-page.d.ts +85 -0
  237. package/dist-server/service/master-page.js +104 -0
  238. package/dist-server/service/master-page.js.map +1 -0
  239. package/dist-server/service/material/index.d.ts +7 -0
  240. package/dist-server/service/material/index.js +12 -0
  241. package/dist-server/service/material/index.js.map +1 -0
  242. package/dist-server/service/material/material-axis-status.d.ts +8 -0
  243. package/dist-server/service/material/material-axis-status.js +19 -0
  244. package/dist-server/service/material/material-axis-status.js.map +1 -0
  245. package/dist-server/service/material/material-class.d.ts +34 -0
  246. package/dist-server/service/material/material-class.js +104 -0
  247. package/dist-server/service/material/material-class.js.map +1 -0
  248. package/dist-server/service/material/material-definition.d.ts +45 -0
  249. package/dist-server/service/material/material-definition.js +125 -0
  250. package/dist-server/service/material/material-definition.js.map +1 -0
  251. package/dist-server/service/material/material-effective-list.d.ts +39 -0
  252. package/dist-server/service/material/material-effective-list.js +54 -0
  253. package/dist-server/service/material/material-effective-list.js.map +1 -0
  254. package/dist-server/service/material/material-master-resolver.d.ts +106 -0
  255. package/dist-server/service/material/material-master-resolver.js +351 -0
  256. package/dist-server/service/material/material-master-resolver.js.map +1 -0
  257. package/dist-server/service/material/material-master.d.ts +9 -0
  258. package/dist-server/service/material/material-master.js +24 -0
  259. package/dist-server/service/material/material-master.js.map +1 -0
  260. package/dist-server/service/material/material-query.d.ts +16 -0
  261. package/dist-server/service/material/material-query.js +79 -0
  262. package/dist-server/service/material/material-query.js.map +1 -0
  263. package/dist-server/service/material/material-revision-content.d.ts +10 -0
  264. package/dist-server/service/material/material-revision-content.js +92 -0
  265. package/dist-server/service/material/material-revision-content.js.map +1 -0
  266. package/dist-server/service/material/material-revision-resolver.d.ts +60 -0
  267. package/dist-server/service/material/material-revision-resolver.js +96 -0
  268. package/dist-server/service/material/material-revision-resolver.js.map +1 -0
  269. package/dist-server/service/material/material-revision-service.d.ts +179 -0
  270. package/dist-server/service/material/material-revision-service.js +687 -0
  271. package/dist-server/service/material/material-revision-service.js.map +1 -0
  272. package/dist-server/service/material/material-revision.d.ts +86 -0
  273. package/dist-server/service/material/material-revision.js +339 -0
  274. package/dist-server/service/material/material-revision.js.map +1 -0
  275. package/dist-server/service/material/recipe-index.d.ts +23 -0
  276. package/dist-server/service/material/recipe-index.js +44 -0
  277. package/dist-server/service/material/recipe-index.js.map +1 -0
  278. package/dist-server/service/operation/index.d.ts +6 -0
  279. package/dist-server/service/operation/index.js +10 -0
  280. package/dist-server/service/operation/index.js.map +1 -0
  281. package/dist-server/service/operation/operation-definition.d.ts +52 -0
  282. package/dist-server/service/operation/operation-definition.js +143 -0
  283. package/dist-server/service/operation/operation-definition.js.map +1 -0
  284. package/dist-server/service/operation/operation-master-resolver.d.ts +52 -0
  285. package/dist-server/service/operation/operation-master-resolver.js +187 -0
  286. package/dist-server/service/operation/operation-master-resolver.js.map +1 -0
  287. package/dist-server/service/operation/operation-master.d.ts +21 -0
  288. package/dist-server/service/operation/operation-master.js +28 -0
  289. package/dist-server/service/operation/operation-master.js.map +1 -0
  290. package/dist-server/service/operation/operation-query.d.ts +15 -0
  291. package/dist-server/service/operation/operation-query.js +56 -0
  292. package/dist-server/service/operation/operation-query.js.map +1 -0
  293. package/dist-server/service/operation/operation-readiness-resolver.d.ts +39 -0
  294. package/dist-server/service/operation/operation-readiness-resolver.js +111 -0
  295. package/dist-server/service/operation/operation-readiness-resolver.js.map +1 -0
  296. package/dist-server/service/operation/operation-readiness.d.ts +34 -0
  297. package/dist-server/service/operation/operation-readiness.js +133 -0
  298. package/dist-server/service/operation/operation-readiness.js.map +1 -0
  299. package/dist-server/service/personnel/index.d.ts +6 -0
  300. package/dist-server/service/personnel/index.js +10 -0
  301. package/dist-server/service/personnel/index.js.map +1 -0
  302. package/dist-server/service/personnel/person.d.ts +51 -0
  303. package/dist-server/service/personnel/person.js +119 -0
  304. package/dist-server/service/personnel/person.js.map +1 -0
  305. package/dist-server/service/personnel/personnel-class-readiness.d.ts +22 -0
  306. package/dist-server/service/personnel/personnel-class-readiness.js +98 -0
  307. package/dist-server/service/personnel/personnel-class-readiness.js.map +1 -0
  308. package/dist-server/service/personnel/personnel-class.d.ts +54 -0
  309. package/dist-server/service/personnel/personnel-class.js +114 -0
  310. package/dist-server/service/personnel/personnel-class.js.map +1 -0
  311. package/dist-server/service/personnel/personnel-master-resolver.d.ts +53 -0
  312. package/dist-server/service/personnel/personnel-master-resolver.js +187 -0
  313. package/dist-server/service/personnel/personnel-master-resolver.js.map +1 -0
  314. package/dist-server/service/personnel/personnel-master.d.ts +39 -0
  315. package/dist-server/service/personnel/personnel-master.js +34 -0
  316. package/dist-server/service/personnel/personnel-master.js.map +1 -0
  317. package/dist-server/service/personnel/personnel-query.d.ts +29 -0
  318. package/dist-server/service/personnel/personnel-query.js +79 -0
  319. package/dist-server/service/personnel/personnel-query.js.map +1 -0
  320. package/dist-server/service/personnel/qualification.d.ts +104 -0
  321. package/dist-server/service/personnel/qualification.js +147 -0
  322. package/dist-server/service/personnel/qualification.js.map +1 -0
  323. package/dist-server/service/quality/index.d.ts +4 -0
  324. package/dist-server/service/quality/index.js +8 -0
  325. package/dist-server/service/quality/index.js.map +1 -0
  326. package/dist-server/service/quality/nonconformance-cause-resolver.d.ts +12 -0
  327. package/dist-server/service/quality/nonconformance-cause-resolver.js +60 -0
  328. package/dist-server/service/quality/nonconformance-cause-resolver.js.map +1 -0
  329. package/dist-server/service/quality/nonconformance-cause.d.ts +20 -0
  330. package/dist-server/service/quality/nonconformance-cause.js +90 -0
  331. package/dist-server/service/quality/nonconformance-cause.js.map +1 -0
  332. package/dist-server/service/recipe/index.d.ts +10 -0
  333. package/dist-server/service/recipe/index.js +16 -0
  334. package/dist-server/service/recipe/index.js.map +1 -0
  335. package/dist-server/service/recipe/recipe-definition.d.ts +75 -0
  336. package/dist-server/service/recipe/recipe-definition.js +143 -0
  337. package/dist-server/service/recipe/recipe-definition.js.map +1 -0
  338. package/dist-server/service/recipe/recipe-effective-list.d.ts +49 -0
  339. package/dist-server/service/recipe/recipe-effective-list.js +96 -0
  340. package/dist-server/service/recipe/recipe-effective-list.js.map +1 -0
  341. package/dist-server/service/recipe/recipe-master-resolver.d.ts +28 -0
  342. package/dist-server/service/recipe/recipe-master-resolver.js +128 -0
  343. package/dist-server/service/recipe/recipe-master-resolver.js.map +1 -0
  344. package/dist-server/service/recipe/recipe-master.d.ts +37 -0
  345. package/dist-server/service/recipe/recipe-master.js +47 -0
  346. package/dist-server/service/recipe/recipe-master.js.map +1 -0
  347. package/dist-server/service/recipe/recipe-query.d.ts +21 -0
  348. package/dist-server/service/recipe/recipe-query.js +82 -0
  349. package/dist-server/service/recipe/recipe-query.js.map +1 -0
  350. package/dist-server/service/recipe/recipe-revision-content.d.ts +32 -0
  351. package/dist-server/service/recipe/recipe-revision-content.js +70 -0
  352. package/dist-server/service/recipe/recipe-revision-content.js.map +1 -0
  353. package/dist-server/service/recipe/recipe-revision-line.d.ts +30 -0
  354. package/dist-server/service/recipe/recipe-revision-line.js +95 -0
  355. package/dist-server/service/recipe/recipe-revision-line.js.map +1 -0
  356. package/dist-server/service/recipe/recipe-revision-resolver.d.ts +65 -0
  357. package/dist-server/service/recipe/recipe-revision-resolver.js +96 -0
  358. package/dist-server/service/recipe/recipe-revision-resolver.js.map +1 -0
  359. package/dist-server/service/recipe/recipe-revision-service.d.ts +183 -0
  360. package/dist-server/service/recipe/recipe-revision-service.js +754 -0
  361. package/dist-server/service/recipe/recipe-revision-service.js.map +1 -0
  362. package/dist-server/service/recipe/recipe-revision.d.ts +102 -0
  363. package/dist-server/service/recipe/recipe-revision.js +373 -0
  364. package/dist-server/service/recipe/recipe-revision.js.map +1 -0
  365. package/dist-server/service/recipe/route-definition.d.ts +51 -0
  366. package/dist-server/service/recipe/route-definition.js +114 -0
  367. package/dist-server/service/recipe/route-definition.js.map +1 -0
  368. package/dist-server/service/resource/class-lineage.d.ts +46 -0
  369. package/dist-server/service/resource/class-lineage.js +80 -0
  370. package/dist-server/service/resource/class-lineage.js.map +1 -0
  371. package/dist-server/service/resource/class-members.d.ts +36 -0
  372. package/dist-server/service/resource/class-members.js +59 -0
  373. package/dist-server/service/resource/class-members.js.map +1 -0
  374. package/dist-server/service/resource/referrers.d.ts +54 -0
  375. package/dist-server/service/resource/referrers.js +99 -0
  376. package/dist-server/service/resource/referrers.js.map +1 -0
  377. package/dist-server/service/resource/resource-class.d.ts +25 -0
  378. package/dist-server/service/resource/resource-class.js +29 -0
  379. package/dist-server/service/resource/resource-class.js.map +1 -0
  380. package/dist-server/service/revision-baseline.d.ts +71 -0
  381. package/dist-server/service/revision-baseline.js +87 -0
  382. package/dist-server/service/revision-baseline.js.map +1 -0
  383. package/dist-server/service/row-lock.d.ts +22 -0
  384. package/dist-server/service/row-lock.js +31 -0
  385. package/dist-server/service/row-lock.js.map +1 -0
  386. package/dist-server/service/status/axis-stamp.d.ts +16 -0
  387. package/dist-server/service/status/axis-stamp.js +22 -0
  388. package/dist-server/service/status/axis-stamp.js.map +1 -0
  389. package/dist-server/service/status/index.d.ts +3 -0
  390. package/dist-server/service/status/index.js +7 -0
  391. package/dist-server/service/status/index.js.map +1 -0
  392. package/dist-server/service/status/master-status.d.ts +38 -0
  393. package/dist-server/service/status/master-status.js +129 -0
  394. package/dist-server/service/status/master-status.js.map +1 -0
  395. package/dist-server/service/test-spec/criteria-check.d.ts +53 -0
  396. package/dist-server/service/test-spec/criteria-check.js +142 -0
  397. package/dist-server/service/test-spec/criteria-check.js.map +1 -0
  398. package/dist-server/service/test-spec/criteria-rows.d.ts +89 -0
  399. package/dist-server/service/test-spec/criteria-rows.js +139 -0
  400. package/dist-server/service/test-spec/criteria-rows.js.map +1 -0
  401. package/dist-server/service/test-spec/index.d.ts +6 -0
  402. package/dist-server/service/test-spec/index.js +11 -0
  403. package/dist-server/service/test-spec/index.js.map +1 -0
  404. package/dist-server/service/test-spec/test-spec-effective-list.d.ts +34 -0
  405. package/dist-server/service/test-spec/test-spec-effective-list.js +42 -0
  406. package/dist-server/service/test-spec/test-spec-effective-list.js.map +1 -0
  407. package/dist-server/service/test-spec/test-spec-master-resolver.d.ts +44 -0
  408. package/dist-server/service/test-spec/test-spec-master-resolver.js +144 -0
  409. package/dist-server/service/test-spec/test-spec-master-resolver.js.map +1 -0
  410. package/dist-server/service/test-spec/test-spec-master.d.ts +6 -0
  411. package/dist-server/service/test-spec/test-spec-master.js +18 -0
  412. package/dist-server/service/test-spec/test-spec-master.js.map +1 -0
  413. package/dist-server/service/test-spec/test-spec-query.d.ts +15 -0
  414. package/dist-server/service/test-spec/test-spec-query.js +61 -0
  415. package/dist-server/service/test-spec/test-spec-query.js.map +1 -0
  416. package/dist-server/service/test-spec/test-spec-revision-resolver.d.ts +59 -0
  417. package/dist-server/service/test-spec/test-spec-revision-resolver.js +96 -0
  418. package/dist-server/service/test-spec/test-spec-revision-resolver.js.map +1 -0
  419. package/dist-server/service/test-spec/test-spec-revision-service.d.ts +178 -0
  420. package/dist-server/service/test-spec/test-spec-revision-service.js +685 -0
  421. package/dist-server/service/test-spec/test-spec-revision-service.js.map +1 -0
  422. package/dist-server/service/test-spec/test-spec-revision.d.ts +86 -0
  423. package/dist-server/service/test-spec/test-spec-revision.js +334 -0
  424. package/dist-server/service/test-spec/test-spec-revision.js.map +1 -0
  425. package/dist-server/service/test-spec/test-specification.d.ts +47 -0
  426. package/dist-server/service/test-spec/test-specification.js +119 -0
  427. package/dist-server/service/test-spec/test-specification.js.map +1 -0
  428. package/dist-server/tsconfig.tsbuildinfo +1 -0
  429. package/package.json +4 -4
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ /**
3
+ * 마스터가 **말이 되나** — 축을 가로질러 한 번에 본다.
4
+ *
5
+ * ── 왜 필요한가 ────────────────────────────────────────────────────────────
6
+ * 축마다 화면이 있고 축마다 값이 차 있는데, 그 사이가 이어지는지는 아무도 안 봤다. 설비 등급 다섯이
7
+ * 서 있고 설비 스물둘이 어느 등급에도 안 들어 있던 일이 그랬다 — 두 화면 다 멀쩡해 보였다.
8
+ * 카메라 자산 다섯이 ECU 등급에 들어 있던 것도, 정지 사유 고르기가 빈 목록으로 보이던 것도 같다.
9
+ *
10
+ * 사람이 열두 화면을 오가며 맞춰 보는 것으로는 안 된다. 맞춰 보지 않으면 아무도 모르고, 맞춰 봤는지
11
+ * 아닌지도 남지 않는다.
12
+ *
13
+ * ── 두 가지만 본다 ─────────────────────────────────────────────────────────
14
+ * **비어 있으면 안 되는 칸**과 **가리키는데 없는 것**이다. 둘 다 사실 판정이라 다툼이 없다.
15
+ * 「이 값이 옳은가」는 여기서 안 본다 — 그것은 현장이 정한다.
16
+ *
17
+ * ── 없는 것을 없다고 말한다 ────────────────────────────────────────────────
18
+ * 표가 통째로 비었으면 그것도 낸다. 「빠진 것 0건」과 「아직 아무것도 안 세웠다」는 다르고, 세지
19
+ * 않으면 둘이 같아 보인다.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.checkMaster = checkMaster;
23
+ exports.scannedCounts = scannedCounts;
24
+ exports.summarize = summarize;
25
+ exports.readMasterSnapshot = readMasterSnapshot;
26
+ const nameSet = (rows) => new Set(rows.map(one => one.name).filter(Boolean));
27
+ /** 값이 비었나 — 빈 문자열과 빈 배열도 빈 것으로 본다. */
28
+ function blank(value) {
29
+ if (value === null || value === undefined) {
30
+ return true;
31
+ }
32
+ if (Array.isArray(value)) {
33
+ return value.length === 0;
34
+ }
35
+ return String(value).trim() === '';
36
+ }
37
+ /** 이름 목록으로 만든다 — 한 개짜리 문자열도, 배열도 같게 다룬다. */
38
+ function asList(value) {
39
+ if (blank(value)) {
40
+ return [];
41
+ }
42
+ return (Array.isArray(value) ? value : [value]).map(one => String(one).trim()).filter(Boolean);
43
+ }
44
+ /**
45
+ * 축 하나를 잰다.
46
+ *
47
+ * `required` 는 비어 있으면 안 되는 칸, `refs` 는 「이 칸의 값이 저 이름들 안에 있어야 한다」이다.
48
+ */
49
+ function checkAxis(axis, rows, required, refs) {
50
+ const found = [];
51
+ if (rows.length === 0) {
52
+ /* 표가 통째로 비었다. 「빠진 것 0건」과 다르다. */
53
+ return [{ axis, kind: 'empty', field: axis }];
54
+ }
55
+ for (const row of rows) {
56
+ for (const field of required) {
57
+ if (blank(row[field])) {
58
+ found.push({ axis, subject: row.name, kind: 'missing', field });
59
+ }
60
+ }
61
+ for (const { field, within } of refs) {
62
+ for (const value of asList(row[field])) {
63
+ if (!within.has(value)) {
64
+ found.push({ axis, subject: row.name, kind: 'dangling', field, value });
65
+ }
66
+ }
67
+ }
68
+ }
69
+ return found;
70
+ }
71
+ /** 아무도 안 가리키는 것들 — 세워 놓고 쓰지 않는 선언. */
72
+ function checkUnused(axis, rows, pointedAt, field) {
73
+ return rows
74
+ .filter(one => one.name && !pointedAt.has(one.name))
75
+ .map(one => ({ axis, subject: one.name, kind: 'unused', field }));
76
+ }
77
+ /**
78
+ * 마스터 전체를 잰다.
79
+ *
80
+ * **순서에 뜻이 없다.** 어느 축부터 보든 같은 답이 나와야 하고, 그래야 이 결과를 두 번 재서
81
+ * 견줄 수 있다.
82
+ */
83
+ function checkMaster(snapshot) {
84
+ const locations = nameSet(snapshot.operationalLocations);
85
+ const operations = nameSet(snapshot.operationDefinitions);
86
+ const routes = nameSet(snapshot.routeDefinitions);
87
+ const materials = nameSet(snapshot.materialDefinitions);
88
+ const specs = nameSet(snapshot.testSpecifications);
89
+ const personnelClasses = nameSet(snapshot.personnelClasses);
90
+ const equipmentClasses = nameSet(snapshot.equipmentClasses);
91
+ const assetClasses = nameSet(snapshot.physicalAssetClasses);
92
+ const materialClasses = nameSet(snapshot.materialClasses);
93
+ const stopReasons = nameSet(snapshot.stopReasons);
94
+ const found = [
95
+ ...checkAxis('person', snapshot.persons, ['personnelClassIds', 'homeLocation'], [
96
+ { field: 'personnelClassIds', within: personnelClasses },
97
+ { field: 'homeLocation', within: locations },
98
+ { field: 'testSpecificationIds', within: specs }
99
+ ]),
100
+ ...checkAxis('equipment', snapshot.equipment, ['kind', 'homeLocation', 'equipmentClassIds'], [
101
+ { field: 'equipmentClassIds', within: equipmentClasses },
102
+ { field: 'homeLocation', within: locations },
103
+ { field: 'testSpecificationIds', within: specs }
104
+ ]),
105
+ ...checkAxis('physicalAsset', snapshot.physicalAssets, ['assetClassIds'], [
106
+ { field: 'assetClassIds', within: assetClasses },
107
+ { field: 'homeLocation', within: locations },
108
+ { field: 'testSpecificationIds', within: specs }
109
+ ]),
110
+ ...checkAxis('materialDefinition', snapshot.materialDefinitions, ['materialClassIds'], [
111
+ { field: 'materialClassIds', within: materialClasses },
112
+ { field: 'testSpecificationIds', within: specs }
113
+ ]),
114
+ /*
115
+ * 공정의 `resourceType` 은 설비 **종류**를 가리키는 값이라 이름 집합이 없다. 여기서는
116
+ * 비었는지만 본다 — 없는 것을 있는 척 검사하지 않는다.
117
+ */
118
+ ...checkAxis('operationDefinition', snapshot.operationDefinitions, ['intent', 'locationType', 'duration'], []),
119
+ ...checkAxis('routeDefinition', snapshot.routeDefinitions, ['steps'], [
120
+ { field: 'steps', within: operations }
121
+ ]),
122
+ ...checkAxis('recipeDefinition', snapshot.recipeDefinitions, ['materialDefinitionName', 'route', 'inputs'], [
123
+ { field: 'materialDefinitionName', within: materials },
124
+ { field: 'route', within: routes }
125
+ ]),
126
+ ...checkAxis('operationalLocation', snapshot.operationalLocations, ['type', 'level'], [
127
+ { field: 'parentId', within: locations }
128
+ ]),
129
+ ...checkAxis('stopReason', snapshot.stopReasons, ['status'], [{ field: 'parentName', within: stopReasons }]),
130
+ ...checkAxis('testSpecification', snapshot.testSpecifications, ['criteria'], [])
131
+ ];
132
+ /*
133
+ * 제조법의 투입은 한 줄이 여럿을 가리킨다. 위의 검사는 칸 하나를 보므로 여기서 따로 본다.
134
+ */
135
+ for (const recipe of snapshot.recipeDefinitions) {
136
+ for (const part of recipe.inputs ?? []) {
137
+ if (part?.material && !materials.has(part.material)) {
138
+ found.push({ axis: 'recipeDefinition', subject: recipe.name, kind: 'dangling', field: 'inputs.material', value: part.material });
139
+ }
140
+ if (part?.operation && !operations.has(part.operation)) {
141
+ found.push({ axis: 'recipeDefinition', subject: recipe.name, kind: 'dangling', field: 'inputs.operation', value: part.operation });
142
+ }
143
+ }
144
+ }
145
+ /*
146
+ * ── 세워 놓고 아무도 안 든 등급 ─────────────────────────────────────────
147
+ *
148
+ * **상속을 타고 센다.** 등급은 등급을 상속하고(`baseIds`), 자격 판정도 그 사슬을 닫아서 본다
149
+ * (커널의 `classClosure`). 그러니 「아무도 안 든다」도 닫힌 소속으로 물어야 한다.
150
+ *
151
+ * 직접 소속만 세면 뿌리 등급이 늘 걸린다. 품목의 유형 등급(완제품 · 반제품 · 원재료)이 그렇다 —
152
+ * 품목은 성격 등급에 들고 그 등급이 유형을 상속하므로, 직접 소속은 언제나 0이다. 그것을 결함으로
153
+ * 읽으면 멀쩡한 등급을 지우러 간다.
154
+ *
155
+ * 처음에는 품목만 따로 다뤘고 나머지 셋은 직접 소속으로 셌다. 아키텍트 레인이 설비 등급에도
156
+ * 같은 축이 있다고 알려 주어 넷을 한 규칙으로 모았다 — 축마다 다르게 세면 한쪽만 고쳐지는 날이
157
+ * 온다. [재봤음] 2026-09-04
158
+ */
159
+ const classAxes = [
160
+ ['personnelClass', snapshot.personnelClasses, snapshot.persons, 'personnelClassIds'],
161
+ ['equipmentClass', snapshot.equipmentClasses, snapshot.equipment, 'equipmentClassIds'],
162
+ ['physicalAssetClass', snapshot.physicalAssetClasses, snapshot.physicalAssets, 'assetClassIds'],
163
+ ['materialClass', snapshot.materialClasses, snapshot.materialDefinitions, 'materialClassIds']
164
+ ];
165
+ for (const [axis, classes, members, field] of classAxes) {
166
+ found.push(...checkUnused(axis, classes, closedMembership(classes, members, field), 'members'));
167
+ }
168
+ /* 아무도 안 가리키는 라우팅·공정. 만들어 놓고 안 쓰는 것은 지워도 되는 것인지 사람이 판단한다. */
169
+ const routesUsed = new Set(snapshot.recipeDefinitions.map(one => one.route).filter(Boolean));
170
+ const operationsUsed = new Set([
171
+ ...snapshot.routeDefinitions.flatMap(one => asList(one.steps)),
172
+ ...snapshot.recipeDefinitions.flatMap(one => (one.inputs ?? []).map((part) => part?.operation).filter(Boolean))
173
+ ]);
174
+ found.push(...checkUnused('routeDefinition', snapshot.routeDefinitions, routesUsed, 'usedByRecipes'), ...checkUnused('operationDefinition', snapshot.operationDefinitions, operationsUsed, 'usedInRoutes'));
175
+ return found;
176
+ }
177
+ /**
178
+ * **닫힌 소속** — 소속이 상속을 타고 닿는 등급까지 모은다.
179
+ *
180
+ * 사람이 `welding-robot-6axis` 에 들고 그것이 `welding-equipment` 를 상속하면, 두 등급 다 「누가
181
+ * 들었다」로 센다. 자격 판정이 그 사슬을 닫아서 보므로(커널의 `classClosure`) 여기서도 같게 본다.
182
+ *
183
+ * **고리를 밟으면 멈춘다.** `baseIds` 는 화면에서 손으로 넣을 수 있어 A→B→A 가 생길 수 있다.
184
+ */
185
+ function closedMembership(classes, members, field) {
186
+ const baseOf = new Map(classes.map(one => [one.name, asList(one.baseIds)]));
187
+ const reached = new Set();
188
+ const walk = (name) => {
189
+ if (!name || reached.has(name)) {
190
+ return;
191
+ }
192
+ reached.add(name);
193
+ for (const base of baseOf.get(name) ?? []) {
194
+ walk(base);
195
+ }
196
+ };
197
+ for (const row of members) {
198
+ for (const name of asList(row[field])) {
199
+ walk(name);
200
+ }
201
+ }
202
+ return reached;
203
+ }
204
+ /** 여러 줄이 가리키는 이름들을 모은다. */
205
+ function collect(rows, field) {
206
+ return new Set(rows.flatMap(one => asList(one[field])));
207
+ }
208
+ /**
209
+ * **무엇을 몇 개 봤나.**
210
+ *
211
+ * 어긋남 0건이 「멀쩡하다」인지 「안 돌았다」인지는 이것으로만 갈린다. 본 수를 안 내면 두 답이
212
+ * 같은 글자로 나온다 — 검사기가 스스로를 못 믿게 만드는 가장 흔한 방식이다.
213
+ */
214
+ function scannedCounts(snapshot) {
215
+ return Object.entries(snapshot)
216
+ .map(([axis, rows]) => ({ axis, rows: rows.length }))
217
+ .sort((a, b) => a.axis.localeCompare(b.axis));
218
+ }
219
+ /** 축·종류별로 몇 건인지. 사람이 먼저 볼 것을 고르는 데 쓴다. */
220
+ function summarize(findings) {
221
+ const tally = new Map();
222
+ for (const one of findings) {
223
+ const key = `${one.axis}${one.kind}`;
224
+ tally.set(key, (tally.get(key) ?? 0) + 1);
225
+ }
226
+ return [...tally.entries()]
227
+ .map(([key, count]) => {
228
+ const [axis, kind] = key.split('');
229
+ return { axis, kind, count };
230
+ })
231
+ .sort((a, b) => b.count - a.count || a.axis.localeCompare(b.axis));
232
+ }
233
+ /**
234
+ * 한 도메인의 마스터를 통째로 읽어 잰다.
235
+ *
236
+ * **상한을 두지 않는다.** 정합성은 「전부 봤나」가 곧 답이라, 일부만 보고 「어긋남 0건」이라고 하면
237
+ * 그 답이 거짓이 된다. 그래서 이것은 목록 화면이 부르는 것이 아니라 **사람이 눌러서 도는 검사**다.
238
+ */
239
+ async function readMasterSnapshot(domain, getRepository, entities) {
240
+ const all = async (Entity, select) => (await getRepository(Entity).find({
241
+ where: { domain: { id: domain.id } },
242
+ select: ['id', 'name', ...select]
243
+ }));
244
+ const [persons, equipment, physicalAssets, materialDefinitions, operationDefinitions, routeDefinitions, recipeDefinitions, operationalLocations, stopReasons, testSpecifications, personnelClasses, equipmentClasses, physicalAssetClasses, materialClasses] = await Promise.all([
245
+ all(entities.Person, ['personnelClassIds', 'homeLocation', 'testSpecificationIds']),
246
+ all(entities.Equipment, ['kind', 'homeLocation', 'equipmentClassIds', 'testSpecificationIds']),
247
+ all(entities.PhysicalAsset, ['assetClassIds', 'homeLocation', 'testSpecificationIds']),
248
+ all(entities.MaterialDefinition, ['materialClassIds', 'testSpecificationIds']),
249
+ all(entities.OperationDefinition, ['intent', 'locationType', 'resourceType', 'duration']),
250
+ all(entities.RouteDefinition, ['steps']),
251
+ all(entities.RecipeDefinition, ['materialDefinitionName', 'route', 'inputs']),
252
+ all(entities.OperationalLocation, ['type', 'level', 'parentId']),
253
+ all(entities.StopReason, ['status', 'parentName']),
254
+ all(entities.TestSpecification, ['criteria']),
255
+ all(entities.PersonnelClass, ['baseIds']),
256
+ all(entities.EquipmentClass, ['baseIds']),
257
+ all(entities.PhysicalAssetClass, ['baseIds']),
258
+ all(entities.MaterialClass, ['baseIds'])
259
+ ]);
260
+ return {
261
+ persons, equipment, physicalAssets, materialDefinitions, operationDefinitions,
262
+ routeDefinitions, recipeDefinitions, operationalLocations, stopReasons, testSpecifications,
263
+ personnelClasses, equipmentClasses, physicalAssetClasses, materialClasses
264
+ };
265
+ }
266
+ //# sourceMappingURL=master-conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"master-conformance.js","sourceRoot":"","sources":["../../server/service/master-conformance.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 마스터가 **말이 되나** — 축을 가로질러 한 번에 본다.\n *\n * ── 왜 필요한가 ────────────────────────────────────────────────────────────\n * 축마다 화면이 있고 축마다 값이 차 있는데, 그 사이가 이어지는지는 아무도 안 봤다. 설비 등급 다섯이\n * 서 있고 설비 스물둘이 어느 등급에도 안 들어 있던 일이 그랬다 — 두 화면 다 멀쩡해 보였다.\n * 카메라 자산 다섯이 ECU 등급에 들어 있던 것도, 정지 사유 고르기가 빈 목록으로 보이던 것도 같다.\n *\n * 사람이 열두 화면을 오가며 맞춰 보는 것으로는 안 된다. 맞춰 보지 않으면 아무도 모르고, 맞춰 봤는지\n * 아닌지도 남지 않는다.\n *\n * ── 두 가지만 본다 ─────────────────────────────────────────────────────────\n * **비어 있으면 안 되는 칸**과 **가리키는데 없는 것**이다. 둘 다 사실 판정이라 다툼이 없다.\n * 「이 값이 옳은가」는 여기서 안 본다 — 그것은 현장이 정한다.\n *\n * ── 없는 것을 없다고 말한다 ────────────────────────────────────────────────\n * 표가 통째로 비었으면 그것도 낸다. 「빠진 것 0건」과 「아직 아무것도 안 세웠다」는 다르고, 세지\n * 않으면 둘이 같아 보인다.\n */\n\n/** 한 건의 어긋남. 사실만 담는다 — 무엇을, 어디서, 무엇이. */\nexport interface Finding {\n /** 어느 축인가. `person` · `equipment` · `recipeDefinition` … */\n axis: string\n /** 어느 줄인가. 표가 통째로 빈 경우에는 없다. */\n subject?: string\n /** `missing` = 비어 있으면 안 되는 칸이 비었다 · `dangling` = 가리키는데 그런 것이 없다 · `empty` = 표가 비었다 · `unused` = 아무도 안 가리킨다 */\n kind: 'missing' | 'dangling' | 'empty' | 'unused'\n /** 어느 칸인가(`missing`·`dangling`), 또는 무엇이 비었나(`empty`·`unused`). */\n field: string\n /** 가리키던 값. `dangling` 일 때만. */\n value?: string\n}\n\n/** 한 축이 내놓는 줄들. 이름과 칸 몇 개만 본다. */\nexport type Row = Record<string, any>\n\nexport interface MasterSnapshot {\n persons: Row[]\n equipment: Row[]\n physicalAssets: Row[]\n materialDefinitions: Row[]\n operationDefinitions: Row[]\n routeDefinitions: Row[]\n recipeDefinitions: Row[]\n operationalLocations: Row[]\n stopReasons: Row[]\n testSpecifications: Row[]\n personnelClasses: Row[]\n equipmentClasses: Row[]\n physicalAssetClasses: Row[]\n materialClasses: Row[]\n}\n\nconst nameSet = (rows: Row[]) => new Set(rows.map(one => one.name).filter(Boolean))\n\n/** 값이 비었나 — 빈 문자열과 빈 배열도 빈 것으로 본다. */\nfunction blank(value: any): boolean {\n if (value === null || value === undefined) {\n return true\n }\n if (Array.isArray(value)) {\n return value.length === 0\n }\n\n return String(value).trim() === ''\n}\n\n/** 이름 목록으로 만든다 — 한 개짜리 문자열도, 배열도 같게 다룬다. */\nfunction asList(value: any): string[] {\n if (blank(value)) {\n return []\n }\n\n return (Array.isArray(value) ? value : [value]).map(one => String(one).trim()).filter(Boolean)\n}\n\n/**\n * 축 하나를 잰다.\n *\n * `required` 는 비어 있으면 안 되는 칸, `refs` 는 「이 칸의 값이 저 이름들 안에 있어야 한다」이다.\n */\nfunction checkAxis(\n axis: string,\n rows: Row[],\n required: string[],\n refs: { field: string; within: Set<string> }[]\n): Finding[] {\n const found: Finding[] = []\n\n if (rows.length === 0) {\n /* 표가 통째로 비었다. 「빠진 것 0건」과 다르다. */\n return [{ axis, kind: 'empty', field: axis }]\n }\n\n for (const row of rows) {\n for (const field of required) {\n if (blank(row[field])) {\n found.push({ axis, subject: row.name, kind: 'missing', field })\n }\n }\n\n for (const { field, within } of refs) {\n for (const value of asList(row[field])) {\n if (!within.has(value)) {\n found.push({ axis, subject: row.name, kind: 'dangling', field, value })\n }\n }\n }\n }\n\n return found\n}\n\n/** 아무도 안 가리키는 것들 — 세워 놓고 쓰지 않는 선언. */\nfunction checkUnused(axis: string, rows: Row[], pointedAt: Set<string>, field: string): Finding[] {\n return rows\n .filter(one => one.name && !pointedAt.has(one.name))\n .map(one => ({ axis, subject: one.name, kind: 'unused' as const, field }))\n}\n\n/**\n * 마스터 전체를 잰다.\n *\n * **순서에 뜻이 없다.** 어느 축부터 보든 같은 답이 나와야 하고, 그래야 이 결과를 두 번 재서\n * 견줄 수 있다.\n */\nexport function checkMaster(snapshot: MasterSnapshot): Finding[] {\n const locations = nameSet(snapshot.operationalLocations)\n const operations = nameSet(snapshot.operationDefinitions)\n const routes = nameSet(snapshot.routeDefinitions)\n const materials = nameSet(snapshot.materialDefinitions)\n const specs = nameSet(snapshot.testSpecifications)\n const personnelClasses = nameSet(snapshot.personnelClasses)\n const equipmentClasses = nameSet(snapshot.equipmentClasses)\n const assetClasses = nameSet(snapshot.physicalAssetClasses)\n const materialClasses = nameSet(snapshot.materialClasses)\n const stopReasons = nameSet(snapshot.stopReasons)\n\n const found: Finding[] = [\n ...checkAxis('person', snapshot.persons, ['personnelClassIds', 'homeLocation'], [\n { field: 'personnelClassIds', within: personnelClasses },\n { field: 'homeLocation', within: locations },\n { field: 'testSpecificationIds', within: specs }\n ]),\n\n ...checkAxis('equipment', snapshot.equipment, ['kind', 'homeLocation', 'equipmentClassIds'], [\n { field: 'equipmentClassIds', within: equipmentClasses },\n { field: 'homeLocation', within: locations },\n { field: 'testSpecificationIds', within: specs }\n ]),\n\n ...checkAxis('physicalAsset', snapshot.physicalAssets, ['assetClassIds'], [\n { field: 'assetClassIds', within: assetClasses },\n { field: 'homeLocation', within: locations },\n { field: 'testSpecificationIds', within: specs }\n ]),\n\n ...checkAxis('materialDefinition', snapshot.materialDefinitions, ['materialClassIds'], [\n { field: 'materialClassIds', within: materialClasses },\n { field: 'testSpecificationIds', within: specs }\n ]),\n\n /*\n * 공정의 `resourceType` 은 설비 **종류**를 가리키는 값이라 이름 집합이 없다. 여기서는\n * 비었는지만 본다 — 없는 것을 있는 척 검사하지 않는다.\n */\n ...checkAxis('operationDefinition', snapshot.operationDefinitions, ['intent', 'locationType', 'duration'], []),\n\n ...checkAxis('routeDefinition', snapshot.routeDefinitions, ['steps'], [\n { field: 'steps', within: operations }\n ]),\n\n ...checkAxis('recipeDefinition', snapshot.recipeDefinitions, ['materialDefinitionName', 'route', 'inputs'], [\n { field: 'materialDefinitionName', within: materials },\n { field: 'route', within: routes }\n ]),\n\n ...checkAxis('operationalLocation', snapshot.operationalLocations, ['type', 'level'], [\n { field: 'parentId', within: locations }\n ]),\n\n ...checkAxis('stopReason', snapshot.stopReasons, ['status'], [{ field: 'parentName', within: stopReasons }]),\n\n ...checkAxis('testSpecification', snapshot.testSpecifications, ['criteria'], [])\n ]\n\n /*\n * 제조법의 투입은 한 줄이 여럿을 가리킨다. 위의 검사는 칸 하나를 보므로 여기서 따로 본다.\n */\n for (const recipe of snapshot.recipeDefinitions) {\n for (const part of recipe.inputs ?? []) {\n if (part?.material && !materials.has(part.material)) {\n found.push({ axis: 'recipeDefinition', subject: recipe.name, kind: 'dangling', field: 'inputs.material', value: part.material })\n }\n if (part?.operation && !operations.has(part.operation)) {\n found.push({ axis: 'recipeDefinition', subject: recipe.name, kind: 'dangling', field: 'inputs.operation', value: part.operation })\n }\n }\n }\n\n /*\n * ── 세워 놓고 아무도 안 든 등급 ─────────────────────────────────────────\n *\n * **상속을 타고 센다.** 등급은 등급을 상속하고(`baseIds`), 자격 판정도 그 사슬을 닫아서 본다\n * (커널의 `classClosure`). 그러니 「아무도 안 든다」도 닫힌 소속으로 물어야 한다.\n *\n * 직접 소속만 세면 뿌리 등급이 늘 걸린다. 품목의 유형 등급(완제품 · 반제품 · 원재료)이 그렇다 —\n * 품목은 성격 등급에 들고 그 등급이 유형을 상속하므로, 직접 소속은 언제나 0이다. 그것을 결함으로\n * 읽으면 멀쩡한 등급을 지우러 간다.\n *\n * 처음에는 품목만 따로 다뤘고 나머지 셋은 직접 소속으로 셌다. 아키텍트 레인이 설비 등급에도\n * 같은 축이 있다고 알려 주어 넷을 한 규칙으로 모았다 — 축마다 다르게 세면 한쪽만 고쳐지는 날이\n * 온다. [재봤음] 2026-09-04\n */\n const classAxes: [string, Row[], Row[], string][] = [\n ['personnelClass', snapshot.personnelClasses, snapshot.persons, 'personnelClassIds'],\n ['equipmentClass', snapshot.equipmentClasses, snapshot.equipment, 'equipmentClassIds'],\n ['physicalAssetClass', snapshot.physicalAssetClasses, snapshot.physicalAssets, 'assetClassIds'],\n ['materialClass', snapshot.materialClasses, snapshot.materialDefinitions, 'materialClassIds']\n ]\n\n for (const [axis, classes, members, field] of classAxes) {\n found.push(...checkUnused(axis, classes, closedMembership(classes, members, field), 'members'))\n }\n\n /* 아무도 안 가리키는 라우팅·공정. 만들어 놓고 안 쓰는 것은 지워도 되는 것인지 사람이 판단한다. */\n const routesUsed = new Set(snapshot.recipeDefinitions.map(one => one.route).filter(Boolean))\n const operationsUsed = new Set([\n ...snapshot.routeDefinitions.flatMap(one => asList(one.steps)),\n ...snapshot.recipeDefinitions.flatMap(one => (one.inputs ?? []).map((part: any) => part?.operation).filter(Boolean))\n ])\n\n found.push(\n ...checkUnused('routeDefinition', snapshot.routeDefinitions, routesUsed, 'usedByRecipes'),\n ...checkUnused('operationDefinition', snapshot.operationDefinitions, operationsUsed, 'usedInRoutes')\n )\n\n return found\n}\n\n/**\n * **닫힌 소속** — 소속이 상속을 타고 닿는 등급까지 모은다.\n *\n * 사람이 `welding-robot-6axis` 에 들고 그것이 `welding-equipment` 를 상속하면, 두 등급 다 「누가\n * 들었다」로 센다. 자격 판정이 그 사슬을 닫아서 보므로(커널의 `classClosure`) 여기서도 같게 본다.\n *\n * **고리를 밟으면 멈춘다.** `baseIds` 는 화면에서 손으로 넣을 수 있어 A→B→A 가 생길 수 있다.\n */\nfunction closedMembership(classes: Row[], members: Row[], field: string): Set<string> {\n const baseOf = new Map(classes.map(one => [one.name, asList(one.baseIds)]))\n const reached = new Set<string>()\n\n const walk = (name: string) => {\n if (!name || reached.has(name)) {\n return\n }\n reached.add(name)\n\n for (const base of baseOf.get(name) ?? []) {\n walk(base)\n }\n }\n\n for (const row of members) {\n for (const name of asList(row[field])) {\n walk(name)\n }\n }\n\n return reached\n}\n\n/** 여러 줄이 가리키는 이름들을 모은다. */\nfunction collect(rows: Row[], field: string): Set<string> {\n return new Set(rows.flatMap(one => asList(one[field])))\n}\n\n/**\n * **무엇을 몇 개 봤나.**\n *\n * 어긋남 0건이 「멀쩡하다」인지 「안 돌았다」인지는 이것으로만 갈린다. 본 수를 안 내면 두 답이\n * 같은 글자로 나온다 — 검사기가 스스로를 못 믿게 만드는 가장 흔한 방식이다.\n */\nexport function scannedCounts(snapshot: MasterSnapshot): { axis: string; rows: number }[] {\n return Object.entries(snapshot)\n .map(([axis, rows]) => ({ axis, rows: (rows as Row[]).length }))\n .sort((a, b) => a.axis.localeCompare(b.axis))\n}\n\n/** 축·종류별로 몇 건인지. 사람이 먼저 볼 것을 고르는 데 쓴다. */\nexport function summarize(findings: Finding[]): { axis: string; kind: string; count: number }[] {\n const tally = new Map<string, number>()\n\n for (const one of findings) {\n const key = `${one.axis}\u0000${one.kind}`\n tally.set(key, (tally.get(key) ?? 0) + 1)\n }\n\n return [...tally.entries()]\n .map(([key, count]) => {\n const [axis, kind] = key.split('\u0000')\n\n return { axis, kind, count }\n })\n .sort((a, b) => b.count - a.count || a.axis.localeCompare(b.axis))\n}\n\n/**\n * 한 도메인의 마스터를 통째로 읽어 잰다.\n *\n * **상한을 두지 않는다.** 정합성은 「전부 봤나」가 곧 답이라, 일부만 보고 「어긋남 0건」이라고 하면\n * 그 답이 거짓이 된다. 그래서 이것은 목록 화면이 부르는 것이 아니라 **사람이 눌러서 도는 검사**다.\n */\nexport async function readMasterSnapshot(domain: any, getRepository: any, entities: Record<string, any>): Promise<MasterSnapshot> {\n const all = async (Entity: any, select: string[]) =>\n (await getRepository(Entity).find({\n where: { domain: { id: domain.id } } as any,\n select: ['id', 'name', ...select] as any\n })) as Row[]\n\n const [\n persons, equipment, physicalAssets, materialDefinitions, operationDefinitions,\n routeDefinitions, recipeDefinitions, operationalLocations, stopReasons, testSpecifications,\n personnelClasses, equipmentClasses, physicalAssetClasses, materialClasses\n ] = await Promise.all([\n all(entities.Person, ['personnelClassIds', 'homeLocation', 'testSpecificationIds']),\n all(entities.Equipment, ['kind', 'homeLocation', 'equipmentClassIds', 'testSpecificationIds']),\n all(entities.PhysicalAsset, ['assetClassIds', 'homeLocation', 'testSpecificationIds']),\n all(entities.MaterialDefinition, ['materialClassIds', 'testSpecificationIds']),\n all(entities.OperationDefinition, ['intent', 'locationType', 'resourceType', 'duration']),\n all(entities.RouteDefinition, ['steps']),\n all(entities.RecipeDefinition, ['materialDefinitionName', 'route', 'inputs']),\n all(entities.OperationalLocation, ['type', 'level', 'parentId']),\n all(entities.StopReason, ['status', 'parentName']),\n all(entities.TestSpecification, ['criteria']),\n all(entities.PersonnelClass, ['baseIds']),\n all(entities.EquipmentClass, ['baseIds']),\n all(entities.PhysicalAssetClass, ['baseIds']),\n all(entities.MaterialClass, ['baseIds'])\n ])\n\n return {\n persons, equipment, physicalAssets, materialDefinitions, operationDefinitions,\n routeDefinitions, recipeDefinitions, operationalLocations, stopReasons, testSpecifications,\n personnelClasses, equipmentClasses, physicalAssetClasses, materialClasses\n }\n}\n"]}
@@ -0,0 +1,55 @@
1
+ import { EntityManager, ObjectLiteral } from 'typeorm';
2
+ import { Domain } from '@things-factory/shell';
3
+ /**
4
+ * 마스터를 채우고 고치는 **한 벌의 규칙** — 열두 축이 같은 함수를 쓴다.
5
+ *
6
+ * ── 왜 마스터는 그리드에서 고칠 수 있나 ────────────────────────────────────
7
+ * 업무 화면(실적 · 검사 · 처분)은 조회 전용이다. 그것은 **일어난 일의 기록**이라, 고칠 수 있으면
8
+ * 「그때 무엇이 있었나」가 「지금 무엇으로 적혀 있나」로 바뀐다.
9
+ *
10
+ * 마스터는 다르다. 「이 사람이 용접 자격을 갖는다」는 일어난 일이 아니라 **선언**이다. 선언은 바뀌고,
11
+ * 바뀐 것이 지금의 선언이다. 그래서 그리드에서 고친다.
12
+ *
13
+ * ── 지우는 것만 다르게 다룬다 ──────────────────────────────────────────────
14
+ * 유효 기간을 가진 축은 **행을 지우지 않는다.** 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다
15
+ * (어제 실적이 가리키던 설비가 사라지면 그 실적은 어느 설비의 것도 아니게 된다). 대신
16
+ * `effectiveEnd` 를 채워 오늘부터 유효하지 않게 한다.
17
+ *
18
+ * 유효 기간이 없는 축만 실제로 지운다.
19
+ */
20
+ /** 그리드가 보내는 표식. `+` 새로 만든 행 · `M` 고친 행 · `-` 지운 행. */
21
+ export type CuFlag = '+' | 'M' | '-';
22
+ export interface MasterPatch {
23
+ id?: string;
24
+ cuFlag?: string;
25
+ [key: string]: unknown;
26
+ }
27
+ type EntityClass = {
28
+ new (): ObjectLiteral;
29
+ };
30
+ export interface SaveMasterOptions {
31
+ /**
32
+ * **언제부터 그러한가** — 배정과 선언을 고칠 때.
33
+ *
34
+ * 안 주면 지금부터다. 미래면 주장만 남고 본행은 그 시각이 올 때까지 그대로다
35
+ * (§`claimAssignmentChanges`).
36
+ */
37
+ appliedAt?: Date;
38
+ /** 과거 시각일 때, **지연 기록인가 이미 적은 것의 정정인가.** 안 주면 지연 기록으로 본다. */
39
+ appliedKind?: 'change' | 'correction';
40
+ /** 정정이면 어느 구간까지인가. */
41
+ appliedUntil?: Date;
42
+ /**
43
+ * 유효 기간을 갖는 축인가.
44
+ *
45
+ * 참이면 지우기가 **`effectiveEnd` 를 채우는 것**이 된다. 거짓이면 행을 지운다.
46
+ */
47
+ hasEffectivePeriod?: boolean;
48
+ }
49
+ /**
50
+ * 그리드가 보낸 변경을 한 번에 적용한다.
51
+ *
52
+ * 한 트랜잭션에서 처리한다 — 절반만 반영되면 그리드가 보여 주는 것과 저장된 것이 갈린다.
53
+ */
54
+ export declare function saveMasterPatches(manager: EntityManager, domain: Domain, entity: EntityClass, patches: readonly MasterPatch[], user: unknown, options?: SaveMasterOptions): Promise<ObjectLiteral[]>;
55
+ export {};
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveMasterPatches = saveMasterPatches;
4
+ const typeorm_1 = require("typeorm");
5
+ const shell_1 = require("@things-factory/shell");
6
+ const master_axis_1 = require("./master-axis");
7
+ const master_change_policy_1 = require("./master-change-policy");
8
+ const assignment_write_1 = require("./assignment/assignment-write");
9
+ /**
10
+ * 그리드가 보낸 변경을 한 번에 적용한다.
11
+ *
12
+ * 한 트랜잭션에서 처리한다 — 절반만 반영되면 그리드가 보여 주는 것과 저장된 것이 갈린다.
13
+ */
14
+ async function saveMasterPatches(manager, domain, entity, patches, user, options = {}) {
15
+ const axis = master_axis_1.MASTER_AXES.find(axis => axis.entity === entity);
16
+ if (!axis)
17
+ throw new Error('saveMasterPatches: the entity must be a declared master axis');
18
+ await (0, master_change_policy_1.assertDirectMasterChange)(manager, domain.id, axis.key);
19
+ if (['recipeDefinition', 'materialDefinition'].includes(axis.key))
20
+ throw new shell_1.Refusal('REVISION_REQUIRED', { axis: axis.key }, 'Change this master through a revision draft, including non-regulated publication.');
21
+ const repository = manager.getRepository(entity);
22
+ const results = [];
23
+ const created = patches.filter(patch => flagOf(patch) === '+');
24
+ const updated = patches.filter(patch => flagOf(patch) === 'M');
25
+ const removed = patches.filter(patch => flagOf(patch) === '-');
26
+ for (const patch of created) {
27
+ /* 새 행의 `id` 는 그리드가 임시로 붙인 것이다 — 그대로 저장하면 그것이 진짜 키가 된다. */
28
+ const { cuFlag, id, ...values } = patch;
29
+ results.push(await repository.save({ ...values, domain, creator: user, updater: user }));
30
+ }
31
+ for (const patch of updated) {
32
+ const { cuFlag, id, ...values } = patch;
33
+ if (!id) {
34
+ throw new Error('saveMasterPatches: a changed row must carry its id');
35
+ }
36
+ const found = await repository.findOne({ where: { domain: { id: domain.id }, id } });
37
+ /*
38
+ * 없는 행을 고치라고 하면 만들지 않는다. 다른 사람이 지웠거나 다른 도메인의 행이고, 둘 다
39
+ * 조용히 새 행을 만들 일이 아니다.
40
+ */
41
+ if (!found) {
42
+ throw new Error(`saveMasterPatches: no such row to change — ${String(id)}`);
43
+ }
44
+ /*
45
+ * ── 배정과 선언은 **주장으로 남기고, 미래는 본행에 안 쓴다** ──────────────
46
+ *
47
+ * 세 칸(`equipment.homeLocation` · `operationalLocation.workShiftNames` · `parentId`)은 가동률
48
+ * 분모를 정한다. 그래서 「언제부터 그러한가」를 함께 받아 이력에 남긴다.
49
+ *
50
+ * **적용 시각이 미래면 본행을 안 건드린다.** 다음 달 이동을 지금 적었다고 다른 제품이 오늘부터
51
+ * 새 자리를 읽으면 안 된다 — 도래하면 `projectDueClaims` 가 옮긴다.
52
+ */
53
+ const scheduled = await (0, assignment_write_1.claimAssignmentChanges)(manager, domain, axis.key, found, values, user, options);
54
+ results.push(await repository.save({ ...found, ...values, ...scheduled.keepOnRow, updater: user }));
55
+ }
56
+ if (removed.length) {
57
+ await retire(repository, domain, removed, user, options);
58
+ }
59
+ return results;
60
+ }
61
+ /**
62
+ * 없앤다 — 유효 기간이 있으면 **끝을 채우고**, 없으면 지운다.
63
+ */
64
+ async function retire(repository, domain, removed, user, options) {
65
+ const ids = removed.map(patch => patch.id).filter(Boolean);
66
+ if (!ids.length) {
67
+ return;
68
+ }
69
+ if (!options.hasEffectivePeriod) {
70
+ await repository.delete({ domain: { id: domain.id }, id: (0, typeorm_1.In)(ids) });
71
+ return;
72
+ }
73
+ const rows = await repository.find({ where: { domain: { id: domain.id }, id: (0, typeorm_1.In)(ids) } });
74
+ const now = new Date();
75
+ for (const row of rows) {
76
+ /*
77
+ * 이미 끝이 적혀 있으면 그대로 둔다. 다시 오늘로 바꾸면 「언제부터 안 썼나」가 바뀐다.
78
+ */
79
+ if (row.effectiveEnd) {
80
+ continue;
81
+ }
82
+ await repository.save({ ...row, effectiveEnd: now, updater: user });
83
+ }
84
+ }
85
+ function flagOf(patch) {
86
+ const flag = String(patch.cuFlag ?? '').toUpperCase();
87
+ if (flag === '+' || flag === 'M' || flag === '-') {
88
+ return flag;
89
+ }
90
+ /* 표식이 없으면 고침으로 본다 — 그리드가 표식을 안 붙이는 경우가 있고, 만드는 쪽으로 두면 행이 늘어난다. */
91
+ return 'M';
92
+ }
93
+ //# sourceMappingURL=master-crud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"master-crud.js","sourceRoot":"","sources":["../../server/service/master-crud.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager, In, ObjectLiteral, Repository } from 'typeorm'\n\nimport { Domain, Refusal } from '@things-factory/shell'\nimport { MASTER_AXES } from './master-axis'\nimport { assertDirectMasterChange } from './master-change-policy'\nimport { claimAssignmentChanges } from './assignment/assignment-write'\n\n/**\n * 마스터를 채우고 고치는 **한 벌의 규칙** — 열두 축이 같은 함수를 쓴다.\n *\n * ── 왜 마스터는 그리드에서 고칠 수 있나 ────────────────────────────────────\n * 업무 화면(실적 · 검사 · 처분)은 조회 전용이다. 그것은 **일어난 일의 기록**이라, 고칠 수 있으면\n * 「그때 무엇이 있었나」가 「지금 무엇으로 적혀 있나」로 바뀐다.\n *\n * 마스터는 다르다. 「이 사람이 용접 자격을 갖는다」는 일어난 일이 아니라 **선언**이다. 선언은 바뀌고,\n * 바뀐 것이 지금의 선언이다. 그래서 그리드에서 고친다.\n *\n * ── 지우는 것만 다르게 다룬다 ──────────────────────────────────────────────\n * 유효 기간을 가진 축은 **행을 지우지 않는다.** 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다\n * (어제 실적이 가리키던 설비가 사라지면 그 실적은 어느 설비의 것도 아니게 된다). 대신\n * `effectiveEnd` 를 채워 오늘부터 유효하지 않게 한다.\n *\n * 유효 기간이 없는 축만 실제로 지운다.\n */\n\n/** 그리드가 보내는 표식. `+` 새로 만든 행 · `M` 고친 행 · `-` 지운 행. */\nexport type CuFlag = '+' | 'M' | '-'\n\nexport interface MasterPatch {\n id?: string\n cuFlag?: string\n [key: string]: unknown\n}\n\ntype EntityClass = { new (): ObjectLiteral }\n\nexport interface SaveMasterOptions {\n /**\n * **언제부터 그러한가** — 배정과 선언을 고칠 때.\n *\n * 안 주면 지금부터다. 미래면 주장만 남고 본행은 그 시각이 올 때까지 그대로다\n * (§`claimAssignmentChanges`).\n */\n appliedAt?: Date\n /** 과거 시각일 때, **지연 기록인가 이미 적은 것의 정정인가.** 안 주면 지연 기록으로 본다. */\n appliedKind?: 'change' | 'correction'\n /** 정정이면 어느 구간까지인가. */\n appliedUntil?: Date\n /**\n * 유효 기간을 갖는 축인가.\n *\n * 참이면 지우기가 **`effectiveEnd` 를 채우는 것**이 된다. 거짓이면 행을 지운다.\n */\n hasEffectivePeriod?: boolean\n}\n\n/**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 한 트랜잭션에서 처리한다 — 절반만 반영되면 그리드가 보여 주는 것과 저장된 것이 갈린다.\n */\nexport async function saveMasterPatches(\n manager: EntityManager,\n domain: Domain,\n entity: EntityClass,\n patches: readonly MasterPatch[],\n user: unknown,\n options: SaveMasterOptions = {}\n): Promise<ObjectLiteral[]> {\n const axis = MASTER_AXES.find(axis => axis.entity === entity)\n if (!axis) throw new Error('saveMasterPatches: the entity must be a declared master axis')\n await assertDirectMasterChange(manager, domain.id, axis.key)\n if (['recipeDefinition', 'materialDefinition'].includes(axis.key))\n throw new Refusal('REVISION_REQUIRED', { axis: axis.key }, 'Change this master through a revision draft, including non-regulated publication.')\n const repository = manager.getRepository(entity)\n const results: ObjectLiteral[] = []\n\n const created = patches.filter(patch => flagOf(patch) === '+')\n const updated = patches.filter(patch => flagOf(patch) === 'M')\n const removed = patches.filter(patch => flagOf(patch) === '-')\n\n for (const patch of created) {\n /* 새 행의 `id` 는 그리드가 임시로 붙인 것이다 — 그대로 저장하면 그것이 진짜 키가 된다. */\n const { cuFlag, id, ...values } = patch\n\n results.push(await repository.save({ ...values, domain, creator: user, updater: user }))\n }\n\n for (const patch of updated) {\n const { cuFlag, id, ...values } = patch\n\n if (!id) {\n throw new Error('saveMasterPatches: a changed row must carry its id')\n }\n\n const found = await repository.findOne({ where: { domain: { id: domain.id }, id } })\n\n /*\n * 없는 행을 고치라고 하면 만들지 않는다. 다른 사람이 지웠거나 다른 도메인의 행이고, 둘 다\n * 조용히 새 행을 만들 일이 아니다.\n */\n if (!found) {\n throw new Error(`saveMasterPatches: no such row to change — ${String(id)}`)\n }\n\n /*\n * ── 배정과 선언은 **주장으로 남기고, 미래는 본행에 안 쓴다** ──────────────\n *\n * 세 칸(`equipment.homeLocation` · `operationalLocation.workShiftNames` · `parentId`)은 가동률\n * 분모를 정한다. 그래서 「언제부터 그러한가」를 함께 받아 이력에 남긴다.\n *\n * **적용 시각이 미래면 본행을 안 건드린다.** 다음 달 이동을 지금 적었다고 다른 제품이 오늘부터\n * 새 자리를 읽으면 안 된다 — 도래하면 `projectDueClaims` 가 옮긴다.\n */\n const scheduled = await claimAssignmentChanges(manager, domain, axis.key, found, values, user, options)\n\n results.push(await repository.save({ ...found, ...values, ...scheduled.keepOnRow, updater: user }))\n }\n\n if (removed.length) {\n await retire(repository, domain, removed, user, options)\n }\n\n return results\n}\n\n/**\n * 없앤다 — 유효 기간이 있으면 **끝을 채우고**, 없으면 지운다.\n */\nasync function retire(\n repository: Repository<ObjectLiteral>,\n domain: Domain,\n removed: readonly MasterPatch[],\n user: unknown,\n options: SaveMasterOptions\n): Promise<void> {\n const ids = removed.map(patch => patch.id).filter(Boolean) as string[]\n\n if (!ids.length) {\n return\n }\n\n if (!options.hasEffectivePeriod) {\n await repository.delete({ domain: { id: domain.id }, id: In(ids) })\n return\n }\n\n const rows = await repository.find({ where: { domain: { id: domain.id }, id: In(ids) } })\n const now = new Date()\n\n for (const row of rows) {\n /*\n * 이미 끝이 적혀 있으면 그대로 둔다. 다시 오늘로 바꾸면 「언제부터 안 썼나」가 바뀐다.\n */\n if (row.effectiveEnd) {\n continue\n }\n\n await repository.save({ ...row, effectiveEnd: now, updater: user })\n }\n}\n\nfunction flagOf(patch: MasterPatch): CuFlag {\n const flag = String(patch.cuFlag ?? '').toUpperCase()\n\n if (flag === '+' || flag === 'M' || flag === '-') {\n return flag\n }\n\n /* 표식이 없으면 고침으로 본다 — 그리드가 표식을 안 붙이는 경우가 있고, 만드는 쪽으로 두면 행이 늘어난다. */\n return 'M'\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { ObjectLiteral } from 'typeorm';
2
+ import { Domain, ListParam } from '@things-factory/shell';
3
+ /**
4
+ * 마스터 한 축을 목록으로 읽는다 — **열두 축이 같은 함수를 쓴다.**
5
+ *
6
+ * 총 건수를 함께 낸다. 화면이 「몇 건 중 몇 건을 보고 있나」를 말하려면 그 값이 있어야 하고, 없으면
7
+ * 잘린 목록과 「이게 전부」를 구별할 수 없다.
8
+ */
9
+ export declare function listMaster(axisKey: string, params: ListParam, domain: Domain): Promise<{
10
+ items: ObjectLiteral[];
11
+ total: number;
12
+ }>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listMaster = listMaster;
4
+ const shell_1 = require("@things-factory/shell");
5
+ const master_axis_1 = require("./master-axis");
6
+ const recipe_effective_list_1 = require("./recipe/recipe-effective-list");
7
+ const material_effective_list_1 = require("./material/material-effective-list");
8
+ /**
9
+ * 마스터 한 축을 목록으로 읽는다 — **열두 축이 같은 함수를 쓴다.**
10
+ *
11
+ * 총 건수를 함께 낸다. 화면이 「몇 건 중 몇 건을 보고 있나」를 말하려면 그 값이 있어야 하고, 없으면
12
+ * 잘린 목록과 「이게 전부」를 구별할 수 없다.
13
+ */
14
+ async function listMaster(axisKey, params, domain) {
15
+ const axis = (0, master_axis_1.masterAxisOf)(axisKey);
16
+ if (axisKey === 'recipeDefinition')
17
+ return (0, recipe_effective_list_1.listEffectiveRecipes)((0, shell_1.getRepository)(axis.entity).manager, domain, params);
18
+ if (axisKey === 'materialDefinition')
19
+ return (0, material_effective_list_1.listEffectiveMaterialDefinitions)((0, shell_1.getRepository)(axis.entity).manager, domain, params);
20
+ const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({
21
+ repository: (0, shell_1.getRepository)(axis.entity),
22
+ params,
23
+ domain,
24
+ searchables: axis.searchables,
25
+ alias: 'm'
26
+ });
27
+ const [items, total] = await queryBuilder.getManyAndCount();
28
+ return { items, total };
29
+ }
30
+ //# sourceMappingURL=master-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"master-list.js","sourceRoot":"","sources":["../../server/service/master-list.ts"],"names":[],"mappings":";;AAcA,gCAoBC;AAhCD,iDAAuG;AAEvG,+CAA4C;AAC5C,0EAAqE;AACrE,gFAAqF;AAErF;;;;;GAKG;AACI,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,MAAiB,EACjB,MAAc;IAEd,MAAM,IAAI,GAAG,IAAA,0BAAY,EAAC,OAAO,CAAC,CAAA;IAClC,IAAI,OAAO,KAAK,kBAAkB;QAAE,OAAO,IAAA,4CAAoB,EAAC,IAAA,qBAAa,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnH,IAAI,OAAO,KAAK,oBAAoB;QAAE,OAAO,IAAA,0DAAgC,EAAC,IAAA,qBAAa,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAEjI,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;QACjD,UAAU,EAAE,IAAA,qBAAa,EAAC,IAAI,CAAC,MAAM,CAAC;QACtC,MAAM;QACN,MAAM;QACN,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,KAAK,EAAE,GAAG;KACX,CAAC,CAAA;IAEF,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAA;IAE3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AACzB,CAAC","sourcesContent":["import { ObjectLiteral } from 'typeorm'\n\nimport { Domain, ListParam, getQueryBuilderFromListParams, getRepository } from '@things-factory/shell'\n\nimport { masterAxisOf } from './master-axis'\nimport { listEffectiveRecipes } from './recipe/recipe-effective-list'\nimport { listEffectiveMaterialDefinitions } from './material/material-effective-list'\n\n/**\n * 마스터 한 축을 목록으로 읽는다 — **열두 축이 같은 함수를 쓴다.**\n *\n * 총 건수를 함께 낸다. 화면이 「몇 건 중 몇 건을 보고 있나」를 말하려면 그 값이 있어야 하고, 없으면\n * 잘린 목록과 「이게 전부」를 구별할 수 없다.\n */\nexport async function listMaster(\n axisKey: string,\n params: ListParam,\n domain: Domain\n): Promise<{ items: ObjectLiteral[]; total: number }> {\n const axis = masterAxisOf(axisKey)\n if (axisKey === 'recipeDefinition') return listEffectiveRecipes(getRepository(axis.entity).manager, domain, params)\n if (axisKey === 'materialDefinition') return listEffectiveMaterialDefinitions(getRepository(axis.entity).manager, domain, params)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(axis.entity),\n params,\n domain,\n searchables: axis.searchables,\n alias: 'm'\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n}\n"]}
@@ -0,0 +1,33 @@
1
+ import { Domain } from '@things-factory/shell';
2
+ import type { Page, PageRequest } from './master-page';
3
+ /**
4
+ * 마스터 한 축을 **나눠 읽는다** — 저장소 쪽. 판단은 `master-page` 가 한다.
5
+ *
6
+ * ═══════════════════════════════════════════════════════════════════════════
7
+ * ── 등급은 매 쪽에 통째로 싣는다 ───────────────────────────────────────────
8
+ * 이 축들은 구성원이 자기 **등급을 이름으로 가리킨다.** 등급과 구성원을 따로 나눠 보내면 구성원이
9
+ * 먼저 도착하고 등급이 나중에 오는 순간이 생기고, 그 순간 받는 쪽은 **없는 등급을 가리키는 구성원**을
10
+ * 갖는다. 원래 이 조회들이 「자르지 않는다」고 적어 둔 이유가 그것이다.
11
+ *
12
+ * 그래서 **구성원만 나누고 등급은 매 쪽에 전부 싣는다.** 등급은 수십 단위라 실어도 크지 않고, 그러면
13
+ * 어느 쪽을 먼저 받아도 가리키는 곳이 항상 있다.
14
+ *
15
+ * ── 이름 다음부터 읽는다 ───────────────────────────────────────────────────
16
+ * `skip` 은 규모에서 못 쓴다 — 건너뛴 만큼을 매번 다시 읽는다. 이 축들은 이미 이름으로 정렬해 내므로
17
+ * **마지막 이름 다음부터** 읽으면 건너뛸 것이 없다.
18
+ * ═══════════════════════════════════════════════════════════════════════════
19
+ */
20
+ /**
21
+ * 한 축을 한 쪽만큼 읽는다.
22
+ *
23
+ * 이름 칸을 받는 이유: 축마다 다르다(`name` · `operationKey` …). 여기서 알아보려 하면 축이 늘 때마다
24
+ * 이 함수를 고쳐야 한다.
25
+ */
26
+ export declare function pullPage<T>(entity: any, domain: Domain, request: PageRequest, nameColumn?: keyof T & string): Promise<Page<T>>;
27
+ /**
28
+ * **통째로 달라고 했는데 너무 크면 던진다.**
29
+ *
30
+ * 자르고 넘어가지 않는다 — 받는 쪽은 그것이 전부인 줄 알고 트윈을 세우고, 없는 품목이 화면에서 그냥
31
+ * 존재하지 않게 된다. 오류가 안 난다. 그래서 **틀린 답 대신 오류**를 준다.
32
+ */
33
+ export declare function refuseIfTooLarge(axis: string, request: PageRequest, page: Page<unknown>): void;