@things-factory/ops-master 10.0.19 → 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 -182
- 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 +4 -1
- package/dist-server/service/index.js +11 -2
- 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.js +2 -2
- 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/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/personnel/person.js +3 -3
- package/dist-server/service/personnel/person.js.map +1 -1
- 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/recipe/recipe-definition.d.ts +3 -3
- package/dist-server/service/recipe/recipe-definition.js +3 -3
- package/dist-server/service/recipe/recipe-definition.js.map +1 -1
- package/dist-server/service/recipe/recipe-master-resolver.d.ts +1 -1
- package/dist-server/service/recipe/recipe-master-resolver.js +1 -1
- package/dist-server/service/recipe/recipe-master-resolver.js.map +1 -1
- package/dist-server/service/recipe/recipe-master.d.ts +1 -1
- package/dist-server/service/recipe/recipe-master.js +2 -2
- package/dist-server/service/recipe/recipe-master.js.map +1 -1
- package/dist-server/service/recipe/recipe-query.d.ts +11 -3
- package/dist-server/service/recipe/recipe-query.js +30 -9
- package/dist-server/service/recipe/recipe-query.js.map +1 -1
- package/dist-server/service/recipe/route-definition.d.ts +6 -6
- package/dist-server/service/recipe/route-definition.js +6 -6
- package/dist-server/service/recipe/route-definition.js.map +1 -1
- 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/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 +86 -3
- package/translations/ja.json +92 -1
- package/translations/ko.json +93 -10
- package/translations/ms.json +92 -1
- package/translations/zh.json +92 -1
- package/dist-client/pages/master-list.d.ts +0 -68
- package/dist-client/pages/master-list.js +0 -239
- package/dist-client/pages/master-list.js.map +0 -1
|
@@ -53,7 +53,7 @@ tslib_1.__decorate([
|
|
|
53
53
|
], EquipmentClass.prototype, "testSpecificationIds", void 0);
|
|
54
54
|
tslib_1.__decorate([
|
|
55
55
|
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
56
|
-
(0, type_graphql_1.Field)(type =>
|
|
56
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'ResourceProperty[]' }),
|
|
57
57
|
tslib_1.__metadata("design:type", Array)
|
|
58
58
|
], EquipmentClass.prototype, "properties", void 0);
|
|
59
59
|
tslib_1.__decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"equipment-class.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-class.ts"],"names":[],"mappings":";;;;AAAA,qCASgB;AAChB,+CAAoD;AAEpD,
|
|
1
|
+
{"version":3,"file":"equipment-class.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-class.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} 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 * 설비 등급 — **ISA-95 `EquipmentClass`**.\n *\n * 공정은 특정 설비를 지목하지 않고 등급으로 요구한다 — 「용접기 1대」. 등급이 없으면 그 요구를 적을 수\n * 없고, 대체 설비를 찾을 수도 없다.\n *\n * 구조는 인원 등급과 같다(표준이 셋을 같은 모양으로 정의한다). 옮기는 함수도 같은 것을 쓴다.\n */\n@Entity({ name: 'ops_equipment_class' })\n@Index('ix_ops_equipment_class_0', (klass: EquipmentClass) => [klass.domain, klass.name], { unique: true })\n@ObjectType({ description: 'ISA-95 EquipmentClass — a kind of equipment that operations require' })\nexport class EquipmentClass {\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((klass: EquipmentClass) => klass.domain)\n domainId?: string\n\n /** 표준 `EquipmentClassID`. */\n @Column()\n @Field()\n name: string\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n description?: string\n\n /** 상위 등급들 — 표준 `EquipmentClassBaseID`(복수). 「6축 용접기」가 「용접기」를 상속한다. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => [String], { nullable: true })\n baseIds?: string[]\n\n /** 이 등급의 적격을 정하는 `TestSpecification` 참조들 — 표준 `TestSpecificationID`. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => [String], { nullable: true })\n testSpecificationIds?: string[]\n\n /** 등급 속성 — 표준 `EquipmentClassProperty`. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'ResourceProperty[]' })\n properties?: Record<string, unknown>[]\n\n /** 언제부터 유효한가 — 표준 `EffectiveStartDate`. */\n @Column({ nullable: true })\n @Field({ nullable: true })\n effectiveStart?: Date\n\n /** 언제까지 유효한가 — 표준 `EffectiveEndDate`. */\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((klass: EquipmentClass) => klass.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((klass: EquipmentClass) => klass.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -19,6 +19,15 @@ export declare class EquipmentClassList {
|
|
|
19
19
|
}
|
|
20
20
|
export declare class EquipmentClassResolver {
|
|
21
21
|
equipmentClasses(params: ListParam, context: ResolverContext): Promise<EquipmentClassList>;
|
|
22
|
+
/**
|
|
23
|
+
* 이 등급에 든 설비들
|
|
24
|
+
*
|
|
25
|
+
* 아무도 안 들면 빈 목록이다. 다만 그것이 「없다」인지 「다 못 봤다」인지는 `memberScanCapped`
|
|
26
|
+
* 가 말한다 — 조용히 자르면 고쳐야 할 선언과 멀쩡한 등급이 같아 보인다.
|
|
27
|
+
*/
|
|
28
|
+
members(klass: EquipmentClass, context: ResolverContext): Promise<string[]>;
|
|
29
|
+
/** 소속을 다 보지 못했나. */
|
|
30
|
+
memberScanCapped(klass: EquipmentClass, context: ResolverContext): Promise<boolean>;
|
|
22
31
|
/**
|
|
23
32
|
* 그리드가 보낸 변경을 한 번에 적용한다.
|
|
24
33
|
*
|
|
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.StopReasonResolver = exports.StopReasonList = exports.EquipmentResolver = exports.EquipmentList = exports.EquipmentClassResolver = exports.EquipmentClassList = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const state_period_rules_js_1 = require("./state-period-rules.js");
|
|
6
7
|
const shell_1 = require("@things-factory/shell");
|
|
7
8
|
const master_crud_1 = require("../master-crud");
|
|
8
9
|
const master_axis_1 = require("../master-axis");
|
|
9
10
|
const master_list_1 = require("../master-list");
|
|
11
|
+
const class_members_1 = require("../resource/class-members");
|
|
10
12
|
const equipment_class_1 = require("./equipment-class");
|
|
11
13
|
const equipment_1 = require("./equipment");
|
|
12
14
|
const stop_reason_1 = require("./stop-reason");
|
|
@@ -34,12 +36,38 @@ tslib_1.__decorate([
|
|
|
34
36
|
exports.EquipmentClassList = EquipmentClassList = tslib_1.__decorate([
|
|
35
37
|
(0, type_graphql_1.ObjectType)({ description: 'A page of equipment classes' })
|
|
36
38
|
], EquipmentClassList);
|
|
39
|
+
/**
|
|
40
|
+
* **이 등급에 무엇이 드나** — 들어오는 관계.
|
|
41
|
+
*
|
|
42
|
+
* 등급을 만들어 놓고 아무도 안 들어 있는 일이 실제로 있었다. 화면에는 등급 이름만 있어서 그 사실이
|
|
43
|
+
* 안 보였다. 없앨 때 무엇이 딸려 자격을 잃는지도 알 수 없었다.
|
|
44
|
+
*
|
|
45
|
+
* 세는 방식과 상한은 `class-members.ts` 머리말에 적었다 — 등급 넷이 같은 함수를 쓴다.
|
|
46
|
+
*/
|
|
47
|
+
function equipmentClassMembersOf(context) {
|
|
48
|
+
const state = context.state;
|
|
49
|
+
state.equipmentClassMembers = state.equipmentClassMembers || (0, class_members_1.scanClassMembers)(equipment_1.Equipment, 'equipmentClassIds', state.domain);
|
|
50
|
+
return state.equipmentClassMembers;
|
|
51
|
+
}
|
|
37
52
|
let EquipmentClassResolver = class EquipmentClassResolver {
|
|
38
53
|
async equipmentClasses(params, context) {
|
|
39
54
|
const { domain } = context.state;
|
|
40
55
|
const { items, total } = await (0, master_list_1.listMaster)('equipmentClass', params, domain);
|
|
41
56
|
return { items: items, total };
|
|
42
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* 이 등급에 든 설비들
|
|
60
|
+
*
|
|
61
|
+
* 아무도 안 들면 빈 목록이다. 다만 그것이 「없다」인지 「다 못 봤다」인지는 `memberScanCapped`
|
|
62
|
+
* 가 말한다 — 조용히 자르면 고쳐야 할 선언과 멀쩡한 등급이 같아 보인다.
|
|
63
|
+
*/
|
|
64
|
+
async members(klass, context) {
|
|
65
|
+
return (await equipmentClassMembersOf(context)).members.get(klass.name) ?? [];
|
|
66
|
+
}
|
|
67
|
+
/** 소속을 다 보지 못했나. */
|
|
68
|
+
async memberScanCapped(klass, context) {
|
|
69
|
+
return (await equipmentClassMembersOf(context)).capped;
|
|
70
|
+
}
|
|
43
71
|
/**
|
|
44
72
|
* 그리드가 보낸 변경을 한 번에 적용한다.
|
|
45
73
|
*
|
|
@@ -66,6 +94,22 @@ tslib_1.__decorate([
|
|
|
66
94
|
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
67
95
|
tslib_1.__metadata("design:returntype", Promise)
|
|
68
96
|
], EquipmentClassResolver.prototype, "equipmentClasses", null);
|
|
97
|
+
tslib_1.__decorate([
|
|
98
|
+
(0, type_graphql_1.FieldResolver)(type => [String], { description: 'Equipment belonging to this class' }),
|
|
99
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
100
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
101
|
+
tslib_1.__metadata("design:type", Function),
|
|
102
|
+
tslib_1.__metadata("design:paramtypes", [equipment_class_1.EquipmentClass, Object]),
|
|
103
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
104
|
+
], EquipmentClassResolver.prototype, "members", null);
|
|
105
|
+
tslib_1.__decorate([
|
|
106
|
+
(0, type_graphql_1.FieldResolver)(type => Boolean, { description: 'True when members were too many to scan fully' }),
|
|
107
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
108
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
109
|
+
tslib_1.__metadata("design:type", Function),
|
|
110
|
+
tslib_1.__metadata("design:paramtypes", [equipment_class_1.EquipmentClass, Object]),
|
|
111
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
112
|
+
], EquipmentClassResolver.prototype, "memberScanCapped", null);
|
|
69
113
|
tslib_1.__decorate([
|
|
70
114
|
(0, type_graphql_1.Directive)('@privilege(category: "ops-master", privilege: "mutation", domainOwnerGranted: true)'),
|
|
71
115
|
(0, type_graphql_1.Directive)('@transaction'),
|
|
@@ -168,6 +212,20 @@ let StopReasonResolver = class StopReasonResolver {
|
|
|
168
212
|
async updateMultipleStopReason(patches, context) {
|
|
169
213
|
const { domain, user, tx } = context.state;
|
|
170
214
|
const axis = (0, master_axis_1.masterAxisOf)('stopReason');
|
|
215
|
+
/*
|
|
216
|
+
* **모르는 상태로는 저장하지 않는다.** 이 값이 가동률을 깎느냐 마느냐를 정하므로, 목록 밖 값이
|
|
217
|
+
* 들어오면 그 사유를 쓴 구간이 전부 어긋남으로 걸린다 — 잘못은 여기서 났는데 불은 거기서 켜진다.
|
|
218
|
+
*
|
|
219
|
+
* 지우는 패치(`retire`)는 상태를 다시 말하지 않으므로 값이 있을 때만 본다.
|
|
220
|
+
*/
|
|
221
|
+
for (const patch of patches) {
|
|
222
|
+
const said = patch?.status;
|
|
223
|
+
if (said === undefined || said === null)
|
|
224
|
+
continue;
|
|
225
|
+
const gap = (0, state_period_rules_js_1.stopReasonStatusGap)(said);
|
|
226
|
+
if (gap)
|
|
227
|
+
throw new Error(`정지 사유 "${patch?.name ?? ''}" — ${gap}`);
|
|
228
|
+
}
|
|
171
229
|
const saved = await (0, master_crud_1.saveMasterPatches)(tx, domain, axis.entity, patches, user, {
|
|
172
230
|
hasEffectivePeriod: axis.hasEffectivePeriod
|
|
173
231
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"equipment-master-resolver.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-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 { EquipmentClass } from './equipment-class'\nimport { Equipment } from './equipment'\nimport { StopReason } from './stop-reason'\n\n/**\n * 설비 축을 채우고 고친다.\n *\n * ── 왜 마스터는 그리드에서 고칠 수 있나 ────────────────────────────────────\n * 업무 기록과 달리 마스터는 **선언**이다. 「이 사람이 용접 자격을 갖는다」는 일어난 일이 아니라 지금의\n * 규정이고, 규정은 바뀐다. 없앨 때 행을 지우지 않고 유효 기간의 끝을 채우는 것이 그래서다 —\n * 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다.\n *\n * 규칙은 `master-crud.ts` 한 곳에 있다. 여기는 축의 이름만 붙인다.\n */\n\n@ObjectType({ description: 'A page of equipment classes' })\nexport class EquipmentClassList {\n @Field(type => [EquipmentClass])\n items: EquipmentClass[]\n\n @Field(type => Int)\n total: number\n}\n\n@Resolver(EquipmentClass)\nexport class EquipmentClassResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EquipmentClassList, { description: 'To fetch equipment classes' })\n async equipmentClasses(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EquipmentClassList> {\n const { domain } = context.state\n const { items, total } = await listMaster('equipmentClass', params, domain)\n\n return { items: items as EquipmentClass[], total }\n }\n\n /**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 패치를 `ScalarObject` 로 받는다 — 축마다 입력 타입을 따로 만들면 칸을 하나 더할 때마다 두 곳을\n * 고쳐야 하고, 한쪽을 빠뜨리면 그 칸이 오류 보고 없이 저장되지 않는다. 돌려주는 것은 타입이 있는\n * 엔티티라 무엇이 저장됐는지 스키마로 확인할 수 있다.\n */\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [EquipmentClass], { description: 'To create, change or retire equipment classes' })\n async updateMultipleEquipmentClass(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<EquipmentClass[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('equipmentClass')\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as EquipmentClass[]\n }\n}\n\n@ObjectType({ description: 'A page of equipment' })\nexport class EquipmentList {\n @Field(type => [Equipment])\n items: Equipment[]\n\n @Field(type => Int)\n total: number\n}\n\n@Resolver(Equipment)\nexport class EquipmentResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EquipmentList, { description: 'To fetch equipment' })\n async equipmentList(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EquipmentList> {\n const { domain } = context.state\n const { items, total } = await listMaster('equipment', params, domain)\n\n return { items: items as Equipment[], total }\n }\n\n /**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 패치를 `ScalarObject` 로 받는다 — 축마다 입력 타입을 따로 만들면 칸을 하나 더할 때마다 두 곳을\n * 고쳐야 하고, 한쪽을 빠뜨리면 그 칸이 오류 보고 없이 저장되지 않는다. 돌려주는 것은 타입이 있는\n * 엔티티라 무엇이 저장됐는지 스키마로 확인할 수 있다.\n */\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [Equipment], { description: 'To create, change or retire equipment' })\n async updateMultipleEquipment(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<Equipment[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('equipment')\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as Equipment[]\n }\n}\n\n@ObjectType({ description: 'A page of stop reasons' })\nexport class StopReasonList {\n @Field(type => [StopReason])\n items: StopReason[]\n\n @Field(type => Int)\n total: number\n}\n\n@Resolver(StopReason)\nexport class StopReasonResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => StopReasonList, { description: 'To fetch stop reasons' })\n async stopReasonList(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<StopReasonList> {\n const { domain } = context.state\n const { items, total } = await listMaster('stopReason', params, domain)\n\n return { items: items as StopReason[], total }\n }\n\n /**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 패치를 `ScalarObject` 로 받는다 — 축마다 입력 타입을 따로 만들면 칸을 하나 더할 때마다 두 곳을\n * 고쳐야 하고, 한쪽을 빠뜨리면 그 칸이 오류 보고 없이 저장되지 않는다. 돌려주는 것은 타입이 있는\n * 엔티티라 무엇이 저장됐는지 스키마로 확인할 수 있다.\n */\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [StopReason], { description: 'To create, change or retire stop reasons' })\n async updateMultipleStopReason(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<StopReason[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('stopReason')\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as StopReason[]\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"equipment-master-resolver.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-master-resolver.ts"],"names":[],"mappings":";;;;AAAA,+CAAgI;AAChI,mEAA6D;AAE7D,iDAAuE;AAEvE,gDAA+D;AAC/D,gDAA6C;AAC7C,gDAA2C;AAC3C,6DAA0E;AAC1E,uDAAkD;AAClD,2CAAuC;AACvC,+CAA0C;AAE1C;;;;;;;;;GASG;AAGI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;CAM9B,CAAA;AANY,gDAAkB;AAE7B;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,gCAAc,CAAC,CAAC;;iDACT;AAGvB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,CAAC;;iDACN;6BALF,kBAAkB;IAD9B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,6BAA6B,EAAE,CAAC;GAC9C,kBAAkB,CAM9B;AAED;;;;;;;GAOG;AACH,SAAS,uBAAuB,CAAC,OAAwB;IACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAA0E,CAAA;IAEhG,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,IAAI,IAAA,gCAAgB,EAAC,qBAAS,EAAE,mBAAmB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAE3H,OAAO,KAAK,CAAC,qBAAqB,CAAA;AACpC,CAAC;AAGM,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;IAG3B,AAAN,KAAK,CAAC,gBAAgB,CAA0B,MAAiB,EAAS,OAAwB;QAChG,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAChC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,IAAA,wBAAU,EAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAE3E,OAAO,EAAE,KAAK,EAAE,KAAyB,EAAE,KAAK,EAAE,CAAA;IACpD,CAAC;IAED;;;;;OAKG;IAEG,AAAN,KAAK,CAAC,OAAO,CAAS,KAAqB,EAAS,OAAwB;QAC1E,OAAO,CAAC,MAAM,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAC/E,CAAC;IAED,oBAAoB;IAEd,AAAN,KAAK,CAAC,gBAAgB,CAAS,KAAqB,EAAS,OAAwB;QACnF,OAAO,CAAC,MAAM,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAA;IACxD,CAAC;IAED;;;;;;OAMG;IAIG,AAAN,KAAK,CAAC,4BAA4B,CACQ,OAAsB,EACvD,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAC1C,MAAM,IAAI,GAAG,IAAA,0BAAY,EAAC,gBAAgB,CAAC,CAAA;QAE3C,MAAM,KAAK,GAAG,MAAM,IAAA,+BAAiB,EAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;YAC5E,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;SAC5C,CAAC,CAAA;QAEF,OAAO,KAAyB,CAAA;IAClC,CAAC;CACF,CAAA;AAlDY,wDAAsB;AAG3B;IAFL,IAAA,wBAAS,EAAC,kFAAkF,CAAC;IAC7F,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,kBAAkB,EAAE,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAC5D,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,iBAAS;;8DAKhE;AASK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;IACvE,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAAyB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAtB,gCAAc;;qDAE1C;AAIK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC;IACzE,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAAyB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAtB,gCAAc;;8DAEnD;AAYK;IAHL,IAAA,wBAAS,EAAC,qFAAqF,CAAC;IAChG,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,gCAAc,CAAC,EAAE,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC;IAErG,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,oBAAY,CAAC,CAAC,CAAA;IACtC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;0EAUP;iCAjDU,sBAAsB;IADlC,IAAA,uBAAQ,EAAC,gCAAc,CAAC;GACZ,sBAAsB,CAkDlC;AAGM,IAAM,aAAa,GAAnB,MAAM,aAAa;CAMzB,CAAA;AANY,sCAAa;AAExB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,qBAAS,CAAC,CAAC;;4CACT;AAGlB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,CAAC;;4CACN;wBALF,aAAa;IADzB,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;GACtC,aAAa,CAMzB;AAGM,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAGtB,AAAN,KAAK,CAAC,aAAa,CAA0B,MAAiB,EAAS,OAAwB;QAC7F,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAChC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,IAAA,wBAAU,EAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAEtE,OAAO,EAAE,KAAK,EAAE,KAAoB,EAAE,KAAK,EAAE,CAAA;IAC/C,CAAC;IAED;;;;;;OAMG;IAIG,AAAN,KAAK,CAAC,uBAAuB,CACa,OAAsB,EACvD,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAC1C,MAAM,IAAI,GAAG,IAAA,0BAAY,EAAC,WAAW,CAAC,CAAA;QAEtC,MAAM,KAAK,GAAG,MAAM,IAAA,+BAAiB,EAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;YAC5E,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;SAC5C,CAAC,CAAA;QAEF,OAAO,KAAoB,CAAA;IAC7B,CAAC;CACF,CAAA;AAjCY,8CAAiB;AAGtB;IAFL,IAAA,wBAAS,EAAC,kFAAkF,CAAC;IAC7F,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;IAClD,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,iBAAS;;sDAK7D;AAYK;IAHL,IAAA,wBAAS,EAAC,qFAAqF,CAAC;IAChG,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,qBAAS,CAAC,EAAE,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;IAExF,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,oBAAY,CAAC,CAAC,CAAA;IACtC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;gEAUP;4BAhCU,iBAAiB;IAD7B,IAAA,uBAAQ,EAAC,qBAAS,CAAC;GACP,iBAAiB,CAiC7B;AAGM,IAAM,cAAc,GAApB,MAAM,cAAc;CAM1B,CAAA;AANY,wCAAc;AAEzB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,wBAAU,CAAC,CAAC;;6CACT;AAGnB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,CAAC;;6CACN;yBALF,cAAc;IAD1B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;GACzC,cAAc,CAM1B;AAGM,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAGvB,AAAN,KAAK,CAAC,cAAc,CAA0B,MAAiB,EAAS,OAAwB;QAC9F,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAChC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,IAAA,wBAAU,EAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAEvE,OAAO,EAAE,KAAK,EAAE,KAAqB,EAAE,KAAK,EAAE,CAAA;IAChD,CAAC;IAED;;;;;;OAMG;IAIG,AAAN,KAAK,CAAC,wBAAwB,CACY,OAAsB,EACvD,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAC1C,MAAM,IAAI,GAAG,IAAA,0BAAY,EAAC,YAAY,CAAC,CAAA;QAEvC;;;;;WAKG;QACH,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAI,KAAa,EAAE,MAAM,CAAA;YACnC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI;gBAAE,SAAQ;YAEjD,MAAM,GAAG,GAAG,IAAA,2CAAmB,EAAC,IAAI,CAAC,CAAA;YACrC,IAAI,GAAG;gBAAE,MAAM,IAAI,KAAK,CAAC,UAAW,KAAa,EAAE,IAAI,IAAI,EAAE,OAAO,GAAG,EAAE,CAAC,CAAA;QAC5E,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAA,+BAAiB,EAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;YAC5E,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;SAC5C,CAAC,CAAA;QAEF,OAAO,KAAqB,CAAA;IAC9B,CAAC;CACF,CAAA;AA/CY,gDAAkB;AAGvB;IAFL,IAAA,wBAAS,EAAC,kFAAkF,CAAC;IAC7F,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;IACrD,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,iBAAS;;wDAK9D;AAYK;IAHL,IAAA,wBAAS,EAAC,qFAAqF,CAAC;IAChG,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,wBAAU,CAAC,EAAE,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC;IAE5F,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,oBAAY,CAAC,CAAC,CAAA;IACtC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;kEAwBP;6BA9CU,kBAAkB;IAD9B,IAAA,uBAAQ,EAAC,wBAAU,CAAC;GACR,kBAAkB,CA+C9B","sourcesContent":["import { FieldResolver, Root, Args, Arg, Ctx, Directive, Int, Mutation, ObjectType, Field, Query, Resolver } from 'type-graphql'\nimport { stopReasonStatusGap } from './state-period-rules.js'\n\nimport { Domain, ListParam, ScalarObject } from '@things-factory/shell'\n\nimport { MasterPatch, saveMasterPatches } from '../master-crud'\nimport { masterAxisOf } from '../master-axis'\nimport { listMaster } from '../master-list'\nimport { ClassMembers, scanClassMembers } from '../resource/class-members'\nimport { EquipmentClass } from './equipment-class'\nimport { Equipment } from './equipment'\nimport { StopReason } from './stop-reason'\n\n/**\n * 설비 축을 채우고 고친다.\n *\n * ── 왜 마스터는 그리드에서 고칠 수 있나 ────────────────────────────────────\n * 업무 기록과 달리 마스터는 **선언**이다. 「이 사람이 용접 자격을 갖는다」는 일어난 일이 아니라 지금의\n * 규정이고, 규정은 바뀐다. 없앨 때 행을 지우지 않고 유효 기간의 끝을 채우는 것이 그래서다 —\n * 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다.\n *\n * 규칙은 `master-crud.ts` 한 곳에 있다. 여기는 축의 이름만 붙인다.\n */\n\n@ObjectType({ description: 'A page of equipment classes' })\nexport class EquipmentClassList {\n @Field(type => [EquipmentClass])\n items: EquipmentClass[]\n\n @Field(type => Int)\n total: number\n}\n\n/**\n * **이 등급에 무엇이 드나** — 들어오는 관계.\n *\n * 등급을 만들어 놓고 아무도 안 들어 있는 일이 실제로 있었다. 화면에는 등급 이름만 있어서 그 사실이\n * 안 보였다. 없앨 때 무엇이 딸려 자격을 잃는지도 알 수 없었다.\n *\n * 세는 방식과 상한은 `class-members.ts` 머리말에 적었다 — 등급 넷이 같은 함수를 쓴다.\n */\nfunction equipmentClassMembersOf(context: ResolverContext): Promise<ClassMembers> {\n const state = context.state as { domain: Domain; equipmentClassMembers?: Promise<ClassMembers> }\n\n state.equipmentClassMembers = state.equipmentClassMembers || scanClassMembers(Equipment, 'equipmentClassIds', state.domain)\n\n return state.equipmentClassMembers\n}\n\n@Resolver(EquipmentClass)\nexport class EquipmentClassResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EquipmentClassList, { description: 'To fetch equipment classes' })\n async equipmentClasses(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EquipmentClassList> {\n const { domain } = context.state\n const { items, total } = await listMaster('equipmentClass', params, domain)\n\n return { items: items as EquipmentClass[], total }\n }\n\n /**\n * 이 등급에 든 설비들\n *\n * 아무도 안 들면 빈 목록이다. 다만 그것이 「없다」인지 「다 못 봤다」인지는 `memberScanCapped`\n * 가 말한다 — 조용히 자르면 고쳐야 할 선언과 멀쩡한 등급이 같아 보인다.\n */\n @FieldResolver(type => [String], { description: 'Equipment belonging to this class' })\n async members(@Root() klass: EquipmentClass, @Ctx() context: ResolverContext): Promise<string[]> {\n return (await equipmentClassMembersOf(context)).members.get(klass.name) ?? []\n }\n\n /** 소속을 다 보지 못했나. */\n @FieldResolver(type => Boolean, { description: 'True when members were too many to scan fully' })\n async memberScanCapped(@Root() klass: EquipmentClass, @Ctx() context: ResolverContext): Promise<boolean> {\n return (await equipmentClassMembersOf(context)).capped\n }\n\n /**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 패치를 `ScalarObject` 로 받는다 — 축마다 입력 타입을 따로 만들면 칸을 하나 더할 때마다 두 곳을\n * 고쳐야 하고, 한쪽을 빠뜨리면 그 칸이 오류 보고 없이 저장되지 않는다. 돌려주는 것은 타입이 있는\n * 엔티티라 무엇이 저장됐는지 스키마로 확인할 수 있다.\n */\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [EquipmentClass], { description: 'To create, change or retire equipment classes' })\n async updateMultipleEquipmentClass(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<EquipmentClass[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('equipmentClass')\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as EquipmentClass[]\n }\n}\n\n@ObjectType({ description: 'A page of equipment' })\nexport class EquipmentList {\n @Field(type => [Equipment])\n items: Equipment[]\n\n @Field(type => Int)\n total: number\n}\n\n@Resolver(Equipment)\nexport class EquipmentResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EquipmentList, { description: 'To fetch equipment' })\n async equipmentList(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EquipmentList> {\n const { domain } = context.state\n const { items, total } = await listMaster('equipment', params, domain)\n\n return { items: items as Equipment[], total }\n }\n\n /**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 패치를 `ScalarObject` 로 받는다 — 축마다 입력 타입을 따로 만들면 칸을 하나 더할 때마다 두 곳을\n * 고쳐야 하고, 한쪽을 빠뜨리면 그 칸이 오류 보고 없이 저장되지 않는다. 돌려주는 것은 타입이 있는\n * 엔티티라 무엇이 저장됐는지 스키마로 확인할 수 있다.\n */\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [Equipment], { description: 'To create, change or retire equipment' })\n async updateMultipleEquipment(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<Equipment[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('equipment')\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as Equipment[]\n }\n}\n\n@ObjectType({ description: 'A page of stop reasons' })\nexport class StopReasonList {\n @Field(type => [StopReason])\n items: StopReason[]\n\n @Field(type => Int)\n total: number\n}\n\n@Resolver(StopReason)\nexport class StopReasonResolver {\n @Directive('@privilege(category: \"ops-master\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => StopReasonList, { description: 'To fetch stop reasons' })\n async stopReasonList(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<StopReasonList> {\n const { domain } = context.state\n const { items, total } = await listMaster('stopReason', params, domain)\n\n return { items: items as StopReason[], total }\n }\n\n /**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 패치를 `ScalarObject` 로 받는다 — 축마다 입력 타입을 따로 만들면 칸을 하나 더할 때마다 두 곳을\n * 고쳐야 하고, 한쪽을 빠뜨리면 그 칸이 오류 보고 없이 저장되지 않는다. 돌려주는 것은 타입이 있는\n * 엔티티라 무엇이 저장됐는지 스키마로 확인할 수 있다.\n */\n @Directive('@privilege(category: \"ops-master\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => [StopReason], { description: 'To create, change or retire stop reasons' })\n async updateMultipleStopReason(\n @Arg('patches', type => [ScalarObject]) patches: MasterPatch[],\n @Ctx() context: ResolverContext\n ): Promise<StopReason[]> {\n const { domain, user, tx } = context.state\n const axis = masterAxisOf('stopReason')\n\n /*\n * **모르는 상태로는 저장하지 않는다.** 이 값이 가동률을 깎느냐 마느냐를 정하므로, 목록 밖 값이\n * 들어오면 그 사유를 쓴 구간이 전부 어긋남으로 걸린다 — 잘못은 여기서 났는데 불은 거기서 켜진다.\n *\n * 지우는 패치(`retire`)는 상태를 다시 말하지 않으므로 값이 있을 때만 본다.\n */\n for (const patch of patches) {\n const said = (patch as any)?.status\n if (said === undefined || said === null) continue\n\n const gap = stopReasonStatusGap(said)\n if (gap) throw new Error(`정지 사유 \"${(patch as any)?.name ?? ''}\" — ${gap}`)\n }\n\n const saved = await saveMasterPatches(tx, domain, axis.entity, patches, user, {\n hasEffectivePeriod: axis.hasEffectivePeriod\n })\n\n return saved as StopReason[]\n }\n}\n"]}
|
|
@@ -5,6 +5,7 @@ import type { EquipmentClass } from './equipment-class';
|
|
|
5
5
|
export interface EquipmentEntry {
|
|
6
6
|
id: string;
|
|
7
7
|
kind: string;
|
|
8
|
+
equipmentClassIds?: string[];
|
|
8
9
|
homeLocation: string;
|
|
9
10
|
identity?: string;
|
|
10
11
|
mtbfMs?: number;
|
|
@@ -20,8 +21,8 @@ export declare function toEquipmentEntry(equipment: Equipment): EquipmentEntry;
|
|
|
20
21
|
/**
|
|
21
22
|
* 설비 축 전체 — 트윈이 당겨 갈 조각.
|
|
22
23
|
*
|
|
23
|
-
* 설비가
|
|
24
|
-
* 등급이 나중에 오는 순간이 생긴다.
|
|
24
|
+
* 설비가 `equipmentClassIds` 로 등급을, `homeLocation` 으로 자리를 가리키므로 등급과 함께 나가야
|
|
25
|
+
* 한다. 한 건씩 밀면 설비가 먼저 도착하고 등급이 나중에 오는 순간이 생긴다.
|
|
25
26
|
*/
|
|
26
27
|
export declare function equipmentMaster(classes: EquipmentClass[], equipment: Equipment[]): {
|
|
27
28
|
equipmentClasses: ResourceClassDef[];
|
|
@@ -3,13 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.toEquipmentEntry = toEquipmentEntry;
|
|
4
4
|
exports.equipmentMaster = equipmentMaster;
|
|
5
5
|
const resource_class_1 = require("../resource/resource-class");
|
|
6
|
+
/*
|
|
7
|
+
* ── 커널이 받는 이름은 `homeLocationId` 다 ────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* 우리 칸 이름은 `homeLocation` 이고 커널의 마스터 접수는 `homeLocationId` 로 받는다. 이름이 하나
|
|
10
|
+
* 달라서 **값이 지나가고 아무도 안 읽었다** — 트윈의 설비 넷이 전부 자리 없이 앉아 있었다.
|
|
11
|
+
* 거절도 경고도 없었다. (인티그레이션 레인 실측, 2026-09-04)
|
|
12
|
+
*
|
|
13
|
+
* 값은 그대로다. 우리가 담는 것이 이미 자리 식별자(이름)라 옮길 것이 없고 이름만 맞춘다. 계약도
|
|
14
|
+
* 「붙박인 자리(마스터의 `homeLocationId`)」라고 적는다.
|
|
15
|
+
*
|
|
16
|
+
* 이 축은 셋 다 같다 — 인원 · 설비 · 자산. 하나만 고치면 나머지 둘이 계속 조용하다.
|
|
17
|
+
*/
|
|
6
18
|
function toEquipmentEntry(equipment) {
|
|
7
|
-
/* `kind` 와
|
|
19
|
+
/* `kind` 와 자리는 비울 수 없다 — 자리를 모르면 커널이 어디서 일하는지 정할 수 없다. */
|
|
8
20
|
const out = {
|
|
9
21
|
id: equipment.name,
|
|
10
22
|
kind: equipment.kind,
|
|
11
|
-
|
|
23
|
+
homeLocationId: equipment.homeLocation
|
|
12
24
|
};
|
|
25
|
+
/*
|
|
26
|
+
* 등급은 비어 있을 수 있다. 비면 커널이 `kind` 하나로 소속을 정한다 — 예전과 같다.
|
|
27
|
+
* 빈 배열을 내보내지 않는 것은 `put` 이 든다(값이 없으면 칸을 만들지 않는다).
|
|
28
|
+
*/
|
|
29
|
+
(0, resource_class_1.put)(out, 'equipmentClassIds', equipment.equipmentClassIds);
|
|
13
30
|
(0, resource_class_1.put)(out, 'identity', equipment.identity);
|
|
14
31
|
(0, resource_class_1.put)(out, 'mtbfMs', equipment.mtbfMs === undefined || equipment.mtbfMs === null ? undefined : Number(equipment.mtbfMs));
|
|
15
32
|
(0, resource_class_1.put)(out, 'mttrMs', equipment.mttrMs === undefined || equipment.mttrMs === null ? undefined : Number(equipment.mttrMs));
|
|
@@ -24,8 +41,8 @@ function toEquipmentEntry(equipment) {
|
|
|
24
41
|
/**
|
|
25
42
|
* 설비 축 전체 — 트윈이 당겨 갈 조각.
|
|
26
43
|
*
|
|
27
|
-
* 설비가
|
|
28
|
-
* 등급이 나중에 오는 순간이 생긴다.
|
|
44
|
+
* 설비가 `equipmentClassIds` 로 등급을, `homeLocation` 으로 자리를 가리키므로 등급과 함께 나가야
|
|
45
|
+
* 한다. 한 건씩 밀면 설비가 먼저 도착하고 등급이 나중에 오는 순간이 생긴다.
|
|
29
46
|
*/
|
|
30
47
|
function equipmentMaster(classes, equipment) {
|
|
31
48
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"equipment-master.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-master.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"equipment-master.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-master.ts"],"names":[],"mappings":";;AAmCA,4CAwBC;AAQD,0CAQC;AAzED,+DAAyE;AAqBzE;;;;;;;;;;;GAWG;AACH,SAAgB,gBAAgB,CAAC,SAAoB;IACnD,0DAA0D;IAC1D,MAAM,GAAG,GAA4B;QACnC,EAAE,EAAE,SAAS,CAAC,IAAI;QAClB,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,cAAc,EAAE,SAAS,CAAC,YAAY;KACvC,CAAA;IAED;;;OAGG;IACH,IAAA,oBAAG,EAAC,GAAG,EAAE,mBAAmB,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAA;IAC1D,IAAA,oBAAG,EAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAA;IACxC,IAAA,oBAAG,EAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;IACtH,IAAA,oBAAG,EAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;IACtH,IAAA,oBAAG,EAAC,GAAG,EAAE,cAAc,EAAE,SAAS,CAAC,YAAY,CAAC,CAAA;IAChD,IAAA,oBAAG,EAAC,GAAG,EAAE,YAAY,EAAE,SAAS,CAAC,UAAU,CAAC,CAAA;IAC5C,IAAA,oBAAG,EAAC,GAAG,EAAE,sBAAsB,EAAE,SAAS,CAAC,oBAAoB,CAAC,CAAA;IAChE,IAAA,oBAAG,EAAC,GAAG,EAAE,aAAa,EAAE,SAAS,CAAC,WAAW,CAAC,CAAA;IAC9C,IAAA,oBAAG,EAAC,GAAG,EAAE,gBAAgB,EAAE,IAAA,oBAAG,EAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAA;IACzD,IAAA,oBAAG,EAAC,GAAG,EAAE,cAAc,EAAE,IAAA,oBAAG,EAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAA;IAErD,OAAO,GAAgC,CAAA;AACzC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAC7B,OAAyB,EACzB,SAAsB;IAEtB,OAAO;QACL,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,mCAAkB,CAAC;QACjD,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC;KAC3C,CAAA;AACH,CAAC","sourcesContent":["import type { ResourceClassDef } from '@operato/ops-contract'\n\nimport { iso, put, toResourceClassDef } from '../resource/resource-class'\nimport type { Equipment } from './equipment'\nimport type { EquipmentClass } from './equipment-class'\n\n/** 트윈 `ReferenceMaster.equipment` 의 한 항목. */\nexport interface EquipmentEntry {\n id: string\n kind: string\n equipmentClassIds?: string[]\n homeLocation: string\n identity?: string\n mtbfMs?: number\n mttrMs?: number\n workCalendar?: unknown[]\n properties?: unknown[]\n testSpecificationIds?: string[]\n testResults?: unknown[]\n effectiveStart?: string\n effectiveEnd?: string\n}\n\n/*\n * ── 커널이 받는 이름은 `homeLocationId` 다 ────────────────────────────────\n *\n * 우리 칸 이름은 `homeLocation` 이고 커널의 마스터 접수는 `homeLocationId` 로 받는다. 이름이 하나\n * 달라서 **값이 지나가고 아무도 안 읽었다** — 트윈의 설비 넷이 전부 자리 없이 앉아 있었다.\n * 거절도 경고도 없었다. (인티그레이션 레인 실측, 2026-09-04)\n *\n * 값은 그대로다. 우리가 담는 것이 이미 자리 식별자(이름)라 옮길 것이 없고 이름만 맞춘다. 계약도\n * 「붙박인 자리(마스터의 `homeLocationId`)」라고 적는다.\n *\n * 이 축은 셋 다 같다 — 인원 · 설비 · 자산. 하나만 고치면 나머지 둘이 계속 조용하다.\n */\nexport function toEquipmentEntry(equipment: Equipment): EquipmentEntry {\n /* `kind` 와 자리는 비울 수 없다 — 자리를 모르면 커널이 어디서 일하는지 정할 수 없다. */\n const out: Record<string, unknown> = {\n id: equipment.name,\n kind: equipment.kind,\n homeLocationId: equipment.homeLocation\n }\n\n /*\n * 등급은 비어 있을 수 있다. 비면 커널이 `kind` 하나로 소속을 정한다 — 예전과 같다.\n * 빈 배열을 내보내지 않는 것은 `put` 이 든다(값이 없으면 칸을 만들지 않는다).\n */\n put(out, 'equipmentClassIds', equipment.equipmentClassIds)\n put(out, 'identity', equipment.identity)\n put(out, 'mtbfMs', equipment.mtbfMs === undefined || equipment.mtbfMs === null ? undefined : Number(equipment.mtbfMs))\n put(out, 'mttrMs', equipment.mttrMs === undefined || equipment.mttrMs === null ? undefined : Number(equipment.mttrMs))\n put(out, 'workCalendar', equipment.workCalendar)\n put(out, 'properties', equipment.properties)\n put(out, 'testSpecificationIds', equipment.testSpecificationIds)\n put(out, 'testResults', equipment.testResults)\n put(out, 'effectiveStart', iso(equipment.effectiveStart))\n put(out, 'effectiveEnd', iso(equipment.effectiveEnd))\n\n return out as unknown as EquipmentEntry\n}\n\n/**\n * 설비 축 전체 — 트윈이 당겨 갈 조각.\n *\n * 설비가 `equipmentClassIds` 로 등급을, `homeLocation` 으로 자리를 가리키므로 등급과 함께 나가야\n * 한다. 한 건씩 밀면 설비가 먼저 도착하고 등급이 나중에 오는 순간이 생긴다.\n */\nexport function equipmentMaster(\n classes: EquipmentClass[],\n equipment: Equipment[]\n): { equipmentClasses: ResourceClassDef[]; equipment: EquipmentEntry[] } {\n return {\n equipmentClasses: classes.map(toResourceClassDef),\n equipment: equipment.map(toEquipmentEntry)\n }\n}\n"]}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
export declare class EquipmentMaster {
|
|
2
2
|
equipmentClasses: string;
|
|
3
3
|
equipment: string;
|
|
4
|
+
/**
|
|
5
|
+
* 더 있나 — **이 값을 안 보고 쓰면 조용히 잘린 마스터로 트윈을 세우게 된다.**
|
|
6
|
+
*
|
|
7
|
+
* 거짓이 될 때까지 `next` 를 `after` 로 넘겨 이어 받는다.
|
|
8
|
+
*/
|
|
9
|
+
hasMore: boolean;
|
|
10
|
+
/** 이어 받을 자리. 더 없으면 없다. */
|
|
11
|
+
next?: string;
|
|
4
12
|
}
|
|
5
13
|
export declare class EquipmentQuery {
|
|
6
14
|
/** 설비 축 전체를 한 번에 낸다 — 설비가 자기 등급과 자리를 가리키므로 함께 나가야 한다. */
|
|
7
|
-
equipmentMaster(context: ResolverContext): Promise<EquipmentMaster>;
|
|
15
|
+
equipmentMaster(after: string | undefined, limit: number | undefined, context: ResolverContext): Promise<EquipmentMaster>;
|
|
8
16
|
}
|
|
@@ -4,6 +4,7 @@ exports.EquipmentQuery = exports.EquipmentMaster = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const type_graphql_1 = require("type-graphql");
|
|
6
6
|
const shell_1 = require("@things-factory/shell");
|
|
7
|
+
const master_page_query_1 = require("../master-page-query");
|
|
7
8
|
const equipment_1 = require("./equipment");
|
|
8
9
|
const equipment_class_1 = require("./equipment-class");
|
|
9
10
|
const equipment_master_1 = require("./equipment-master");
|
|
@@ -18,30 +19,51 @@ tslib_1.__decorate([
|
|
|
18
19
|
(0, type_graphql_1.Field)(type => String, { description: 'ReferenceMaster equipment[] as JSON text' }),
|
|
19
20
|
tslib_1.__metadata("design:type", String)
|
|
20
21
|
], EquipmentMaster.prototype, "equipment", 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
|
+
], EquipmentMaster.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
|
+
], EquipmentMaster.prototype, "next", void 0);
|
|
21
30
|
exports.EquipmentMaster = EquipmentMaster = tslib_1.__decorate([
|
|
22
31
|
(0, type_graphql_1.ObjectType)({ description: 'Equipment master as the twin receives it' })
|
|
23
32
|
], EquipmentMaster);
|
|
24
33
|
let EquipmentQuery = class EquipmentQuery {
|
|
25
34
|
/** 설비 축 전체를 한 번에 낸다 — 설비가 자기 등급과 자리를 가리키므로 함께 나가야 한다. */
|
|
26
|
-
async equipmentMaster(context) {
|
|
35
|
+
async equipmentMaster(after, limit, context) {
|
|
27
36
|
const { domain } = context.state;
|
|
28
|
-
const
|
|
37
|
+
const request = { after, limit };
|
|
38
|
+
/*
|
|
39
|
+
* **등급은 통째로, 구성원만 나눈다.** 구성원이 자기 등급을 이름으로 가리키므로 둘을 함께 나누면
|
|
40
|
+
* 구성원이 먼저 도착하고 등급이 나중에 오는 순간이 생긴다 — 그 순간 받는 쪽은 없는 등급을
|
|
41
|
+
* 가리키는 구성원을 갖는다. 등급은 수십 단위라 매 쪽에 실어도 크지 않다.
|
|
42
|
+
*/
|
|
43
|
+
const [classes, page] = await Promise.all([
|
|
29
44
|
(0, shell_1.getRepository)(equipment_class_1.EquipmentClass).find({ where: { domain: { id: domain.id } }, order: { name: 'ASC' } }),
|
|
30
|
-
(0,
|
|
45
|
+
(0, master_page_query_1.pullPage)(equipment_1.Equipment, domain, request)
|
|
31
46
|
]);
|
|
47
|
+
/* 통째로 달라고 했는데 한도를 넘으면 **자르지 않고 거절한다**(§`master-page`). */
|
|
48
|
+
(0, master_page_query_1.refuseIfTooLarge)('설비', request, page);
|
|
49
|
+
const equipment = page.rows;
|
|
32
50
|
const master = (0, equipment_master_1.equipmentMaster)(classes, equipment);
|
|
33
51
|
return {
|
|
34
52
|
equipmentClasses: JSON.stringify(master.equipmentClasses),
|
|
35
|
-
equipment: JSON.stringify(master.equipment)
|
|
53
|
+
equipment: JSON.stringify(master.equipment),
|
|
54
|
+
hasMore: page.hasMore,
|
|
55
|
+
...(page.next ? { next: page.next } : {})
|
|
36
56
|
};
|
|
37
57
|
}
|
|
38
58
|
};
|
|
39
59
|
exports.EquipmentQuery = EquipmentQuery;
|
|
40
60
|
tslib_1.__decorate([
|
|
41
61
|
(0, type_graphql_1.Query)(returns => EquipmentMaster, { description: 'Equipment master for the twin to pull' }),
|
|
42
|
-
tslib_1.__param(0, (0, type_graphql_1.
|
|
62
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('after', { nullable: true, description: 'resume after this name — the previous page\'s next' })),
|
|
63
|
+
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' })),
|
|
64
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
43
65
|
tslib_1.__metadata("design:type", Function),
|
|
44
|
-
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
66
|
+
tslib_1.__metadata("design:paramtypes", [String, Number, Object]),
|
|
45
67
|
tslib_1.__metadata("design:returntype", Promise)
|
|
46
68
|
], EquipmentQuery.prototype, "equipmentMaster", null);
|
|
47
69
|
exports.EquipmentQuery = EquipmentQuery = tslib_1.__decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"equipment-query.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-query.ts"],"names":[],"mappings":";;;;AAAA,+
|
|
1
|
+
{"version":3,"file":"equipment-query.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment-query.ts"],"names":[],"mappings":"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","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 { Equipment } from './equipment'\nimport { EquipmentClass } from './equipment-class'\nimport { equipmentMaster as buildEquipmentMaster } from './equipment-master'\n\n@ObjectType({ description: 'Equipment master as the twin receives it' })\nexport class EquipmentMaster {\n @Field(type => String, { description: 'ResourceClassDef[] as JSON text' })\n equipmentClasses: string\n\n @Field(type => String, { description: 'ReferenceMaster equipment[] as JSON text' })\n equipment: 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(Equipment)\nexport class EquipmentQuery {\n /** 설비 축 전체를 한 번에 낸다 — 설비가 자기 등급과 자리를 가리키므로 함께 나가야 한다. */\n @Query(returns => EquipmentMaster, { description: 'Equipment master for the twin to pull' })\n async equipmentMaster(\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<EquipmentMaster> {\n const { domain } = context.state\n\n const request = { after, limit }\n\n /*\n * **등급은 통째로, 구성원만 나눈다.** 구성원이 자기 등급을 이름으로 가리키므로 둘을 함께 나누면\n * 구성원이 먼저 도착하고 등급이 나중에 오는 순간이 생긴다 — 그 순간 받는 쪽은 없는 등급을\n * 가리키는 구성원을 갖는다. 등급은 수십 단위라 매 쪽에 실어도 크지 않다.\n */\n const [classes, page] = await Promise.all([\n getRepository(EquipmentClass).find({ where: { domain: { id: domain.id } }, order: { name: 'ASC' } }),\n pullPage<Equipment>(Equipment, domain, request)\n ])\n\n /* 통째로 달라고 했는데 한도를 넘으면 **자르지 않고 거절한다**(§`master-page`). */\n refuseIfTooLarge('설비', request, page)\n\n const equipment = page.rows\n\n const master = buildEquipmentMaster(classes, equipment)\n\n return {\n equipmentClasses: JSON.stringify(master.equipmentClasses),\n equipment: JSON.stringify(master.equipment),\n hasMore: page.hasMore,\n ...(page.next ? { next: page.next } : {})\n }\n }\n}\n"]}
|
|
@@ -14,8 +14,34 @@ export declare class Equipment {
|
|
|
14
14
|
/** 표준 `EquipmentID` — 트윈으로 나갈 때 `equipment[].id` 가 된다. */
|
|
15
15
|
name: string;
|
|
16
16
|
description?: string;
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* 종류 — 계약의 `kind` 자리다.
|
|
19
|
+
*
|
|
20
|
+
* **등급이기도 하고 종류이기도 한 칸이다.** 등급을 담을 칸이 따로 없던 동안 이 한 낱말이 둘을
|
|
21
|
+
* 다 했고, 지금도 하중을 받고 있다 — 설비를 이름으로 부르는 공정들이 이 값을 가리킨다. 그래서
|
|
22
|
+
* 아래에 `equipmentClassIds` 를 열면서도 이 칸을 빼지 않았다.
|
|
23
|
+
*
|
|
24
|
+
* 커널은 소속을 `equipmentClassIds ∪ {kind}` 로 본다(계약의 `equipmentClassMembership`).
|
|
25
|
+
*/
|
|
18
26
|
kind: string;
|
|
27
|
+
/**
|
|
28
|
+
* 속한 등급들 — 표준 `EquipmentClassID`(복수).
|
|
29
|
+
*
|
|
30
|
+
* ── 왜 복수인가 ──────────────────────────────────────────────────────────
|
|
31
|
+
* 인원과 자산이 이미 복수다(`personnelClassIds` · `assetClassIds`). 설비만 없어서 판정이
|
|
32
|
+
* `kind` 하나를 소속으로 썼고, 그래서 표준 요구가 **종류와 이름이 같을 때만** 채워졌다.
|
|
33
|
+
*
|
|
34
|
+
* ```
|
|
35
|
+
* equipmentSpecification: { equipmentClass: 'welding-equipment', quantity: 2 }
|
|
36
|
+
* → kind 가 'welding-equipment' 인 설비만 세어졌다
|
|
37
|
+
* → 6축 로봇과 수동 용접기를 「용접설비 2대」로 함께 세는 것이 불가능했다
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* 요구가 조용히 안 채워지고 작업이 서 있었다. 오류는 나지 않았다.
|
|
41
|
+
*
|
|
42
|
+
* 비워 두면 예전과 똑같이 돈다 — `kind` 만으로 소속이 정해진다.
|
|
43
|
+
*/
|
|
44
|
+
equipmentClassIds?: string[];
|
|
19
45
|
/** 이 설비가 있는 자리 — 표준 `OperationalLocation`. */
|
|
20
46
|
homeLocation: string;
|
|
21
47
|
/** GS1 GIAI. 없으면 비워 둔다 — 회사 프리픽스를 지어내지 않는다. */
|
|
@@ -45,6 +45,11 @@ tslib_1.__decorate([
|
|
|
45
45
|
(0, type_graphql_1.Field)(),
|
|
46
46
|
tslib_1.__metadata("design:type", String)
|
|
47
47
|
], Equipment.prototype, "kind", void 0);
|
|
48
|
+
tslib_1.__decorate([
|
|
49
|
+
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
50
|
+
(0, type_graphql_1.Field)(type => [String], { nullable: true }),
|
|
51
|
+
tslib_1.__metadata("design:type", Array)
|
|
52
|
+
], Equipment.prototype, "equipmentClassIds", void 0);
|
|
48
53
|
tslib_1.__decorate([
|
|
49
54
|
(0, typeorm_1.Column)(),
|
|
50
55
|
(0, type_graphql_1.Field)(),
|
|
@@ -67,12 +72,12 @@ tslib_1.__decorate([
|
|
|
67
72
|
], Equipment.prototype, "mttrMs", void 0);
|
|
68
73
|
tslib_1.__decorate([
|
|
69
74
|
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
70
|
-
(0, type_graphql_1.Field)(type =>
|
|
75
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'WorkCalendarEntry[]' }),
|
|
71
76
|
tslib_1.__metadata("design:type", Array)
|
|
72
77
|
], Equipment.prototype, "workCalendar", void 0);
|
|
73
78
|
tslib_1.__decorate([
|
|
74
79
|
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
75
|
-
(0, type_graphql_1.Field)(type =>
|
|
80
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'ResourceProperty[]' }),
|
|
76
81
|
tslib_1.__metadata("design:type", Array)
|
|
77
82
|
], Equipment.prototype, "properties", void 0);
|
|
78
83
|
tslib_1.__decorate([
|
|
@@ -82,7 +87,7 @@ tslib_1.__decorate([
|
|
|
82
87
|
], Equipment.prototype, "testSpecificationIds", void 0);
|
|
83
88
|
tslib_1.__decorate([
|
|
84
89
|
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
85
|
-
(0, type_graphql_1.Field)(type =>
|
|
90
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'TestResult[]' }),
|
|
86
91
|
tslib_1.__metadata("design:type", Array)
|
|
87
92
|
], Equipment.prototype, "testResults", void 0);
|
|
88
93
|
tslib_1.__decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"equipment.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment.ts"],"names":[],"mappings":";;;;AAAA,qCASgB;AAChB,+CAAyD;AAEzD,
|
|
1
|
+
{"version":3,"file":"equipment.js","sourceRoot":"","sources":["../../../server/service/equipment/equipment.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, ID, Int, ObjectType } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\n/**\n * 설비 — **ISA-95 `Equipment`**.\n *\n * 설비는 작업을 수행하는 자원이다. 배정을 받고, 가동률로 평가받고, 능력으로 찾힌다. **계측기는 설비가\n * 아니다** — 저울과 센서는 그 어느 것도 하지 않고, 그것은 관측의 원천이다. 계측기를 설비로 세우면\n * 가동률 화면이 저울을 기계로 세고 「설비가 논다」가 나온다.\n */\n@Entity({ name: 'ops_equipment' })\n@Index('ix_ops_equipment_0', (equipment: Equipment) => [equipment.domain, equipment.name], { unique: true })\n@ObjectType({ description: 'ISA-95 Equipment — a resource that performs work' })\nexport class Equipment {\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((equipment: Equipment) => equipment.domain)\n domainId?: string\n\n /** 표준 `EquipmentID` — 트윈으로 나갈 때 `equipment[].id` 가 된다. */\n @Column()\n @Field()\n name: string\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n description?: string\n\n /**\n * 종류 — 계약의 `kind` 자리다.\n *\n * **등급이기도 하고 종류이기도 한 칸이다.** 등급을 담을 칸이 따로 없던 동안 이 한 낱말이 둘을\n * 다 했고, 지금도 하중을 받고 있다 — 설비를 이름으로 부르는 공정들이 이 값을 가리킨다. 그래서\n * 아래에 `equipmentClassIds` 를 열면서도 이 칸을 빼지 않았다.\n *\n * 커널은 소속을 `equipmentClassIds ∪ {kind}` 로 본다(계약의 `equipmentClassMembership`).\n */\n @Column()\n @Field()\n kind: string\n\n /**\n * 속한 등급들 — 표준 `EquipmentClassID`(복수).\n *\n * ── 왜 복수인가 ──────────────────────────────────────────────────────────\n * 인원과 자산이 이미 복수다(`personnelClassIds` · `assetClassIds`). 설비만 없어서 판정이\n * `kind` 하나를 소속으로 썼고, 그래서 표준 요구가 **종류와 이름이 같을 때만** 채워졌다.\n *\n * ```\n * equipmentSpecification: { equipmentClass: 'welding-equipment', quantity: 2 }\n * → kind 가 'welding-equipment' 인 설비만 세어졌다\n * → 6축 로봇과 수동 용접기를 「용접설비 2대」로 함께 세는 것이 불가능했다\n * ```\n *\n * 요구가 조용히 안 채워지고 작업이 서 있었다. 오류는 나지 않았다.\n *\n * 비워 두면 예전과 똑같이 돈다 — `kind` 만으로 소속이 정해진다.\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => [String], { nullable: true })\n equipmentClassIds?: string[]\n\n /** 이 설비가 있는 자리 — 표준 `OperationalLocation`. */\n @Column()\n @Field()\n homeLocation: string\n\n /** GS1 GIAI. 없으면 비워 둔다 — 회사 프리픽스를 지어내지 않는다. */\n @Column({ nullable: true })\n @Field({ nullable: true })\n identity?: string\n\n /** 평균 고장 간격(밀리초) — 없으면 고장이 없는 설비로 예측된다. */\n @Column({ type: 'bigint', nullable: true })\n @Field(type => Int, { nullable: true })\n mtbfMs?: number\n\n /** 평균 수리 시간(밀리초). */\n @Column({ type: 'bigint', nullable: true })\n @Field(type => Int, { nullable: true })\n mttrMs?: number\n\n /** 근무 캘린더 — 표준 `WorkCalendar`. 교대 이름과 구간. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'WorkCalendarEntry[]' })\n workCalendar?: Record<string, unknown>[]\n\n /** 개체 속성 — 표준 `EquipmentProperty`. 속도처럼 계산에 들어가는 속성이 여기 온다. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'ResourceProperty[]' })\n properties?: Record<string, unknown>[]\n\n /** 이 설비에 요구되는 `TestSpecification` 참조들 — 검정·교정이 이 모양에 맞는다. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => [String], { nullable: true })\n testSpecificationIds?: string[]\n\n /** `TestResult` — 만료되었거나 떨어졌으면 그 설비에 작업이 가지 않는다. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'TestResult[]' })\n testResults?: Record<string, unknown>[]\n\n /** 언제부터 이 설비가 현장에 있나 — 도입 예정 설비를 미리 등록할 수 있다. */\n @Column({ nullable: true })\n @Field({ nullable: true })\n effectiveStart?: Date\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((equipment: Equipment) => equipment.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((equipment: Equipment) => equipment.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -13,6 +13,25 @@
|
|
|
13
13
|
/** 계약의 `EQUIPMENT_STATUS` 와 같은 어휘. 여기서 새로 만들지 않는다. */
|
|
14
14
|
export declare const EQUIPMENT_PERIOD_STATUS: readonly ["idle", "busy", "down", "setup", "planned-stop"];
|
|
15
15
|
export type EquipmentPeriodStatus = (typeof EQUIPMENT_PERIOD_STATUS)[number];
|
|
16
|
+
/**
|
|
17
|
+
* 정지 사유가 붙을 수 있는 상태 — **`busy` 는 빠진다.**
|
|
18
|
+
*
|
|
19
|
+
* 돌고 있는 것에는 사유가 없다(§`StopReason.status` 주석). 그래서 구간이 가질 수 있는 상태는 다섯인데
|
|
20
|
+
* 사유가 가질 수 있는 상태는 넷이다.
|
|
21
|
+
*/
|
|
22
|
+
export declare const STOP_REASON_STATUS: ("idle" | "down" | "setup" | "planned-stop")[];
|
|
23
|
+
/**
|
|
24
|
+
* 이 사유를 마스터에 적을 수 있나 — **적을 수 없으면 왜인지, 그리고 무엇이 되는지.**
|
|
25
|
+
*
|
|
26
|
+
* ── 왜 마스터에서 막나 (2026-09-03) ────────────────────────────────────────
|
|
27
|
+
* 사유의 `status` 가 자유 문자열이라 `broken` 이 그대로 저장됐다. 그러면 **그 사유를 쓴 모든 구간이**
|
|
28
|
+
* 「사유와 상태가 어긋난다」로 걸린다(§`reasonIssues`). 잘못은 마스터 한 줄에서 났는데 불은 구간
|
|
29
|
+
* 수백 개에서 켜지고, 그 문장은 마스터를 가리키지 않는다.
|
|
30
|
+
*
|
|
31
|
+
* 그래서 틀린 자리에서 막는다. 구간 쪽 검사는 그대로 둔다 — 마스터를 채우기 전에 쓰인 지난 줄과,
|
|
32
|
+
* 사유를 나중에 고친 경우가 거기서 걸린다.
|
|
33
|
+
*/
|
|
34
|
+
export declare function stopReasonStatusGap(status: unknown): string | undefined;
|
|
16
35
|
export type PeriodProblem =
|
|
17
36
|
/** 끝이 시작보다 앞이거나 같다 — 길이가 없는 구간은 셀 것이 없다. */
|
|
18
37
|
'not-a-period'
|
|
@@ -12,10 +12,44 @@
|
|
|
12
12
|
* 거짓이라 나중에 찾을 방법이 없다.
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.EQUIPMENT_PERIOD_STATUS = void 0;
|
|
15
|
+
exports.STOP_REASON_STATUS = exports.EQUIPMENT_PERIOD_STATUS = void 0;
|
|
16
|
+
exports.stopReasonStatusGap = stopReasonStatusGap;
|
|
16
17
|
exports.judgePeriod = judgePeriod;
|
|
17
18
|
/** 계약의 `EQUIPMENT_STATUS` 와 같은 어휘. 여기서 새로 만들지 않는다. */
|
|
18
19
|
exports.EQUIPMENT_PERIOD_STATUS = ['idle', 'busy', 'down', 'setup', 'planned-stop'];
|
|
20
|
+
/**
|
|
21
|
+
* 정지 사유가 붙을 수 있는 상태 — **`busy` 는 빠진다.**
|
|
22
|
+
*
|
|
23
|
+
* 돌고 있는 것에는 사유가 없다(§`StopReason.status` 주석). 그래서 구간이 가질 수 있는 상태는 다섯인데
|
|
24
|
+
* 사유가 가질 수 있는 상태는 넷이다.
|
|
25
|
+
*/
|
|
26
|
+
exports.STOP_REASON_STATUS = exports.EQUIPMENT_PERIOD_STATUS.filter(status => status !== 'busy');
|
|
27
|
+
/**
|
|
28
|
+
* 이 사유를 마스터에 적을 수 있나 — **적을 수 없으면 왜인지, 그리고 무엇이 되는지.**
|
|
29
|
+
*
|
|
30
|
+
* ── 왜 마스터에서 막나 (2026-09-03) ────────────────────────────────────────
|
|
31
|
+
* 사유의 `status` 가 자유 문자열이라 `broken` 이 그대로 저장됐다. 그러면 **그 사유를 쓴 모든 구간이**
|
|
32
|
+
* 「사유와 상태가 어긋난다」로 걸린다(§`reasonIssues`). 잘못은 마스터 한 줄에서 났는데 불은 구간
|
|
33
|
+
* 수백 개에서 켜지고, 그 문장은 마스터를 가리키지 않는다.
|
|
34
|
+
*
|
|
35
|
+
* 그래서 틀린 자리에서 막는다. 구간 쪽 검사는 그대로 둔다 — 마스터를 채우기 전에 쓰인 지난 줄과,
|
|
36
|
+
* 사유를 나중에 고친 경우가 거기서 걸린다.
|
|
37
|
+
*/
|
|
38
|
+
function stopReasonStatusGap(status) {
|
|
39
|
+
const said = typeof status === 'string' ? status.trim() : '';
|
|
40
|
+
if (!said) {
|
|
41
|
+
return ('정지 사유에는 어느 상태에 쓰이는지가 있어야 합니다 — 가동률을 깎느냐 마느냐를 그 값이 정합니다 ' +
|
|
42
|
+
`(쓸 수 있는 것: ${exports.STOP_REASON_STATUS.join(' · ')})`);
|
|
43
|
+
}
|
|
44
|
+
if (said === 'busy') {
|
|
45
|
+
return '돌고 있는 상태에는 정지 사유가 없습니다 — busy 는 정지가 아닙니다';
|
|
46
|
+
}
|
|
47
|
+
if (!exports.STOP_REASON_STATUS.includes(said)) {
|
|
48
|
+
return (`모르는 상태입니다: "${said}" — 이 값으로 저장하면 그 사유를 쓴 모든 구간이 어긋남으로 걸립니다 ` +
|
|
49
|
+
`(쓸 수 있는 것: ${exports.STOP_REASON_STATUS.join(' · ')})`);
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
19
53
|
/**
|
|
20
54
|
* 이 구간을 받아도 되나.
|
|
21
55
|
*
|