@things-factory/ops-master 10.1.248 → 10.1.249
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.
- package/dist-client/bootstrap.d.ts +19 -0
- package/dist-client/bootstrap.js +66 -0
- package/dist-client/bootstrap.js.map +1 -0
- package/dist-client/index.d.ts +17 -0
- package/dist-client/index.js +21 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/master-change-approval.d.ts +14 -0
- package/dist-client/master-change-approval.js +36 -0
- package/dist-client/master-change-approval.js.map +1 -0
- package/dist-client/master-change-policy-axes.d.ts +37 -0
- package/dist-client/master-change-policy-axes.js +29 -0
- package/dist-client/master-change-policy-axes.js.map +1 -0
- package/dist-client/master-change-policy-panel.d.ts +59 -0
- package/dist-client/master-change-policy-panel.js +454 -0
- package/dist-client/master-change-policy-panel.js.map +1 -0
- package/dist-client/master-change-providers.d.ts +4 -0
- package/dist-client/master-change-providers.js +91 -0
- package/dist-client/master-change-providers.js.map +1 -0
- package/dist-client/pages/master/applied-when-dialog.d.ts +48 -0
- package/dist-client/pages/master/applied-when-dialog.js +137 -0
- package/dist-client/pages/master/applied-when-dialog.js.map +1 -0
- package/dist-client/pages/master/assignment-fields.d.ts +27 -0
- package/dist-client/pages/master/assignment-fields.js +62 -0
- package/dist-client/pages/master/assignment-fields.js.map +1 -0
- package/dist-client/pages/master/equipment-class.d.ts +12 -0
- package/dist-client/pages/master/equipment-class.js +42 -0
- package/dist-client/pages/master/equipment-class.js.map +1 -0
- package/dist-client/pages/master/equipment.d.ts +12 -0
- package/dist-client/pages/master/equipment.js +58 -0
- package/dist-client/pages/master/equipment.js.map +1 -0
- package/dist-client/pages/master/grist-iso-duration.d.ts +20 -0
- package/dist-client/pages/master/grist-iso-duration.js +70 -0
- package/dist-client/pages/master/grist-iso-duration.js.map +1 -0
- package/dist-client/pages/master/grist-reference.d.ts +91 -0
- package/dist-client/pages/master/grist-reference.js +419 -0
- package/dist-client/pages/master/grist-reference.js.map +1 -0
- package/dist-client/pages/master/import-rows.d.ts +35 -0
- package/dist-client/pages/master/import-rows.js +66 -0
- package/dist-client/pages/master/import-rows.js.map +1 -0
- package/dist-client/pages/master/iso-duration.d.ts +34 -0
- package/dist-client/pages/master/iso-duration.js +76 -0
- package/dist-client/pages/master/iso-duration.js.map +1 -0
- package/dist-client/pages/master/master-options.d.ts +40 -0
- package/dist-client/pages/master/master-options.js +54 -0
- package/dist-client/pages/master/master-options.js.map +1 -0
- package/dist-client/pages/master/master-page-base.d.ts +369 -0
- package/dist-client/pages/master/master-page-base.js +657 -0
- package/dist-client/pages/master/master-page-base.js.map +1 -0
- package/dist-client/pages/master/material-class.d.ts +12 -0
- package/dist-client/pages/master/material-class.js +42 -0
- package/dist-client/pages/master/material-class.js.map +1 -0
- package/dist-client/pages/master/material-definition.d.ts +5 -0
- package/dist-client/pages/master/material-definition.js +14 -0
- package/dist-client/pages/master/material-definition.js.map +1 -0
- package/dist-client/pages/master/material-revision-fields.d.ts +2 -0
- package/dist-client/pages/master/material-revision-fields.js +43 -0
- package/dist-client/pages/master/material-revision-fields.js.map +1 -0
- package/dist-client/pages/master/operation-definition.d.ts +12 -0
- package/dist-client/pages/master/operation-definition.js +49 -0
- package/dist-client/pages/master/operation-definition.js.map +1 -0
- package/dist-client/pages/master/operational-location.d.ts +84 -0
- package/dist-client/pages/master/operational-location.js +432 -0
- package/dist-client/pages/master/operational-location.js.map +1 -0
- package/dist-client/pages/master/person.d.ts +12 -0
- package/dist-client/pages/master/person.js +41 -0
- package/dist-client/pages/master/person.js.map +1 -0
- package/dist-client/pages/master/personnel-class.d.ts +12 -0
- package/dist-client/pages/master/personnel-class.js +43 -0
- package/dist-client/pages/master/personnel-class.js.map +1 -0
- package/dist-client/pages/master/physical-asset-class.d.ts +12 -0
- package/dist-client/pages/master/physical-asset-class.js +40 -0
- package/dist-client/pages/master/physical-asset-class.js.map +1 -0
- package/dist-client/pages/master/physical-asset.d.ts +12 -0
- package/dist-client/pages/master/physical-asset.js +41 -0
- package/dist-client/pages/master/physical-asset.js.map +1 -0
- package/dist-client/pages/master/recipe-definition.d.ts +5 -0
- package/dist-client/pages/master/recipe-definition.js +14 -0
- package/dist-client/pages/master/recipe-definition.js.map +1 -0
- package/dist-client/pages/master/reference-targets.d.ts +42 -0
- package/dist-client/pages/master/reference-targets.js +82 -0
- package/dist-client/pages/master/reference-targets.js.map +1 -0
- package/dist-client/pages/master/revision-comparison.d.ts +49 -0
- package/dist-client/pages/master/revision-comparison.js +560 -0
- package/dist-client/pages/master/revision-comparison.js.map +1 -0
- package/dist-client/pages/master/revision-view.d.ts +34 -0
- package/dist-client/pages/master/revision-view.js +145 -0
- package/dist-client/pages/master/revision-view.js.map +1 -0
- package/dist-client/pages/master/revision-workspace.d.ts +50 -0
- package/dist-client/pages/master/revision-workspace.js +763 -0
- package/dist-client/pages/master/revision-workspace.js.map +1 -0
- package/dist-client/pages/master/route-definition.d.ts +19 -0
- package/dist-client/pages/master/route-definition.js +40 -0
- package/dist-client/pages/master/route-definition.js.map +1 -0
- package/dist-client/pages/master/stop-reason.d.ts +12 -0
- package/dist-client/pages/master/stop-reason.js +48 -0
- package/dist-client/pages/master/stop-reason.js.map +1 -0
- package/dist-client/pages/master/test-specification.d.ts +5 -0
- package/dist-client/pages/master/test-specification.js +14 -0
- package/dist-client/pages/master/test-specification.js.map +1 -0
- package/dist-client/pages/master-axes.d.ts +24 -0
- package/dist-client/pages/master-axes.js +39 -0
- package/dist-client/pages/master-axes.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +81 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +19 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/service/ai-entry/master-entry-rules.d.ts +175 -0
- package/dist-server/service/ai-entry/master-entry-rules.js +302 -0
- package/dist-server/service/ai-entry/master-entry-rules.js.map +1 -0
- package/dist-server/service/ai-entry/master-entry-targets.d.ts +23 -0
- package/dist-server/service/ai-entry/master-entry-targets.js +293 -0
- package/dist-server/service/ai-entry/master-entry-targets.js.map +1 -0
- package/dist-server/service/approval-route.d.ts +37 -0
- package/dist-server/service/approval-route.js +34 -0
- package/dist-server/service/approval-route.js.map +1 -0
- package/dist-server/service/asset/asset-lifecycle.d.ts +106 -0
- package/dist-server/service/asset/asset-lifecycle.js +126 -0
- package/dist-server/service/asset/asset-lifecycle.js.map +1 -0
- package/dist-server/service/asset/asset-master-resolver.d.ts +53 -0
- package/dist-server/service/asset/asset-master-resolver.js +185 -0
- package/dist-server/service/asset/asset-master-resolver.js.map +1 -0
- package/dist-server/service/asset/asset-master.d.ts +21 -0
- package/dist-server/service/asset/asset-master.js +25 -0
- package/dist-server/service/asset/asset-master.js.map +1 -0
- package/dist-server/service/asset/asset-query.d.ts +16 -0
- package/dist-server/service/asset/asset-query.js +72 -0
- package/dist-server/service/asset/asset-query.js.map +1 -0
- package/dist-server/service/asset/index.d.ts +6 -0
- package/dist-server/service/asset/index.js +10 -0
- package/dist-server/service/asset/index.js.map +1 -0
- package/dist-server/service/asset/physical-asset-class.d.ts +34 -0
- package/dist-server/service/asset/physical-asset-class.js +104 -0
- package/dist-server/service/asset/physical-asset-class.js.map +1 -0
- package/dist-server/service/asset/physical-asset.d.ts +66 -0
- package/dist-server/service/asset/physical-asset.js +123 -0
- package/dist-server/service/asset/physical-asset.js.map +1 -0
- package/dist-server/service/assignment/applied-when.d.ts +24 -0
- package/dist-server/service/assignment/applied-when.js +16 -0
- package/dist-server/service/assignment/applied-when.js.map +1 -0
- package/dist-server/service/assignment/assignment-history.d.ts +92 -0
- package/dist-server/service/assignment/assignment-history.js +289 -0
- package/dist-server/service/assignment/assignment-history.js.map +1 -0
- package/dist-server/service/assignment/assignment-write.d.ts +42 -0
- package/dist-server/service/assignment/assignment-write.js +101 -0
- package/dist-server/service/assignment/assignment-write.js.map +1 -0
- package/dist-server/service/assignment/master-value-claim.d.ts +135 -0
- package/dist-server/service/assignment/master-value-claim.js +174 -0
- package/dist-server/service/assignment/master-value-claim.js.map +1 -0
- package/dist-server/service/equipment/equipment-class.d.ts +34 -0
- package/dist-server/service/equipment/equipment-class.js +104 -0
- package/dist-server/service/equipment/equipment-class.js.map +1 -0
- package/dist-server/service/equipment/equipment-master-resolver.d.ts +77 -0
- package/dist-server/service/equipment/equipment-master-resolver.js +266 -0
- package/dist-server/service/equipment/equipment-master-resolver.js.map +1 -0
- package/dist-server/service/equipment/equipment-master.d.ts +30 -0
- package/dist-server/service/equipment/equipment-master.js +53 -0
- package/dist-server/service/equipment/equipment-master.js.map +1 -0
- package/dist-server/service/equipment/equipment-query.d.ts +16 -0
- package/dist-server/service/equipment/equipment-query.js +72 -0
- package/dist-server/service/equipment/equipment-query.js.map +1 -0
- package/dist-server/service/equipment/equipment.d.ts +71 -0
- package/dist-server/service/equipment/equipment.js +138 -0
- package/dist-server/service/equipment/equipment.js.map +1 -0
- package/dist-server/service/equipment/index.d.ts +8 -0
- package/dist-server/service/equipment/index.js +12 -0
- package/dist-server/service/equipment/index.js.map +1 -0
- package/dist-server/service/equipment/state-period-rules.d.ts +95 -0
- package/dist-server/service/equipment/state-period-rules.js +122 -0
- package/dist-server/service/equipment/state-period-rules.js.map +1 -0
- package/dist-server/service/equipment/stop-reason-query.d.ts +11 -0
- package/dist-server/service/equipment/stop-reason-query.js +39 -0
- package/dist-server/service/equipment/stop-reason-query.js.map +1 -0
- package/dist-server/service/equipment/stop-reason.d.ts +58 -0
- package/dist-server/service/equipment/stop-reason.js +114 -0
- package/dist-server/service/equipment/stop-reason.js.map +1 -0
- package/dist-server/service/index.d.ts +82 -0
- package/dist-server/service/index.js +145 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/location/index.d.ts +5 -0
- package/dist-server/service/location/index.js +9 -0
- package/dist-server/service/location/index.js.map +1 -0
- package/dist-server/service/location/location-master-resolver.d.ts +60 -0
- package/dist-server/service/location/location-master-resolver.js +313 -0
- package/dist-server/service/location/location-master-resolver.js.map +1 -0
- package/dist-server/service/location/location-master.d.ts +26 -0
- package/dist-server/service/location/location-master.js +28 -0
- package/dist-server/service/location/location-master.js.map +1 -0
- package/dist-server/service/location/location-query.d.ts +15 -0
- package/dist-server/service/location/location-query.js +56 -0
- package/dist-server/service/location/location-query.js.map +1 -0
- package/dist-server/service/location/operational-location.d.ts +116 -0
- package/dist-server/service/location/operational-location.js +157 -0
- package/dist-server/service/location/operational-location.js.map +1 -0
- package/dist-server/service/master-axis.d.ts +40 -0
- package/dist-server/service/master-axis.js +57 -0
- package/dist-server/service/master-axis.js.map +1 -0
- package/dist-server/service/master-change-approval/approval-input.d.ts +17 -0
- package/dist-server/service/master-change-approval/approval-input.js +35 -0
- package/dist-server/service/master-change-approval/approval-input.js.map +1 -0
- package/dist-server/service/master-change-approval/builtin-axes.d.ts +4 -0
- package/dist-server/service/master-change-approval/builtin-axes.js +96 -0
- package/dist-server/service/master-change-approval/builtin-axes.js.map +1 -0
- package/dist-server/service/master-change-approval/index.d.ts +14 -0
- package/dist-server/service/master-change-approval/index.js +37 -0
- package/dist-server/service/master-change-approval/index.js.map +1 -0
- package/dist-server/service/master-change-approval/master-change-axis.d.ts +54 -0
- package/dist-server/service/master-change-approval/master-change-axis.js +17 -0
- package/dist-server/service/master-change-approval/master-change-axis.js.map +1 -0
- package/dist-server/service/master-change-approval/master-change-flow.d.ts +65 -0
- package/dist-server/service/master-change-approval/master-change-flow.js +125 -0
- package/dist-server/service/master-change-approval/master-change-flow.js.map +1 -0
- package/dist-server/service/master-change-approval/master-change-resolver.d.ts +18 -0
- package/dist-server/service/master-change-approval/master-change-resolver.js +58 -0
- package/dist-server/service/master-change-approval/master-change-resolver.js.map +1 -0
- package/dist-server/service/master-change-policy.d.ts +122 -0
- package/dist-server/service/master-change-policy.js +304 -0
- package/dist-server/service/master-change-policy.js.map +1 -0
- package/dist-server/service/master-conformance-resolver.d.ts +34 -0
- package/dist-server/service/master-conformance-resolver.js +153 -0
- package/dist-server/service/master-conformance-resolver.js.map +1 -0
- package/dist-server/service/master-conformance.d.ts +80 -0
- package/dist-server/service/master-conformance.js +266 -0
- package/dist-server/service/master-conformance.js.map +1 -0
- package/dist-server/service/master-crud.d.ts +55 -0
- package/dist-server/service/master-crud.js +93 -0
- package/dist-server/service/master-crud.js.map +1 -0
- package/dist-server/service/master-list.d.ts +12 -0
- package/dist-server/service/master-list.js +30 -0
- package/dist-server/service/master-list.js.map +1 -0
- package/dist-server/service/master-page-query.d.ts +33 -0
- package/dist-server/service/master-page-query.js +55 -0
- package/dist-server/service/master-page-query.js.map +1 -0
- package/dist-server/service/master-page.d.ts +85 -0
- package/dist-server/service/master-page.js +104 -0
- package/dist-server/service/master-page.js.map +1 -0
- package/dist-server/service/material/index.d.ts +7 -0
- package/dist-server/service/material/index.js +12 -0
- package/dist-server/service/material/index.js.map +1 -0
- package/dist-server/service/material/material-axis-status.d.ts +8 -0
- package/dist-server/service/material/material-axis-status.js +19 -0
- package/dist-server/service/material/material-axis-status.js.map +1 -0
- package/dist-server/service/material/material-class.d.ts +34 -0
- package/dist-server/service/material/material-class.js +104 -0
- package/dist-server/service/material/material-class.js.map +1 -0
- package/dist-server/service/material/material-definition.d.ts +45 -0
- package/dist-server/service/material/material-definition.js +125 -0
- package/dist-server/service/material/material-definition.js.map +1 -0
- package/dist-server/service/material/material-effective-list.d.ts +39 -0
- package/dist-server/service/material/material-effective-list.js +54 -0
- package/dist-server/service/material/material-effective-list.js.map +1 -0
- package/dist-server/service/material/material-master-resolver.d.ts +106 -0
- package/dist-server/service/material/material-master-resolver.js +351 -0
- package/dist-server/service/material/material-master-resolver.js.map +1 -0
- package/dist-server/service/material/material-master.d.ts +9 -0
- package/dist-server/service/material/material-master.js +24 -0
- package/dist-server/service/material/material-master.js.map +1 -0
- package/dist-server/service/material/material-query.d.ts +16 -0
- package/dist-server/service/material/material-query.js +79 -0
- package/dist-server/service/material/material-query.js.map +1 -0
- package/dist-server/service/material/material-revision-content.d.ts +10 -0
- package/dist-server/service/material/material-revision-content.js +92 -0
- package/dist-server/service/material/material-revision-content.js.map +1 -0
- package/dist-server/service/material/material-revision-resolver.d.ts +60 -0
- package/dist-server/service/material/material-revision-resolver.js +96 -0
- package/dist-server/service/material/material-revision-resolver.js.map +1 -0
- package/dist-server/service/material/material-revision-service.d.ts +179 -0
- package/dist-server/service/material/material-revision-service.js +687 -0
- package/dist-server/service/material/material-revision-service.js.map +1 -0
- package/dist-server/service/material/material-revision.d.ts +86 -0
- package/dist-server/service/material/material-revision.js +339 -0
- package/dist-server/service/material/material-revision.js.map +1 -0
- package/dist-server/service/material/recipe-index.d.ts +23 -0
- package/dist-server/service/material/recipe-index.js +44 -0
- package/dist-server/service/material/recipe-index.js.map +1 -0
- package/dist-server/service/operation/index.d.ts +6 -0
- package/dist-server/service/operation/index.js +10 -0
- package/dist-server/service/operation/index.js.map +1 -0
- package/dist-server/service/operation/operation-definition.d.ts +52 -0
- package/dist-server/service/operation/operation-definition.js +143 -0
- package/dist-server/service/operation/operation-definition.js.map +1 -0
- package/dist-server/service/operation/operation-master-resolver.d.ts +52 -0
- package/dist-server/service/operation/operation-master-resolver.js +187 -0
- package/dist-server/service/operation/operation-master-resolver.js.map +1 -0
- package/dist-server/service/operation/operation-master.d.ts +21 -0
- package/dist-server/service/operation/operation-master.js +28 -0
- package/dist-server/service/operation/operation-master.js.map +1 -0
- package/dist-server/service/operation/operation-query.d.ts +15 -0
- package/dist-server/service/operation/operation-query.js +56 -0
- package/dist-server/service/operation/operation-query.js.map +1 -0
- package/dist-server/service/operation/operation-readiness-resolver.d.ts +39 -0
- package/dist-server/service/operation/operation-readiness-resolver.js +111 -0
- package/dist-server/service/operation/operation-readiness-resolver.js.map +1 -0
- package/dist-server/service/operation/operation-readiness.d.ts +34 -0
- package/dist-server/service/operation/operation-readiness.js +133 -0
- package/dist-server/service/operation/operation-readiness.js.map +1 -0
- package/dist-server/service/personnel/index.d.ts +6 -0
- package/dist-server/service/personnel/index.js +10 -0
- package/dist-server/service/personnel/index.js.map +1 -0
- package/dist-server/service/personnel/person.d.ts +51 -0
- package/dist-server/service/personnel/person.js +119 -0
- package/dist-server/service/personnel/person.js.map +1 -0
- package/dist-server/service/personnel/personnel-class-readiness.d.ts +22 -0
- package/dist-server/service/personnel/personnel-class-readiness.js +98 -0
- package/dist-server/service/personnel/personnel-class-readiness.js.map +1 -0
- package/dist-server/service/personnel/personnel-class.d.ts +54 -0
- package/dist-server/service/personnel/personnel-class.js +114 -0
- package/dist-server/service/personnel/personnel-class.js.map +1 -0
- package/dist-server/service/personnel/personnel-master-resolver.d.ts +53 -0
- package/dist-server/service/personnel/personnel-master-resolver.js +187 -0
- package/dist-server/service/personnel/personnel-master-resolver.js.map +1 -0
- package/dist-server/service/personnel/personnel-master.d.ts +39 -0
- package/dist-server/service/personnel/personnel-master.js +34 -0
- package/dist-server/service/personnel/personnel-master.js.map +1 -0
- package/dist-server/service/personnel/personnel-query.d.ts +29 -0
- package/dist-server/service/personnel/personnel-query.js +79 -0
- package/dist-server/service/personnel/personnel-query.js.map +1 -0
- package/dist-server/service/personnel/qualification.d.ts +104 -0
- package/dist-server/service/personnel/qualification.js +147 -0
- package/dist-server/service/personnel/qualification.js.map +1 -0
- package/dist-server/service/quality/index.d.ts +4 -0
- package/dist-server/service/quality/index.js +8 -0
- package/dist-server/service/quality/index.js.map +1 -0
- package/dist-server/service/quality/nonconformance-cause-resolver.d.ts +12 -0
- package/dist-server/service/quality/nonconformance-cause-resolver.js +60 -0
- package/dist-server/service/quality/nonconformance-cause-resolver.js.map +1 -0
- package/dist-server/service/quality/nonconformance-cause.d.ts +20 -0
- package/dist-server/service/quality/nonconformance-cause.js +90 -0
- package/dist-server/service/quality/nonconformance-cause.js.map +1 -0
- package/dist-server/service/recipe/index.d.ts +10 -0
- package/dist-server/service/recipe/index.js +16 -0
- package/dist-server/service/recipe/index.js.map +1 -0
- package/dist-server/service/recipe/recipe-definition.d.ts +75 -0
- package/dist-server/service/recipe/recipe-definition.js +143 -0
- package/dist-server/service/recipe/recipe-definition.js.map +1 -0
- package/dist-server/service/recipe/recipe-effective-list.d.ts +49 -0
- package/dist-server/service/recipe/recipe-effective-list.js +96 -0
- package/dist-server/service/recipe/recipe-effective-list.js.map +1 -0
- package/dist-server/service/recipe/recipe-master-resolver.d.ts +28 -0
- package/dist-server/service/recipe/recipe-master-resolver.js +128 -0
- package/dist-server/service/recipe/recipe-master-resolver.js.map +1 -0
- package/dist-server/service/recipe/recipe-master.d.ts +37 -0
- package/dist-server/service/recipe/recipe-master.js +47 -0
- package/dist-server/service/recipe/recipe-master.js.map +1 -0
- package/dist-server/service/recipe/recipe-query.d.ts +21 -0
- package/dist-server/service/recipe/recipe-query.js +82 -0
- package/dist-server/service/recipe/recipe-query.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-content.d.ts +32 -0
- package/dist-server/service/recipe/recipe-revision-content.js +70 -0
- package/dist-server/service/recipe/recipe-revision-content.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-line.d.ts +30 -0
- package/dist-server/service/recipe/recipe-revision-line.js +95 -0
- package/dist-server/service/recipe/recipe-revision-line.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-resolver.d.ts +65 -0
- package/dist-server/service/recipe/recipe-revision-resolver.js +96 -0
- package/dist-server/service/recipe/recipe-revision-resolver.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision-service.d.ts +183 -0
- package/dist-server/service/recipe/recipe-revision-service.js +754 -0
- package/dist-server/service/recipe/recipe-revision-service.js.map +1 -0
- package/dist-server/service/recipe/recipe-revision.d.ts +102 -0
- package/dist-server/service/recipe/recipe-revision.js +373 -0
- package/dist-server/service/recipe/recipe-revision.js.map +1 -0
- package/dist-server/service/recipe/route-definition.d.ts +51 -0
- package/dist-server/service/recipe/route-definition.js +114 -0
- package/dist-server/service/recipe/route-definition.js.map +1 -0
- package/dist-server/service/resource/class-lineage.d.ts +46 -0
- package/dist-server/service/resource/class-lineage.js +80 -0
- package/dist-server/service/resource/class-lineage.js.map +1 -0
- package/dist-server/service/resource/class-members.d.ts +36 -0
- package/dist-server/service/resource/class-members.js +59 -0
- package/dist-server/service/resource/class-members.js.map +1 -0
- package/dist-server/service/resource/referrers.d.ts +54 -0
- package/dist-server/service/resource/referrers.js +99 -0
- package/dist-server/service/resource/referrers.js.map +1 -0
- package/dist-server/service/resource/resource-class.d.ts +25 -0
- package/dist-server/service/resource/resource-class.js +29 -0
- package/dist-server/service/resource/resource-class.js.map +1 -0
- package/dist-server/service/revision-baseline.d.ts +71 -0
- package/dist-server/service/revision-baseline.js +87 -0
- package/dist-server/service/revision-baseline.js.map +1 -0
- package/dist-server/service/row-lock.d.ts +22 -0
- package/dist-server/service/row-lock.js +31 -0
- package/dist-server/service/row-lock.js.map +1 -0
- package/dist-server/service/status/axis-stamp.d.ts +16 -0
- package/dist-server/service/status/axis-stamp.js +22 -0
- package/dist-server/service/status/axis-stamp.js.map +1 -0
- package/dist-server/service/status/index.d.ts +3 -0
- package/dist-server/service/status/index.js +7 -0
- package/dist-server/service/status/index.js.map +1 -0
- package/dist-server/service/status/master-status.d.ts +38 -0
- package/dist-server/service/status/master-status.js +129 -0
- package/dist-server/service/status/master-status.js.map +1 -0
- package/dist-server/service/test-spec/criteria-check.d.ts +53 -0
- package/dist-server/service/test-spec/criteria-check.js +142 -0
- package/dist-server/service/test-spec/criteria-check.js.map +1 -0
- package/dist-server/service/test-spec/criteria-rows.d.ts +89 -0
- package/dist-server/service/test-spec/criteria-rows.js +139 -0
- package/dist-server/service/test-spec/criteria-rows.js.map +1 -0
- package/dist-server/service/test-spec/index.d.ts +6 -0
- package/dist-server/service/test-spec/index.js +11 -0
- package/dist-server/service/test-spec/index.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-effective-list.d.ts +34 -0
- package/dist-server/service/test-spec/test-spec-effective-list.js +42 -0
- package/dist-server/service/test-spec/test-spec-effective-list.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.d.ts +44 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.js +144 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-master.d.ts +6 -0
- package/dist-server/service/test-spec/test-spec-master.js +18 -0
- package/dist-server/service/test-spec/test-spec-master.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-query.d.ts +15 -0
- package/dist-server/service/test-spec/test-spec-query.js +61 -0
- package/dist-server/service/test-spec/test-spec-query.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-revision-resolver.d.ts +59 -0
- package/dist-server/service/test-spec/test-spec-revision-resolver.js +96 -0
- package/dist-server/service/test-spec/test-spec-revision-resolver.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-revision-service.d.ts +178 -0
- package/dist-server/service/test-spec/test-spec-revision-service.js +685 -0
- package/dist-server/service/test-spec/test-spec-revision-service.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-revision.d.ts +86 -0
- package/dist-server/service/test-spec/test-spec-revision.js +334 -0
- package/dist-server/service/test-spec/test-spec-revision.js.map +1 -0
- package/dist-server/service/test-spec/test-specification.d.ts +47 -0
- package/dist-server/service/test-spec/test-specification.js +119 -0
- package/dist-server/service/test-spec/test-specification.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +3 -3
|
@@ -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;
|