@things-factory/ops-master 10.0.18 → 10.1.0
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 +18 -0
- package/dist-client/bootstrap.js +36 -0
- package/dist-client/bootstrap.js.map +1 -0
- package/dist-client/index.d.ts +15 -1
- package/dist-client/index.js +18 -1
- package/dist-client/index.js.map +1 -1
- 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 +57 -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 +33 -0
- package/dist-client/pages/master/master-options.js +47 -0
- package/dist-client/pages/master/master-options.js.map +1 -0
- package/dist-client/pages/master/master-page-base.d.ts +357 -0
- package/dist-client/pages/master/master-page-base.js +626 -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 +12 -0
- package/dist-client/pages/master/material-definition.js +62 -0
- package/dist-client/pages/master/material-definition.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 +426 -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 +136 -0
- package/dist-client/pages/master/recipe-definition.js +404 -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/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 +93 -0
- package/dist-client/pages/master/test-specification.js +449 -0
- package/dist-client/pages/master/test-specification.js.map +1 -0
- package/dist-client/pages/master-axes.d.ts +20 -29
- package/dist-client/pages/master-axes.js +32 -169
- package/dist-client/pages/master-axes.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +76 -3
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/asset/asset-lifecycle.d.ts +30 -7
- package/dist-server/service/asset/asset-lifecycle.js +33 -6
- package/dist-server/service/asset/asset-lifecycle.js.map +1 -1
- package/dist-server/service/asset/asset-master-resolver.d.ts +9 -0
- package/dist-server/service/asset/asset-master-resolver.js +41 -0
- package/dist-server/service/asset/asset-master-resolver.js.map +1 -1
- package/dist-server/service/asset/asset-master.js +1 -1
- package/dist-server/service/asset/asset-master.js.map +1 -1
- package/dist-server/service/asset/asset-query.d.ts +9 -1
- package/dist-server/service/asset/asset-query.js +28 -6
- package/dist-server/service/asset/asset-query.js.map +1 -1
- package/dist-server/service/asset/physical-asset-class.js +1 -1
- package/dist-server/service/asset/physical-asset-class.js.map +1 -1
- package/dist-server/service/asset/physical-asset.d.ts +17 -4
- package/dist-server/service/asset/physical-asset.js +6 -6
- package/dist-server/service/asset/physical-asset.js.map +1 -1
- package/dist-server/service/equipment/equipment-class.js +1 -1
- package/dist-server/service/equipment/equipment-class.js.map +1 -1
- package/dist-server/service/equipment/equipment-master-resolver.d.ts +9 -0
- package/dist-server/service/equipment/equipment-master-resolver.js +58 -0
- package/dist-server/service/equipment/equipment-master-resolver.js.map +1 -1
- package/dist-server/service/equipment/equipment-master.d.ts +3 -2
- package/dist-server/service/equipment/equipment-master.js +21 -4
- package/dist-server/service/equipment/equipment-master.js.map +1 -1
- package/dist-server/service/equipment/equipment-query.d.ts +9 -1
- package/dist-server/service/equipment/equipment-query.js +28 -6
- package/dist-server/service/equipment/equipment-query.js.map +1 -1
- package/dist-server/service/equipment/equipment.d.ts +27 -1
- package/dist-server/service/equipment/equipment.js +8 -3
- package/dist-server/service/equipment/equipment.js.map +1 -1
- package/dist-server/service/equipment/state-period-rules.d.ts +19 -0
- package/dist-server/service/equipment/state-period-rules.js +35 -1
- package/dist-server/service/equipment/state-period-rules.js.map +1 -1
- package/dist-server/service/index.d.ts +12 -2
- package/dist-server/service/index.js +21 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/location/location-master-resolver.d.ts +29 -0
- package/dist-server/service/location/location-master-resolver.js +228 -1
- package/dist-server/service/location/location-master-resolver.js.map +1 -1
- package/dist-server/service/location/location-query.d.ts +9 -1
- package/dist-server/service/location/location-query.js +24 -9
- package/dist-server/service/location/location-query.js.map +1 -1
- package/dist-server/service/location/operational-location.d.ts +37 -0
- package/dist-server/service/location/operational-location.js +22 -2
- package/dist-server/service/location/operational-location.js.map +1 -1
- package/dist-server/service/master-axis.d.ts +1 -1
- package/dist-server/service/master-axis.js +16 -1
- package/dist-server/service/master-axis.js.map +1 -1
- package/dist-server/service/master-conformance-resolver.d.ts +34 -0
- package/dist-server/service/master-conformance-resolver.js +143 -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-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/material-class.js +1 -1
- package/dist-server/service/material/material-class.js.map +1 -1
- package/dist-server/service/material/material-definition.js +2 -2
- package/dist-server/service/material/material-definition.js.map +1 -1
- package/dist-server/service/material/material-master-resolver.d.ts +62 -0
- package/dist-server/service/material/material-master-resolver.js +213 -0
- package/dist-server/service/material/material-master-resolver.js.map +1 -1
- package/dist-server/service/material/material-query.d.ts +9 -1
- package/dist-server/service/material/material-query.js +28 -6
- package/dist-server/service/material/material-query.js.map +1 -1
- 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 +2 -1
- package/dist-server/service/operation/index.js +2 -1
- package/dist-server/service/operation/index.js.map +1 -1
- package/dist-server/service/operation/operation-definition.d.ts +1 -1
- package/dist-server/service/operation/operation-definition.js +4 -4
- package/dist-server/service/operation/operation-definition.js.map +1 -1
- package/dist-server/service/operation/operation-master-resolver.d.ts +24 -0
- package/dist-server/service/operation/operation-master-resolver.js +107 -0
- package/dist-server/service/operation/operation-master-resolver.js.map +1 -1
- package/dist-server/service/operation/operation-query.d.ts +10 -2
- package/dist-server/service/operation/operation-query.js +25 -10
- package/dist-server/service/operation/operation-query.js.map +1 -1
- 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/person.js +3 -3
- package/dist-server/service/personnel/person.js.map +1 -1
- 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 +1 -1
- package/dist-server/service/personnel/personnel-class.js +2 -2
- package/dist-server/service/personnel/personnel-class.js.map +1 -1
- package/dist-server/service/personnel/personnel-master-resolver.d.ts +9 -0
- package/dist-server/service/personnel/personnel-master-resolver.js +43 -0
- package/dist-server/service/personnel/personnel-master-resolver.js.map +1 -1
- package/dist-server/service/personnel/personnel-master.js +1 -1
- package/dist-server/service/personnel/personnel-master.js.map +1 -1
- package/dist-server/service/personnel/personnel-query.d.ts +9 -1
- package/dist-server/service/personnel/personnel-query.js +28 -6
- package/dist-server/service/personnel/personnel-query.js.map +1 -1
- package/dist-server/service/personnel/qualification.d.ts +7 -0
- package/dist-server/service/personnel/qualification.js +25 -0
- package/dist-server/service/personnel/qualification.js.map +1 -1
- package/dist-server/service/recipe/index.d.ts +9 -0
- package/dist-server/service/recipe/index.js +14 -0
- package/dist-server/service/recipe/index.js.map +1 -0
- package/dist-server/service/recipe/recipe-definition.d.ts +71 -0
- package/dist-server/service/recipe/recipe-definition.js +130 -0
- package/dist-server/service/recipe/recipe-definition.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 +124 -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 +75 -0
- package/dist-server/service/recipe/recipe-query.js.map +1 -0
- package/dist-server/service/recipe/route-definition.d.ts +51 -0
- package/dist-server/service/recipe/route-definition.js +113 -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 +50 -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/status/master-status.d.ts +0 -7
- package/dist-server/service/status/master-status.js +5 -6
- package/dist-server/service/status/master-status.js.map +1 -1
- 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/test-spec-master-resolver.d.ts +33 -7
- package/dist-server/service/test-spec/test-spec-master-resolver.js +137 -2
- package/dist-server/service/test-spec/test-spec-master-resolver.js.map +1 -1
- package/dist-server/service/test-spec/test-spec-query.d.ts +9 -1
- package/dist-server/service/test-spec/test-spec-query.js +23 -9
- package/dist-server/service/test-spec/test-spec-query.js.map +1 -1
- package/dist-server/service/test-spec/test-specification.js +1 -1
- package/dist-server/service/test-spec/test-specification.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/ops-master/equipment-class.ko.md +11 -0
- package/helps/ops-master/equipment-class.md +11 -0
- package/helps/ops-master/equipment.ko.md +11 -0
- package/helps/ops-master/equipment.md +11 -0
- package/helps/ops-master/material-class.ko.md +11 -0
- package/helps/ops-master/material-class.md +11 -0
- package/helps/ops-master/material-definition.ko.md +11 -0
- package/helps/ops-master/material-definition.md +11 -0
- package/helps/ops-master/operation-definition.ko.md +11 -0
- package/helps/ops-master/operation-definition.md +11 -0
- package/helps/ops-master/operational-location.ko.md +11 -0
- package/helps/ops-master/operational-location.md +11 -0
- package/helps/ops-master/person.ko.md +11 -0
- package/helps/ops-master/person.md +11 -0
- package/helps/ops-master/personnel-class.ko.md +11 -0
- package/helps/ops-master/personnel-class.md +11 -0
- package/helps/ops-master/physical-asset-class.ko.md +11 -0
- package/helps/ops-master/physical-asset-class.md +11 -0
- package/helps/ops-master/physical-asset.ko.md +11 -0
- package/helps/ops-master/physical-asset.md +11 -0
- package/helps/ops-master/recipe-definition.ko.md +11 -0
- package/helps/ops-master/recipe-definition.md +11 -0
- package/helps/ops-master/route-definition.ko.md +11 -0
- package/helps/ops-master/route-definition.md +11 -0
- package/helps/ops-master/stop-reason.ko.md +11 -0
- package/helps/ops-master/stop-reason.md +11 -0
- package/helps/ops-master/test-specification.ko.md +11 -0
- package/helps/ops-master/test-specification.md +11 -0
- package/package.json +5 -5
- package/things-factory.config.js +22 -2
- package/translations/en.json +89 -6
- package/translations/ja.json +96 -1
- package/translations/ko.json +96 -13
- package/translations/ms.json +96 -1
- package/translations/zh.json +96 -1
- package/dist-client/pages/master-list.d.ts +0 -68
- package/dist-client/pages/master-list.js +0 -267
- package/dist-client/pages/master-list.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-definition.js","sourceRoot":"","sources":["../../../server/service/recipe/recipe-definition.ts"],"names":[],"mappings":";;;;AAAA,qCAAkI;AAClI,+CAAoD;AAEpD,iDAA4D;AAC5D,yDAAgD;AAEhD;;;;;;;;;;;;;;;;;;;;GAoBG;AAMI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CA8F5B,CAAA;AA9FY,4CAAgB;AAGlB;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,CAAC;;4CACC;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;sCACb,cAAM;gDAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,MAAwB,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;;kDACvC;AAKjB;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,GAAE;;8CACI;AAIZ;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;qDACN;AAYpB;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,GAAE;;gEACsB;AAU9B;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IAC/B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;;gDAC1D;AAKjC;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IAC/B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;;iDAC3B;AAUlC;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACZ;AAKd;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACT,IAAI;IAErB;;;;;OAKG;;wDAPkB;AAUrB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACX,IAAI;sDAAA;AAInB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACd,IAAI;mDAAA;AAIhB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACd,IAAI;mDAAA;AAIhB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCAC9B,gBAAI;iDAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,MAAwB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;;mDACvC;AAIlB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCAC9B,gBAAI;iDAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,MAAwB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;;mDACvC;2BA7FP,gBAAgB;IAL5B,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;IACzC,IAAA,eAAK,EAAC,4BAA4B,EAAE,CAAC,MAAwB,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAClH,8DAA8D;;IAC7D,IAAA,eAAK,EAAC,4BAA4B,EAAE,CAAC,MAAwB,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACjH,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,iFAAiF,EAAE,CAAC;GAClG,gBAAgB,CA8F5B","sourcesContent":["import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\nimport { Field, ID, ObjectType } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\n/**\n * 레시피 — **무엇으로 무엇을 만드나**. 커널 `RecipeDef` 와 같은 모양이다.\n *\n * ── 이 자리가 답하는 것 ──────────────────────────────────────────────────\n * 「이 품목은 무엇으로 만드나」와 「이 품목을 만드는 것은 어느 레시피인가」다. 둘째가 MES 가 물어야 했던\n * 것인데 물을 곳이 없었다.\n *\n * ── 품목에 지시서를 달지 않는 이유 ───────────────────────────────────────\n * ISA-95 에는 자재 명세가 붙는 자리가 둘이고 뜻이 다르다(§`RecipePart.operation`).\n *\n * · `ProcessSegment` — 그 자리가 **할 수 있는 일**. 품목에 매이지 않는다 → `OperationDefinition`\n * · `OperationsSegment` — 그 **품목을 만드는 절차**의 한 단계. 품목에 매인다 → **레시피가 그 범위다**\n *\n * 그래서 품목→지시서를 이으려면 그 사이에 레시피가 있어야 한다. 공정에 품목을 붙이면 범주 오류이고,\n * 실 데이터가 그 크기를 보였다 — 「배합」에 품목별 BOM 을 붙이면 배합을 지나는 **모든** 로트가 자재\n * 631종 36톤을 먹는다.\n *\n * ── 같은 품목에 레시피가 둘일 수 있다 ────────────────────────────────────\n * 대체 레시피가 정상이다(첫 실 연동에서 라우팅이 둘 이상인 레시피가 306/471). 그래서 **품목이 레시피를\n * 가리키지 않고 레시피가 품목을 가리킨다** — 품목은 하나를 고를 수 없다.\n */\n@Entity({ name: 'ops_recipe_definition' })\n@Index('ix_ops_recipe_definition_0', (recipe: RecipeDefinition) => [recipe.domain, recipe.name], { unique: true })\n/* 「이 품목을 만드는 레시피」로 묻는 질의가 이 축으로 온다 — MES 가 지시를 받을 때마다 부른다. */\n@Index('ix_ops_recipe_definition_1', (recipe: RecipeDefinition) => [recipe.domain, recipe.materialDefinitionName])\n@ObjectType({ description: 'Recipe — what a material is made of and through which route (kernel RecipeDef).' })\nexport class RecipeDefinition {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain)\n domain?: Domain\n\n @RelationId((recipe: RecipeDefinition) => recipe.domain)\n domainId?: string\n\n /** 레시피 키 — 오더의 `recipeKey` 가 이 값을 가리킨다(커널 `RecipeDef.key`). */\n @Column()\n @Field()\n name: string\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n description?: string\n\n /**\n * **무엇을 만드나** — `MaterialDefinition.name`.\n *\n * `outputs` 안에도 있지만 이 칸을 따로 둔다. 「이 품목을 만드는 레시피」를 JSON 안을 뒤져 찾으면\n * 다섯 드라이버에서 색인이 서지 않고, 그 질의는 MES 가 지시를 받을 때마다 부른다.\n *\n * 산출이 여럿인 레시피(부산물)에서는 **주 산출**을 적는다. 나머지는 `outputs` 가 든다.\n */\n @Column()\n @Field()\n materialDefinitionName: string\n\n /**\n * 투입 — 커널 `RecipePart[]`(`material` · `qty` · `operation?`).\n *\n * `operation` 은 **이 투입이 들어가는 공정**이다. 없으면 오더 착수에 확보한다. 그 태그가 여기 있는\n * 이유는 품목별 소요가 사는 자리가 레시피이기 때문이다.\n */\n @Column({ type: 'simple-json' })\n @Field(type => ScalarObject, { description: 'RecipePart[] — material · qty · operation?' })\n inputs: Record<string, unknown>[]\n\n /** 산출 — 커널 `RecipePart[]`. 부산물이 있으면 여기 함께 든다. */\n @Column({ type: 'simple-json' })\n @Field(type => ScalarObject, { description: 'RecipePart[]' })\n outputs: Record<string, unknown>[]\n\n /**\n * 이 산출물을 만드는 공정 라우팅 — `RouteDefinition.name`(커널 `RecipeDef.route`).\n *\n * 순서는 라우팅이 소유하고 레시피는 그것을 가리킨다. 레시피에 단계 목록을 또 두면 두 목록이 어긋날 수\n * 있고, 어긋났을 때 어느 쪽이 맞는지 말할 근거가 없다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true })\n route?: string\n\n /** 언제부터 유효한가 — 표준 `EffectiveStartDate`. */\n @Column({ nullable: true })\n @Field({ nullable: true })\n effectiveStart?: Date\n\n /**\n * 언제까지 유효한가 — 표준 `EffectiveEndDate`.\n *\n * **개정할 때 행을 고치지 않고 이 칸을 채우고 새 행을 세운다.** 고치면 그 레시피로 만든 지난 실적이\n * 어느 배합으로 만든 것인지 잃는다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true })\n effectiveEnd?: Date\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((recipe: RecipeDefinition) => recipe.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((recipe: RecipeDefinition) => recipe.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ListParam } from '@things-factory/shell';
|
|
2
|
+
import { MasterPatch } from '../master-crud';
|
|
3
|
+
import { RecipeDefinition } from './recipe-definition';
|
|
4
|
+
import { RouteDefinition } from './route-definition';
|
|
5
|
+
/**
|
|
6
|
+
* 레시피·라우팅 축을 채우고 고친다.
|
|
7
|
+
*
|
|
8
|
+
* 규칙은 `master-crud.ts` 한 곳에 있다. 여기는 축의 이름만 붙인다 — 다른 열셋과 같은 모양이다.
|
|
9
|
+
*
|
|
10
|
+
* **개정할 때 행을 고치지 않고 유효 기간의 끝을 채운다.** 고치면 그 레시피로 만든 지난 실적이 어느
|
|
11
|
+
* 배합으로 만든 것인지 잃는다.
|
|
12
|
+
*/
|
|
13
|
+
export declare class RecipeDefinitionList {
|
|
14
|
+
items: RecipeDefinition[];
|
|
15
|
+
total: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class RouteDefinitionList {
|
|
18
|
+
items: RouteDefinition[];
|
|
19
|
+
total: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class RecipeDefinitionResolver {
|
|
22
|
+
recipeDefinitions(params: ListParam, context: ResolverContext): Promise<RecipeDefinitionList>;
|
|
23
|
+
updateMultipleRecipeDefinition(patches: MasterPatch[], context: ResolverContext): Promise<RecipeDefinition[]>;
|
|
24
|
+
}
|
|
25
|
+
export declare class RouteDefinitionResolver {
|
|
26
|
+
routeDefinitions(params: ListParam, context: ResolverContext): Promise<RouteDefinitionList>;
|
|
27
|
+
updateMultipleRouteDefinition(patches: MasterPatch[], context: ResolverContext): Promise<RouteDefinition[]>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RouteDefinitionResolver = exports.RecipeDefinitionResolver = exports.RouteDefinitionList = exports.RecipeDefinitionList = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const shell_1 = require("@things-factory/shell");
|
|
7
|
+
const master_crud_1 = require("../master-crud");
|
|
8
|
+
const master_axis_1 = require("../master-axis");
|
|
9
|
+
const master_list_1 = require("../master-list");
|
|
10
|
+
const recipe_definition_1 = require("./recipe-definition");
|
|
11
|
+
const route_definition_1 = require("./route-definition");
|
|
12
|
+
/**
|
|
13
|
+
* 레시피·라우팅 축을 채우고 고친다.
|
|
14
|
+
*
|
|
15
|
+
* 규칙은 `master-crud.ts` 한 곳에 있다. 여기는 축의 이름만 붙인다 — 다른 열셋과 같은 모양이다.
|
|
16
|
+
*
|
|
17
|
+
* **개정할 때 행을 고치지 않고 유효 기간의 끝을 채운다.** 고치면 그 레시피로 만든 지난 실적이 어느
|
|
18
|
+
* 배합으로 만든 것인지 잃는다.
|
|
19
|
+
*/
|
|
20
|
+
let RecipeDefinitionList = class RecipeDefinitionList {
|
|
21
|
+
};
|
|
22
|
+
exports.RecipeDefinitionList = RecipeDefinitionList;
|
|
23
|
+
tslib_1.__decorate([
|
|
24
|
+
(0, type_graphql_1.Field)(type => [recipe_definition_1.RecipeDefinition]),
|
|
25
|
+
tslib_1.__metadata("design:type", Array)
|
|
26
|
+
], RecipeDefinitionList.prototype, "items", void 0);
|
|
27
|
+
tslib_1.__decorate([
|
|
28
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int),
|
|
29
|
+
tslib_1.__metadata("design:type", Number)
|
|
30
|
+
], RecipeDefinitionList.prototype, "total", void 0);
|
|
31
|
+
exports.RecipeDefinitionList = RecipeDefinitionList = tslib_1.__decorate([
|
|
32
|
+
(0, type_graphql_1.ObjectType)({ description: 'A page of recipe definitions' })
|
|
33
|
+
], RecipeDefinitionList);
|
|
34
|
+
let RouteDefinitionList = class RouteDefinitionList {
|
|
35
|
+
};
|
|
36
|
+
exports.RouteDefinitionList = RouteDefinitionList;
|
|
37
|
+
tslib_1.__decorate([
|
|
38
|
+
(0, type_graphql_1.Field)(type => [route_definition_1.RouteDefinition]),
|
|
39
|
+
tslib_1.__metadata("design:type", Array)
|
|
40
|
+
], RouteDefinitionList.prototype, "items", void 0);
|
|
41
|
+
tslib_1.__decorate([
|
|
42
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int),
|
|
43
|
+
tslib_1.__metadata("design:type", Number)
|
|
44
|
+
], RouteDefinitionList.prototype, "total", void 0);
|
|
45
|
+
exports.RouteDefinitionList = RouteDefinitionList = tslib_1.__decorate([
|
|
46
|
+
(0, type_graphql_1.ObjectType)({ description: 'A page of route definitions' })
|
|
47
|
+
], RouteDefinitionList);
|
|
48
|
+
let RecipeDefinitionResolver = class RecipeDefinitionResolver {
|
|
49
|
+
async recipeDefinitions(params, context) {
|
|
50
|
+
const { domain } = context.state;
|
|
51
|
+
const { items, total } = await (0, master_list_1.listMaster)('recipeDefinition', params, domain);
|
|
52
|
+
return { items: items, total };
|
|
53
|
+
}
|
|
54
|
+
async updateMultipleRecipeDefinition(patches, context) {
|
|
55
|
+
const { domain, user, tx } = context.state;
|
|
56
|
+
const axis = (0, master_axis_1.masterAxisOf)('recipeDefinition');
|
|
57
|
+
const saved = await (0, master_crud_1.saveMasterPatches)(tx, domain, axis.entity, patches, user, {
|
|
58
|
+
hasEffectivePeriod: axis.hasEffectivePeriod
|
|
59
|
+
});
|
|
60
|
+
return saved;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.RecipeDefinitionResolver = RecipeDefinitionResolver;
|
|
64
|
+
tslib_1.__decorate([
|
|
65
|
+
(0, type_graphql_1.Directive)('@privilege(category: "ops-master", privilege: "query", domainOwnerGranted: true)'),
|
|
66
|
+
(0, type_graphql_1.Query)(returns => RecipeDefinitionList, { description: 'To fetch recipe definitions' }),
|
|
67
|
+
tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
|
|
68
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
69
|
+
tslib_1.__metadata("design:type", Function),
|
|
70
|
+
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
71
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
72
|
+
], RecipeDefinitionResolver.prototype, "recipeDefinitions", null);
|
|
73
|
+
tslib_1.__decorate([
|
|
74
|
+
(0, type_graphql_1.Directive)('@privilege(category: "ops-master", privilege: "mutation", domainOwnerGranted: true)'),
|
|
75
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
76
|
+
(0, type_graphql_1.Mutation)(returns => [recipe_definition_1.RecipeDefinition], { description: 'To create, change or retire recipe definitions' }),
|
|
77
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('patches', type => [shell_1.ScalarObject])),
|
|
78
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
79
|
+
tslib_1.__metadata("design:type", Function),
|
|
80
|
+
tslib_1.__metadata("design:paramtypes", [Array, Object]),
|
|
81
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
82
|
+
], RecipeDefinitionResolver.prototype, "updateMultipleRecipeDefinition", null);
|
|
83
|
+
exports.RecipeDefinitionResolver = RecipeDefinitionResolver = tslib_1.__decorate([
|
|
84
|
+
(0, type_graphql_1.Resolver)(recipe_definition_1.RecipeDefinition)
|
|
85
|
+
], RecipeDefinitionResolver);
|
|
86
|
+
let RouteDefinitionResolver = class RouteDefinitionResolver {
|
|
87
|
+
async routeDefinitions(params, context) {
|
|
88
|
+
const { domain } = context.state;
|
|
89
|
+
const { items, total } = await (0, master_list_1.listMaster)('routeDefinition', params, domain);
|
|
90
|
+
return { items: items, total };
|
|
91
|
+
}
|
|
92
|
+
async updateMultipleRouteDefinition(patches, context) {
|
|
93
|
+
const { domain, user, tx } = context.state;
|
|
94
|
+
const axis = (0, master_axis_1.masterAxisOf)('routeDefinition');
|
|
95
|
+
const saved = await (0, master_crud_1.saveMasterPatches)(tx, domain, axis.entity, patches, user, {
|
|
96
|
+
hasEffectivePeriod: axis.hasEffectivePeriod
|
|
97
|
+
});
|
|
98
|
+
return saved;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
exports.RouteDefinitionResolver = RouteDefinitionResolver;
|
|
102
|
+
tslib_1.__decorate([
|
|
103
|
+
(0, type_graphql_1.Directive)('@privilege(category: "ops-master", privilege: "query", domainOwnerGranted: true)'),
|
|
104
|
+
(0, type_graphql_1.Query)(returns => RouteDefinitionList, { description: 'To fetch route definitions' }),
|
|
105
|
+
tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
|
|
106
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
107
|
+
tslib_1.__metadata("design:type", Function),
|
|
108
|
+
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
109
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
110
|
+
], RouteDefinitionResolver.prototype, "routeDefinitions", null);
|
|
111
|
+
tslib_1.__decorate([
|
|
112
|
+
(0, type_graphql_1.Directive)('@privilege(category: "ops-master", privilege: "mutation", domainOwnerGranted: true)'),
|
|
113
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
114
|
+
(0, type_graphql_1.Mutation)(returns => [route_definition_1.RouteDefinition], { description: 'To create, change or retire route definitions' }),
|
|
115
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('patches', type => [shell_1.ScalarObject])),
|
|
116
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
117
|
+
tslib_1.__metadata("design:type", Function),
|
|
118
|
+
tslib_1.__metadata("design:paramtypes", [Array, Object]),
|
|
119
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
120
|
+
], RouteDefinitionResolver.prototype, "updateMultipleRouteDefinition", null);
|
|
121
|
+
exports.RouteDefinitionResolver = RouteDefinitionResolver = tslib_1.__decorate([
|
|
122
|
+
(0, type_graphql_1.Resolver)(route_definition_1.RouteDefinition)
|
|
123
|
+
], RouteDefinitionResolver);
|
|
124
|
+
//# sourceMappingURL=recipe-master-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-master-resolver.js","sourceRoot":"","sources":["../../../server/service/recipe/recipe-master-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { Args, Arg, Ctx, Directive, Int, Mutation, ObjectType, Field, Query, Resolver } from 'type-graphql'\n\nimport { ListParam, ScalarObject } from '@things-factory/shell'\n\nimport { MasterPatch, saveMasterPatches } from '../master-crud'\nimport { masterAxisOf } from '../master-axis'\nimport { listMaster } from '../master-list'\nimport { RecipeDefinition } from './recipe-definition'\nimport { RouteDefinition } from './route-definition'\n\n/**\n * 레시피·라우팅 축을 채우고 고친다.\n *\n * 규칙은 `master-crud.ts` 한 곳에 있다. 여기는 축의 이름만 붙인다 — 다른 열셋과 같은 모양이다.\n *\n * **개정할 때 행을 고치지 않고 유효 기간의 끝을 채운다.** 고치면 그 레시피로 만든 지난 실적이 어느\n * 배합으로 만든 것인지 잃는다.\n */\n\n@ObjectType({ description: 'A page of recipe definitions' })\nexport class RecipeDefinitionList {\n @Field(type => [RecipeDefinition])\n items: RecipeDefinition[]\n\n @Field(type => Int)\n total: number\n}\n\n@ObjectType({ description: 'A page of route definitions' })\nexport class RouteDefinitionList {\n @Field(type => [RouteDefinition])\n items: RouteDefinition[]\n\n @Field(type => Int)\n total: number\n}\n\n@Resolver(RecipeDefinition)\nexport class RecipeDefinitionResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => RecipeDefinitionList, { description: 'To fetch recipe definitions' })\n async recipeDefinitions(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<RecipeDefinitionList> {\n const { domain } = context.state\n const { items, total } = await listMaster('recipeDefinition', params, domain)\n\n return { items: items as RecipeDefinition[], total }\n }\n\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [RecipeDefinition], { description: 'To create, change or retire recipe definitions' })\n async updateMultipleRecipeDefinition(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<RecipeDefinition[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('recipeDefinition')\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as RecipeDefinition[]\n }\n}\n\n@Resolver(RouteDefinition)\nexport class RouteDefinitionResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => RouteDefinitionList, { description: 'To fetch route definitions' })\n async routeDefinitions(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<RouteDefinitionList> {\n const { domain } = context.state\n const { items, total } = await listMaster('routeDefinition', params, domain)\n\n return { items: items as RouteDefinition[], total }\n }\n\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [RouteDefinition], { description: 'To create, change or retire route definitions' })\n async updateMultipleRouteDefinition(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<RouteDefinition[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('routeDefinition')\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as RouteDefinition[]\n }\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { RecipeDefinition } from './recipe-definition';
|
|
2
|
+
import type { RouteDefinition } from './route-definition';
|
|
3
|
+
/**
|
|
4
|
+
* 트윈 선언의 `recipes`·`routes` 한 항목 — 계약의 `RecipeDef`·`RouteDef` 모양이다.
|
|
5
|
+
*
|
|
6
|
+
* 마스터가 다른 모양으로 들면 옮기는 코드가 두 겹이 되고, 그 코드가 언젠가 어긋난다. 그래서 칸 이름을
|
|
7
|
+
* 계약과 같게 둔다 — 다른 것은 마스터가 `name` 으로 부르는 것을 계약이 `key` 로 부르는 것 하나다.
|
|
8
|
+
*/
|
|
9
|
+
export interface RouteEntry {
|
|
10
|
+
key: string;
|
|
11
|
+
label: string;
|
|
12
|
+
steps: string[];
|
|
13
|
+
procedure?: unknown[];
|
|
14
|
+
effectiveStart?: string;
|
|
15
|
+
effectiveEnd?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface RecipeEntry {
|
|
18
|
+
key: string;
|
|
19
|
+
label: string;
|
|
20
|
+
inputs: unknown[];
|
|
21
|
+
outputs: unknown[];
|
|
22
|
+
route?: string;
|
|
23
|
+
effectiveStart?: string;
|
|
24
|
+
effectiveEnd?: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function toRouteEntry(route: RouteDefinition): RouteEntry;
|
|
27
|
+
export declare function toRecipeEntry(recipe: RecipeDefinition): RecipeEntry;
|
|
28
|
+
/**
|
|
29
|
+
* **이 품목을 만드는 레시피들** — 여럿일 수 있다.
|
|
30
|
+
*
|
|
31
|
+
* 하나를 골라 주지 않는다. 대체 레시피가 정상이고(첫 실 연동에서 라우팅이 둘 이상인 레시피가 306/471),
|
|
32
|
+
* 어느 것으로 만들지는 오더가 정하거나 사람이 고른다. 여기서 하나를 골라 주면 그 판정이 숨는다.
|
|
33
|
+
*
|
|
34
|
+
* 유효 기간은 여기서 걸러 내지 않는다 — 「지금 무엇을 쓸 수 있나」와 「그때 무엇을 썼나」가 다른 물음이고,
|
|
35
|
+
* 시각을 아는 것은 부르는 쪽이다.
|
|
36
|
+
*/
|
|
37
|
+
export declare function recipesFor(recipes: RecipeDefinition[], materialDefinitionName: string): RecipeEntry[];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toRouteEntry = toRouteEntry;
|
|
4
|
+
exports.toRecipeEntry = toRecipeEntry;
|
|
5
|
+
exports.recipesFor = recipesFor;
|
|
6
|
+
const resource_class_1 = require("../resource/resource-class");
|
|
7
|
+
function toRouteEntry(route) {
|
|
8
|
+
/* `steps` 를 비울 수 없다 — 단계가 없는 라우팅은 지나갈 곳이 없다. */
|
|
9
|
+
const out = {
|
|
10
|
+
key: route.name,
|
|
11
|
+
label: route.description ?? route.name,
|
|
12
|
+
steps: route.steps ?? []
|
|
13
|
+
};
|
|
14
|
+
(0, resource_class_1.put)(out, 'procedure', route.procedure);
|
|
15
|
+
(0, resource_class_1.put)(out, 'effectiveStart', (0, resource_class_1.iso)(route.effectiveStart));
|
|
16
|
+
(0, resource_class_1.put)(out, 'effectiveEnd', (0, resource_class_1.iso)(route.effectiveEnd));
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
19
|
+
function toRecipeEntry(recipe) {
|
|
20
|
+
/*
|
|
21
|
+
* `inputs` 와 `outputs` 를 비울 수 없다. 산출이 없으면 무엇을 만드는지 알 수 없고, 투입이 없으면
|
|
22
|
+
* 무엇으로 만드는지 알 수 없다 — 둘 중 하나만으로는 레시피가 아니다.
|
|
23
|
+
*/
|
|
24
|
+
const out = {
|
|
25
|
+
key: recipe.name,
|
|
26
|
+
label: recipe.description ?? recipe.name,
|
|
27
|
+
inputs: recipe.inputs ?? [],
|
|
28
|
+
outputs: recipe.outputs ?? []
|
|
29
|
+
};
|
|
30
|
+
(0, resource_class_1.put)(out, 'route', recipe.route);
|
|
31
|
+
(0, resource_class_1.put)(out, 'effectiveStart', (0, resource_class_1.iso)(recipe.effectiveStart));
|
|
32
|
+
(0, resource_class_1.put)(out, 'effectiveEnd', (0, resource_class_1.iso)(recipe.effectiveEnd));
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* **이 품목을 만드는 레시피들** — 여럿일 수 있다.
|
|
37
|
+
*
|
|
38
|
+
* 하나를 골라 주지 않는다. 대체 레시피가 정상이고(첫 실 연동에서 라우팅이 둘 이상인 레시피가 306/471),
|
|
39
|
+
* 어느 것으로 만들지는 오더가 정하거나 사람이 고른다. 여기서 하나를 골라 주면 그 판정이 숨는다.
|
|
40
|
+
*
|
|
41
|
+
* 유효 기간은 여기서 걸러 내지 않는다 — 「지금 무엇을 쓸 수 있나」와 「그때 무엇을 썼나」가 다른 물음이고,
|
|
42
|
+
* 시각을 아는 것은 부르는 쪽이다.
|
|
43
|
+
*/
|
|
44
|
+
function recipesFor(recipes, materialDefinitionName) {
|
|
45
|
+
return recipes.filter(r => r.materialDefinitionName === materialDefinitionName).map(toRecipeEntry);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=recipe-master.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-master.js","sourceRoot":"","sources":["../../../server/service/recipe/recipe-master.ts"],"names":[],"mappings":";;AA6BA,oCAWC;AAED,sCAeC;AAWD,gCAEC;AAtED,+DAAqD;AA6BrD,SAAgB,YAAY,CAAC,KAAsB;IACjD,gDAAgD;IAChD,MAAM,GAAG,GAA4B;QACnC,GAAG,EAAE,KAAK,CAAC,IAAI;QACf,KAAK,EAAE,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI;QACtC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;KACzB,CAAA;IACD,IAAA,oBAAG,EAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;IACtC,IAAA,oBAAG,EAAC,GAAG,EAAE,gBAAgB,EAAE,IAAA,oBAAG,EAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAA;IACrD,IAAA,oBAAG,EAAC,GAAG,EAAE,cAAc,EAAE,IAAA,oBAAG,EAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAA;IACjD,OAAO,GAA4B,CAAA;AACrC,CAAC;AAED,SAAgB,aAAa,CAAC,MAAwB;IACpD;;;OAGG;IACH,MAAM,GAAG,GAA4B;QACnC,GAAG,EAAE,MAAM,CAAC,IAAI;QAChB,KAAK,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI;QACxC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;KAC9B,CAAA;IACD,IAAA,oBAAG,EAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAC/B,IAAA,oBAAG,EAAC,GAAG,EAAE,gBAAgB,EAAE,IAAA,oBAAG,EAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAA;IACtD,IAAA,oBAAG,EAAC,GAAG,EAAE,cAAc,EAAE,IAAA,oBAAG,EAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAA;IAClD,OAAO,GAA6B,CAAA;AACtC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,UAAU,CAAC,OAA2B,EAAE,sBAA8B;IACpF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,sBAAsB,KAAK,sBAAsB,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;AACpG,CAAC","sourcesContent":["import { iso, put } from '../resource/resource-class'\nimport type { RecipeDefinition } from './recipe-definition'\nimport type { RouteDefinition } from './route-definition'\n\n/**\n * 트윈 선언의 `recipes`·`routes` 한 항목 — 계약의 `RecipeDef`·`RouteDef` 모양이다.\n *\n * 마스터가 다른 모양으로 들면 옮기는 코드가 두 겹이 되고, 그 코드가 언젠가 어긋난다. 그래서 칸 이름을\n * 계약과 같게 둔다 — 다른 것은 마스터가 `name` 으로 부르는 것을 계약이 `key` 로 부르는 것 하나다.\n */\nexport interface RouteEntry {\n key: string\n label: string\n steps: string[]\n procedure?: unknown[]\n effectiveStart?: string\n effectiveEnd?: string\n}\n\nexport interface RecipeEntry {\n key: string\n label: string\n inputs: unknown[]\n outputs: unknown[]\n route?: string\n effectiveStart?: string\n effectiveEnd?: string\n}\n\nexport function toRouteEntry(route: RouteDefinition): RouteEntry {\n /* `steps` 를 비울 수 없다 — 단계가 없는 라우팅은 지나갈 곳이 없다. */\n const out: Record<string, unknown> = {\n key: route.name,\n label: route.description ?? route.name,\n steps: route.steps ?? []\n }\n put(out, 'procedure', route.procedure)\n put(out, 'effectiveStart', iso(route.effectiveStart))\n put(out, 'effectiveEnd', iso(route.effectiveEnd))\n return out as unknown as RouteEntry\n}\n\nexport function toRecipeEntry(recipe: RecipeDefinition): RecipeEntry {\n /*\n * `inputs` 와 `outputs` 를 비울 수 없다. 산출이 없으면 무엇을 만드는지 알 수 없고, 투입이 없으면\n * 무엇으로 만드는지 알 수 없다 — 둘 중 하나만으로는 레시피가 아니다.\n */\n const out: Record<string, unknown> = {\n key: recipe.name,\n label: recipe.description ?? recipe.name,\n inputs: recipe.inputs ?? [],\n outputs: recipe.outputs ?? []\n }\n put(out, 'route', recipe.route)\n put(out, 'effectiveStart', iso(recipe.effectiveStart))\n put(out, 'effectiveEnd', iso(recipe.effectiveEnd))\n return out as unknown as RecipeEntry\n}\n\n/**\n * **이 품목을 만드는 레시피들** — 여럿일 수 있다.\n *\n * 하나를 골라 주지 않는다. 대체 레시피가 정상이고(첫 실 연동에서 라우팅이 둘 이상인 레시피가 306/471),\n * 어느 것으로 만들지는 오더가 정하거나 사람이 고른다. 여기서 하나를 골라 주면 그 판정이 숨는다.\n *\n * 유효 기간은 여기서 걸러 내지 않는다 — 「지금 무엇을 쓸 수 있나」와 「그때 무엇을 썼나」가 다른 물음이고,\n * 시각을 아는 것은 부르는 쪽이다.\n */\nexport function recipesFor(recipes: RecipeDefinition[], materialDefinitionName: string): RecipeEntry[] {\n return recipes.filter(r => r.materialDefinitionName === materialDefinitionName).map(toRecipeEntry)\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class RecipeMaster {
|
|
2
|
+
recipes: string;
|
|
3
|
+
routes: string;
|
|
4
|
+
/**
|
|
5
|
+
* 더 있나 — **이 값을 안 보고 쓰면 조용히 잘린 마스터로 트윈을 세우게 된다.**
|
|
6
|
+
*
|
|
7
|
+
* 거짓이 될 때까지 `next` 를 `after` 로 넘겨 이어 받는다.
|
|
8
|
+
*/
|
|
9
|
+
hasMore: boolean;
|
|
10
|
+
/** 이어 받을 자리. 더 없으면 없다. */
|
|
11
|
+
next?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class RecipeQuery {
|
|
14
|
+
/**
|
|
15
|
+
* 레시피와 라우팅을 **한 질의로** 낸다.
|
|
16
|
+
*
|
|
17
|
+
* 따로 물으면 그 사이에 마스터가 바뀌어 레시피가 없는 라우팅을 가리키는 순간이 생긴다. 구조는
|
|
18
|
+
* 서로를 가리키므로 통째로 맞아야 한다 — 마스터를 당겨 가는 다른 축과 같은 규율이다.
|
|
19
|
+
*/
|
|
20
|
+
recipeMaster(after: string | undefined, limit: number | undefined, context: ResolverContext): Promise<RecipeMaster>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RecipeQuery = exports.RecipeMaster = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const shell_1 = require("@things-factory/shell");
|
|
7
|
+
const master_page_query_1 = require("../master-page-query");
|
|
8
|
+
const recipe_definition_1 = require("./recipe-definition");
|
|
9
|
+
const route_definition_1 = require("./route-definition");
|
|
10
|
+
const recipe_master_1 = require("./recipe-master");
|
|
11
|
+
let RecipeMaster = class RecipeMaster {
|
|
12
|
+
};
|
|
13
|
+
exports.RecipeMaster = RecipeMaster;
|
|
14
|
+
tslib_1.__decorate([
|
|
15
|
+
(0, type_graphql_1.Field)(type => String, { description: 'RecipeDef[] as JSON text' }),
|
|
16
|
+
tslib_1.__metadata("design:type", String)
|
|
17
|
+
], RecipeMaster.prototype, "recipes", void 0);
|
|
18
|
+
tslib_1.__decorate([
|
|
19
|
+
(0, type_graphql_1.Field)(type => String, { description: 'RouteDef[] as JSON text' }),
|
|
20
|
+
tslib_1.__metadata("design:type", String)
|
|
21
|
+
], RecipeMaster.prototype, "routes", void 0);
|
|
22
|
+
tslib_1.__decorate([
|
|
23
|
+
(0, type_graphql_1.Field)({ description: 'true when more rows remain — keep pulling with next as after' }),
|
|
24
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
25
|
+
], RecipeMaster.prototype, "hasMore", void 0);
|
|
26
|
+
tslib_1.__decorate([
|
|
27
|
+
(0, type_graphql_1.Field)(type => String, { nullable: true, description: 'cursor for the next page — the last name in this page' }),
|
|
28
|
+
tslib_1.__metadata("design:type", String)
|
|
29
|
+
], RecipeMaster.prototype, "next", void 0);
|
|
30
|
+
exports.RecipeMaster = RecipeMaster = tslib_1.__decorate([
|
|
31
|
+
(0, type_graphql_1.ObjectType)({ description: 'Recipes and routes as the twin receives them' })
|
|
32
|
+
], RecipeMaster);
|
|
33
|
+
let RecipeQuery = class RecipeQuery {
|
|
34
|
+
/**
|
|
35
|
+
* 레시피와 라우팅을 **한 질의로** 낸다.
|
|
36
|
+
*
|
|
37
|
+
* 따로 물으면 그 사이에 마스터가 바뀌어 레시피가 없는 라우팅을 가리키는 순간이 생긴다. 구조는
|
|
38
|
+
* 서로를 가리키므로 통째로 맞아야 한다 — 마스터를 당겨 가는 다른 축과 같은 규율이다.
|
|
39
|
+
*/
|
|
40
|
+
async recipeMaster(after, limit, context) {
|
|
41
|
+
const { domain } = context.state;
|
|
42
|
+
const request = { after, limit };
|
|
43
|
+
/*
|
|
44
|
+
* **라우팅은 통째로, 레시피만 나눈다.** 레시피가 라우팅을 이름으로 가리키므로, 둘을 함께 나누면
|
|
45
|
+
* 레시피가 먼저 도착하고 라우팅이 나중에 오는 순간이 생긴다 — 이 파일이 원래 「따로 물으면 레시피가
|
|
46
|
+
* 없는 라우팅을 가리키는 순간이 생긴다」고 적어 둔 그 이유다.
|
|
47
|
+
*/
|
|
48
|
+
const [page, routes] = await Promise.all([
|
|
49
|
+
(0, master_page_query_1.pullPage)(recipe_definition_1.RecipeDefinition, domain, request),
|
|
50
|
+
(0, shell_1.getRepository)(route_definition_1.RouteDefinition).find({ where: { domain: { id: domain.id } }, order: { name: 'ASC' } })
|
|
51
|
+
]);
|
|
52
|
+
/* 통째로 달라고 했는데 한도를 넘으면 **자르지 않고 거절한다**(§`master-page`). */
|
|
53
|
+
(0, master_page_query_1.refuseIfTooLarge)('레시피', request, page);
|
|
54
|
+
return {
|
|
55
|
+
recipes: JSON.stringify(page.rows.map(recipe_master_1.toRecipeEntry)),
|
|
56
|
+
routes: JSON.stringify(routes.map(recipe_master_1.toRouteEntry)),
|
|
57
|
+
hasMore: page.hasMore,
|
|
58
|
+
...(page.next ? { next: page.next } : {})
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
exports.RecipeQuery = RecipeQuery;
|
|
63
|
+
tslib_1.__decorate([
|
|
64
|
+
(0, type_graphql_1.Query)(returns => RecipeMaster, { description: 'Recipes and routes for the twin to pull' }),
|
|
65
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('after', { nullable: true, description: 'resume after this name — the previous page\'s next' })),
|
|
66
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('limit', type => type_graphql_1.Int, { nullable: true, description: 'rows per page — omit only when the axis is small enough to pull whole' })),
|
|
67
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
68
|
+
tslib_1.__metadata("design:type", Function),
|
|
69
|
+
tslib_1.__metadata("design:paramtypes", [String, Number, Object]),
|
|
70
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
71
|
+
], RecipeQuery.prototype, "recipeMaster", null);
|
|
72
|
+
exports.RecipeQuery = RecipeQuery = tslib_1.__decorate([
|
|
73
|
+
(0, type_graphql_1.Resolver)(recipe_definition_1.RecipeDefinition)
|
|
74
|
+
], RecipeQuery);
|
|
75
|
+
//# sourceMappingURL=recipe-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-query.js","sourceRoot":"","sources":["../../../server/service/recipe/recipe-query.ts"],"names":[],"mappings":";;;;AAAA,+CAAgF;AAEhF,iDAAqD;AAErD,4DAAiE;AAEjE,2DAAsD;AACtD,yDAAoD;AACpD,mDAA6D;AAGtD,IAAM,YAAY,GAAlB,MAAM,YAAY;CAmBxB,CAAA;AAnBY,oCAAY;AAEvB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC;;6CACpD;AAGf;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;;4CACpD;AAQd;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;;6CACvE;AAIhB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uDAAuD,EAAE,CAAC;;0CACnG;uBAjBF,YAAY;IADxB,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;GAC/D,YAAY,CAmBxB;AAGM,IAAM,WAAW,GAAjB,MAAM,WAAW;IACtB;;;;;OAKG;IAEG,AAAN,KAAK,CAAC,YAAY,CACqF,KAAyB,EACO,KAAyB,EACvJ,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;QAEhC;;;;WAIG;QACH,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACvC,IAAA,4BAAQ,EAAmB,oCAAgB,EAAE,MAAM,EAAE,OAAO,CAAC;YAC7D,IAAA,qBAAa,EAAC,kCAAe,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;SACtG,CAAC,CAAA;QAEF,0DAA0D;QAC1D,IAAA,oCAAgB,EAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;QAEtC,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,6BAAa,CAAC,CAAC;YACrD,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,4BAAY,CAAC,CAAC;YAChD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,CAAA;IACH,CAAC;CACF,CAAA;AArCY,kCAAW;AAQhB;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;IAExF,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC,CAAA;IACnG,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uEAAuE,EAAE,CAAC,CAAA;IACnI,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;+CAyBP;sBApCU,WAAW;IADvB,IAAA,uBAAQ,EAAC,oCAAgB,CAAC;GACd,WAAW,CAqCvB","sourcesContent":["import { Arg, Ctx, Field, Int, ObjectType, Query, Resolver } from 'type-graphql'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { pullPage, refuseIfTooLarge } from '../master-page-query'\n\nimport { RecipeDefinition } from './recipe-definition'\nimport { RouteDefinition } from './route-definition'\nimport { toRecipeEntry, toRouteEntry } from './recipe-master'\n\n@ObjectType({ description: 'Recipes and routes as the twin receives them' })\nexport class RecipeMaster {\n @Field(type => String, { description: 'RecipeDef[] as JSON text' })\n recipes: string\n\n @Field(type => String, { description: 'RouteDef[] as JSON text' })\n routes: string\n\n /**\n * 더 있나 — **이 값을 안 보고 쓰면 조용히 잘린 마스터로 트윈을 세우게 된다.**\n *\n * 거짓이 될 때까지 `next` 를 `after` 로 넘겨 이어 받는다.\n */\n @Field({ description: 'true when more rows remain — keep pulling with next as after' })\n hasMore: boolean\n\n /** 이어 받을 자리. 더 없으면 없다. */\n @Field(type => String, { nullable: true, description: 'cursor for the next page — the last name in this page' })\n next?: string\n\n}\n\n@Resolver(RecipeDefinition)\nexport class RecipeQuery {\n /**\n * 레시피와 라우팅을 **한 질의로** 낸다.\n *\n * 따로 물으면 그 사이에 마스터가 바뀌어 레시피가 없는 라우팅을 가리키는 순간이 생긴다. 구조는\n * 서로를 가리키므로 통째로 맞아야 한다 — 마스터를 당겨 가는 다른 축과 같은 규율이다.\n */\n @Query(returns => RecipeMaster, { description: 'Recipes and routes for the twin to pull' })\n async recipeMaster(\n @Arg('after', { nullable: true, description: 'resume after this name — the previous page\\'s next' }) after: string | undefined,\n @Arg('limit', type => Int, { nullable: true, description: 'rows per page — omit only when the axis is small enough to pull whole' }) limit: number | undefined,\n @Ctx() context: ResolverContext\n ): Promise<RecipeMaster> {\n const { domain } = context.state\n\n const request = { after, limit }\n\n /*\n * **라우팅은 통째로, 레시피만 나눈다.** 레시피가 라우팅을 이름으로 가리키므로, 둘을 함께 나누면\n * 레시피가 먼저 도착하고 라우팅이 나중에 오는 순간이 생긴다 — 이 파일이 원래 「따로 물으면 레시피가\n * 없는 라우팅을 가리키는 순간이 생긴다」고 적어 둔 그 이유다.\n */\n const [page, routes] = await Promise.all([\n pullPage<RecipeDefinition>(RecipeDefinition, domain, request),\n getRepository(RouteDefinition).find({ where: { domain: { id: domain.id } }, order: { name: 'ASC' } })\n ])\n\n /* 통째로 달라고 했는데 한도를 넘으면 **자르지 않고 거절한다**(§`master-page`). */\n refuseIfTooLarge('레시피', request, page)\n\n return {\n recipes: JSON.stringify(page.rows.map(toRecipeEntry)),\n routes: JSON.stringify(routes.map(toRouteEntry)),\n hasMore: page.hasMore,\n ...(page.next ? { next: page.next } : {})\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Domain } from '@things-factory/shell';
|
|
2
|
+
import { User } from '@things-factory/auth-base';
|
|
3
|
+
/**
|
|
4
|
+
* 라우팅 — **공정을 지나는 순서**. 커널 `RouteDef` 와 같은 모양이다.
|
|
5
|
+
*
|
|
6
|
+
* ── 왜 마스터에 있나 (2026-08-31) ────────────────────────────────────────
|
|
7
|
+
* 커널에 `RouteDef` 가 있고 `JobOrder.routeKey` 가 그것을 가리키는데, **그 값이 가리킬 표가 없었다.**
|
|
8
|
+
* 사람이 문자열을 손으로 적는 상태였고, 그래서 MES 가 받은 작업지시에 라우팅을 자동으로 붙일 수 없었다.
|
|
9
|
+
*
|
|
10
|
+
* 트윈 모델 JSON 에 선언하는 길도 있었는데 그러지 않은 이유가 셋이다.
|
|
11
|
+
*
|
|
12
|
+
* · **유효기간을 담을 자리가 없다.** 라우팅은 개정된다. 모델에 두면 「언제부터 이 라우팅였나」가 없고,
|
|
13
|
+
* 그러면 지난 실적이 **어느 라우팅으로 만든 것인지** 잃는다. 정산과 추적이 그 위에 선다.
|
|
14
|
+
* · **MES 가 트윈 없이 배포된다.** 라우팅이 모델에 살면 MES 가 트윈을 세워야 자기 지시서를 만든다.
|
|
15
|
+
* · **표준이 그 자리에 둔다.** `OperationsDefinition` 은 Level 4·3 의 마스터이고 실행 모델이 아니다.
|
|
16
|
+
*
|
|
17
|
+
* ── 순서의 정본은 `steps` 다 ──────────────────────────────────────────────
|
|
18
|
+
* `procedure`(ISA-88 절차 계층)는 그 위에 이름을 붙이는 것이다. 트리를 따로 두면 두 곳이 어긋날 수
|
|
19
|
+
* 있고, 어긋났을 때 어느 쪽이 맞는지 말할 근거가 없다(§`RouteDef.procedure`).
|
|
20
|
+
*/
|
|
21
|
+
export declare class RouteDefinition {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
domain?: Domain;
|
|
24
|
+
domainId?: string;
|
|
25
|
+
/** 라우팅 키 — 레시피와 오더가 이 값을 가리킨다(커널 `RouteDef.key`). */
|
|
26
|
+
name: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
/**
|
|
29
|
+
* 지나는 공정의 **순서** — `OperationDefinition.name` 의 목록(커널 `RouteDef.steps`).
|
|
30
|
+
*
|
|
31
|
+
* 이름으로 가리킨다. 외래키로 묶지 않는 이유는, 공정이 유효기간으로 끝나도 그것을 지나간 지난 기록이
|
|
32
|
+
* 가리킬 것을 잃지 않아야 하기 때문이다 — 마스터의 다른 축도 같은 규율이다.
|
|
33
|
+
*/
|
|
34
|
+
steps: string[];
|
|
35
|
+
/** ISA-88 절차 계층 — 선언하지 않으면 `steps` 만으로 돈다(커널 `RouteDef.procedure`). */
|
|
36
|
+
procedure?: Record<string, unknown>[];
|
|
37
|
+
/** 언제부터 유효한가 — 표준 `EffectiveStartDate`. */
|
|
38
|
+
effectiveStart?: Date;
|
|
39
|
+
/**
|
|
40
|
+
* 언제까지 유효한가 — 표준 `EffectiveEndDate`.
|
|
41
|
+
*
|
|
42
|
+
* **없앨 때 행을 지우지 않고 이 칸을 채운다.** 지우면 그것으로 만든 지난 기록이 가리킬 것을 잃는다.
|
|
43
|
+
*/
|
|
44
|
+
effectiveEnd?: Date;
|
|
45
|
+
createdAt?: Date;
|
|
46
|
+
updatedAt?: Date;
|
|
47
|
+
creator?: User;
|
|
48
|
+
creatorId?: string;
|
|
49
|
+
updater?: User;
|
|
50
|
+
updaterId?: string;
|
|
51
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RouteDefinition = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const typeorm_1 = require("typeorm");
|
|
6
|
+
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const shell_1 = require("@things-factory/shell");
|
|
8
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
9
|
+
/**
|
|
10
|
+
* 라우팅 — **공정을 지나는 순서**. 커널 `RouteDef` 와 같은 모양이다.
|
|
11
|
+
*
|
|
12
|
+
* ── 왜 마스터에 있나 (2026-08-31) ────────────────────────────────────────
|
|
13
|
+
* 커널에 `RouteDef` 가 있고 `JobOrder.routeKey` 가 그것을 가리키는데, **그 값이 가리킬 표가 없었다.**
|
|
14
|
+
* 사람이 문자열을 손으로 적는 상태였고, 그래서 MES 가 받은 작업지시에 라우팅을 자동으로 붙일 수 없었다.
|
|
15
|
+
*
|
|
16
|
+
* 트윈 모델 JSON 에 선언하는 길도 있었는데 그러지 않은 이유가 셋이다.
|
|
17
|
+
*
|
|
18
|
+
* · **유효기간을 담을 자리가 없다.** 라우팅은 개정된다. 모델에 두면 「언제부터 이 라우팅였나」가 없고,
|
|
19
|
+
* 그러면 지난 실적이 **어느 라우팅으로 만든 것인지** 잃는다. 정산과 추적이 그 위에 선다.
|
|
20
|
+
* · **MES 가 트윈 없이 배포된다.** 라우팅이 모델에 살면 MES 가 트윈을 세워야 자기 지시서를 만든다.
|
|
21
|
+
* · **표준이 그 자리에 둔다.** `OperationsDefinition` 은 Level 4·3 의 마스터이고 실행 모델이 아니다.
|
|
22
|
+
*
|
|
23
|
+
* ── 순서의 정본은 `steps` 다 ──────────────────────────────────────────────
|
|
24
|
+
* `procedure`(ISA-88 절차 계층)는 그 위에 이름을 붙이는 것이다. 트리를 따로 두면 두 곳이 어긋날 수
|
|
25
|
+
* 있고, 어긋났을 때 어느 쪽이 맞는지 말할 근거가 없다(§`RouteDef.procedure`).
|
|
26
|
+
*/
|
|
27
|
+
let RouteDefinition = class RouteDefinition {
|
|
28
|
+
};
|
|
29
|
+
exports.RouteDefinition = RouteDefinition;
|
|
30
|
+
tslib_1.__decorate([
|
|
31
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
32
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID),
|
|
33
|
+
tslib_1.__metadata("design:type", String)
|
|
34
|
+
], RouteDefinition.prototype, "id", void 0);
|
|
35
|
+
tslib_1.__decorate([
|
|
36
|
+
(0, typeorm_1.ManyToOne)(type => shell_1.Domain),
|
|
37
|
+
(0, type_graphql_1.Field)(type => shell_1.Domain),
|
|
38
|
+
tslib_1.__metadata("design:type", shell_1.Domain)
|
|
39
|
+
], RouteDefinition.prototype, "domain", void 0);
|
|
40
|
+
tslib_1.__decorate([
|
|
41
|
+
(0, typeorm_1.RelationId)((route) => route.domain),
|
|
42
|
+
tslib_1.__metadata("design:type", String)
|
|
43
|
+
], RouteDefinition.prototype, "domainId", void 0);
|
|
44
|
+
tslib_1.__decorate([
|
|
45
|
+
(0, typeorm_1.Column)(),
|
|
46
|
+
(0, type_graphql_1.Field)(),
|
|
47
|
+
tslib_1.__metadata("design:type", String)
|
|
48
|
+
], RouteDefinition.prototype, "name", void 0);
|
|
49
|
+
tslib_1.__decorate([
|
|
50
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
51
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
52
|
+
tslib_1.__metadata("design:type", String)
|
|
53
|
+
], RouteDefinition.prototype, "description", void 0);
|
|
54
|
+
tslib_1.__decorate([
|
|
55
|
+
(0, typeorm_1.Column)({ type: 'simple-json' }),
|
|
56
|
+
(0, type_graphql_1.Field)(type => [String]),
|
|
57
|
+
tslib_1.__metadata("design:type", Array)
|
|
58
|
+
], RouteDefinition.prototype, "steps", void 0);
|
|
59
|
+
tslib_1.__decorate([
|
|
60
|
+
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
61
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'ProcedureElementDef[]' }),
|
|
62
|
+
tslib_1.__metadata("design:type", Array)
|
|
63
|
+
], RouteDefinition.prototype, "procedure", void 0);
|
|
64
|
+
tslib_1.__decorate([
|
|
65
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
66
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
67
|
+
tslib_1.__metadata("design:type", Date
|
|
68
|
+
/**
|
|
69
|
+
* 언제까지 유효한가 — 표준 `EffectiveEndDate`.
|
|
70
|
+
*
|
|
71
|
+
* **없앨 때 행을 지우지 않고 이 칸을 채운다.** 지우면 그것으로 만든 지난 기록이 가리킬 것을 잃는다.
|
|
72
|
+
*/
|
|
73
|
+
)
|
|
74
|
+
], RouteDefinition.prototype, "effectiveStart", void 0);
|
|
75
|
+
tslib_1.__decorate([
|
|
76
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
77
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
78
|
+
tslib_1.__metadata("design:type", Date)
|
|
79
|
+
], RouteDefinition.prototype, "effectiveEnd", void 0);
|
|
80
|
+
tslib_1.__decorate([
|
|
81
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
82
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
83
|
+
tslib_1.__metadata("design:type", Date)
|
|
84
|
+
], RouteDefinition.prototype, "createdAt", void 0);
|
|
85
|
+
tslib_1.__decorate([
|
|
86
|
+
(0, typeorm_1.UpdateDateColumn)(),
|
|
87
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
88
|
+
tslib_1.__metadata("design:type", Date)
|
|
89
|
+
], RouteDefinition.prototype, "updatedAt", void 0);
|
|
90
|
+
tslib_1.__decorate([
|
|
91
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
92
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
|
|
93
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
94
|
+
], RouteDefinition.prototype, "creator", void 0);
|
|
95
|
+
tslib_1.__decorate([
|
|
96
|
+
(0, typeorm_1.RelationId)((route) => route.creator),
|
|
97
|
+
tslib_1.__metadata("design:type", String)
|
|
98
|
+
], RouteDefinition.prototype, "creatorId", void 0);
|
|
99
|
+
tslib_1.__decorate([
|
|
100
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
101
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
|
|
102
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
103
|
+
], RouteDefinition.prototype, "updater", void 0);
|
|
104
|
+
tslib_1.__decorate([
|
|
105
|
+
(0, typeorm_1.RelationId)((route) => route.updater),
|
|
106
|
+
tslib_1.__metadata("design:type", String)
|
|
107
|
+
], RouteDefinition.prototype, "updaterId", void 0);
|
|
108
|
+
exports.RouteDefinition = RouteDefinition = tslib_1.__decorate([
|
|
109
|
+
(0, typeorm_1.Entity)({ name: 'ops_route_definition' }),
|
|
110
|
+
(0, typeorm_1.Index)('ix_ops_route_definition_0', (route) => [route.domain, route.name], { unique: true }),
|
|
111
|
+
(0, type_graphql_1.ObjectType)({ description: 'Route — the ordered operations a material passes through (kernel RouteDef).' })
|
|
112
|
+
], RouteDefinition);
|
|
113
|
+
//# sourceMappingURL=route-definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-definition.js","sourceRoot":"","sources":["../../../server/service/recipe/route-definition.ts"],"names":[],"mappings":"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","sourcesContent":["import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\nimport { Field, ID, ObjectType } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\n/**\n * 라우팅 — **공정을 지나는 순서**. 커널 `RouteDef` 와 같은 모양이다.\n *\n * ── 왜 마스터에 있나 (2026-08-31) ────────────────────────────────────────\n * 커널에 `RouteDef` 가 있고 `JobOrder.routeKey` 가 그것을 가리키는데, **그 값이 가리킬 표가 없었다.**\n * 사람이 문자열을 손으로 적는 상태였고, 그래서 MES 가 받은 작업지시에 라우팅을 자동으로 붙일 수 없었다.\n *\n * 트윈 모델 JSON 에 선언하는 길도 있었는데 그러지 않은 이유가 셋이다.\n *\n * · **유효기간을 담을 자리가 없다.** 라우팅은 개정된다. 모델에 두면 「언제부터 이 라우팅였나」가 없고,\n * 그러면 지난 실적이 **어느 라우팅으로 만든 것인지** 잃는다. 정산과 추적이 그 위에 선다.\n * · **MES 가 트윈 없이 배포된다.** 라우팅이 모델에 살면 MES 가 트윈을 세워야 자기 지시서를 만든다.\n * · **표준이 그 자리에 둔다.** `OperationsDefinition` 은 Level 4·3 의 마스터이고 실행 모델이 아니다.\n *\n * ── 순서의 정본은 `steps` 다 ──────────────────────────────────────────────\n * `procedure`(ISA-88 절차 계층)는 그 위에 이름을 붙이는 것이다. 트리를 따로 두면 두 곳이 어긋날 수\n * 있고, 어긋났을 때 어느 쪽이 맞는지 말할 근거가 없다(§`RouteDef.procedure`).\n */\n@Entity({ name: 'ops_route_definition' })\n@Index('ix_ops_route_definition_0', (route: RouteDefinition) => [route.domain, route.name], { unique: true })\n@ObjectType({ description: 'Route — the ordered operations a material passes through (kernel RouteDef).' })\nexport class RouteDefinition {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain)\n domain?: Domain\n\n @RelationId((route: RouteDefinition) => route.domain)\n domainId?: string\n\n /** 라우팅 키 — 레시피와 오더가 이 값을 가리킨다(커널 `RouteDef.key`). */\n @Column()\n @Field()\n name: string\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n description?: string\n\n /**\n * 지나는 공정의 **순서** — `OperationDefinition.name` 의 목록(커널 `RouteDef.steps`).\n *\n * 이름으로 가리킨다. 외래키로 묶지 않는 이유는, 공정이 유효기간으로 끝나도 그것을 지나간 지난 기록이\n * 가리킬 것을 잃지 않아야 하기 때문이다 — 마스터의 다른 축도 같은 규율이다.\n */\n @Column({ type: 'simple-json' })\n @Field(type => [String])\n steps: string[]\n\n /** ISA-88 절차 계층 — 선언하지 않으면 `steps` 만으로 돈다(커널 `RouteDef.procedure`). */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'ProcedureElementDef[]' })\n procedure?: Record<string, unknown>[]\n\n /** 언제부터 유효한가 — 표준 `EffectiveStartDate`. */\n @Column({ nullable: true })\n @Field({ nullable: true })\n effectiveStart?: Date\n\n /**\n * 언제까지 유효한가 — 표준 `EffectiveEndDate`.\n *\n * **없앨 때 행을 지우지 않고 이 칸을 채운다.** 지우면 그것으로 만든 지난 기록이 가리킬 것을 잃는다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true })\n effectiveEnd?: Date\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((route: RouteDefinition) => route.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((route: RouteDefinition) => route.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ResourceClassFields } from './resource-class';
|
|
2
|
+
/**
|
|
3
|
+
* 등급 상속을 걷는다 — **`baseIds` 는 네 등급 표에 다 선언되어 있는데 아무도 걷지 않았다.**
|
|
4
|
+
*
|
|
5
|
+
* 표준 `MaterialClassBaseID` · `PersonnelClassBaseID` 는 등급이 등급을 상속한다고 말한다. 우리 표에도
|
|
6
|
+
* 칸이 있고 화면에서 편집도 되고 트윈에도 나간다. 그런데 그 값을 **읽어서 무엇을 답하는 곳이 한 군데도
|
|
7
|
+
* 없었다.** 그래서 「이 품목이 완제품인가」를 물으면 등급 이름 `MC-ECU-FG` 가 나왔다 — 사람은 읽지만
|
|
8
|
+
* 화면은 못 읽는다.
|
|
9
|
+
*
|
|
10
|
+
* ISA-95 에는 「완제품/반제품/원재료」를 담는 전용 요소가 없다. `MaterialDefinitionType` 을 전수로 보면
|
|
11
|
+
* `ID` · `Version` · `Description*` · `PublishedDate` · `EffectiveStartDate`/`EndDate` · `HierarchyScope` ·
|
|
12
|
+
* `SpatialDefinition` · `MaterialDefinitionProperty*` · `MaterialClassID*` · `MaterialLotSourceID*` ·
|
|
13
|
+
* `TestSpecificationID*` · `AssemblyDefinition*` 뿐이다. 표준이 그 구분을 두는 자리는 **등급**이고,
|
|
14
|
+
* 등급 표의 주석도 「원자재·완제품처럼 품목을 묶는 상위 개념」이라고 적고 있다.
|
|
15
|
+
*
|
|
16
|
+
* 그러니 새 축을 만들지 않는다. 이미 있는 상속을 걷는다.
|
|
17
|
+
*/
|
|
18
|
+
/** 등급 이름 → 등급. 이름이 등급의 식별자다(표준 `MaterialClassID`). */
|
|
19
|
+
export type ClassIndex = ReadonlyMap<string, ResourceClassFields>;
|
|
20
|
+
/**
|
|
21
|
+
* 한 등급에서 위로 걸어 **뿌리 등급**들을 낸다.
|
|
22
|
+
*
|
|
23
|
+
* 뿌리는 `baseIds` 가 없는 등급이다. 「완제품」·「반제품」·「원재료」처럼 더 위가 없는 것.
|
|
24
|
+
*
|
|
25
|
+
* 답이 여럿일 수 있다 — 한 등급이 두 갈래를 상속하면 뿌리가 둘이다. **하나로 줄이지 않는다.**
|
|
26
|
+
* 줄이면 화면이 「완제품」이라고 단정하는데 실제로는 「완제품이면서 반제품」인 모순을 감춘다. 여럿이면
|
|
27
|
+
* 여럿으로 내고, 그것을 본 사람이 등급을 고치게 한다.
|
|
28
|
+
*/
|
|
29
|
+
export declare function rootClassesOf(className: string, index: ClassIndex): string[];
|
|
30
|
+
/**
|
|
31
|
+
* 한 등급에서 뿌리까지의 **경로**를 낸다 — 뿌리가 앞, 자기가 뒤.
|
|
32
|
+
*
|
|
33
|
+
* `['원재료', 'ECU 기구부품']` 처럼 읽는다. 화면이 이것을 그대로 보이면 「이 품목이 무엇인가」를
|
|
34
|
+
* 사람이 한 번에 읽는다.
|
|
35
|
+
*
|
|
36
|
+
* 갈래가 여럿이면 **첫 갈래만** 낸다. 경로는 보여 주기 위한 것이고, 판정은 `rootClassesOf` 로 한다.
|
|
37
|
+
* 여기서 여러 경로를 다 내면 화면 한 칸에 못 담는다.
|
|
38
|
+
*/
|
|
39
|
+
export declare function classPathOf(className: string, index: ClassIndex): string[];
|
|
40
|
+
/**
|
|
41
|
+
* 품목 하나가 어느 뿌리 등급들에 드는가 — 등급이 여럿이니 뿌리도 여럿일 수 있다.
|
|
42
|
+
*
|
|
43
|
+
* **등급이 하나도 없으면 빈 배열이다.** 「원재료」로 넘겨짚지 않는다 — 등급을 안 붙인 품목과 원재료를
|
|
44
|
+
* 섞으면, 붙이는 것을 잊었다는 사실이 화면에서 사라진다.
|
|
45
|
+
*/
|
|
46
|
+
export declare function rootClassesOfMaterial(classNames: string[] | undefined, index: ClassIndex): string[];
|