@things-factory/ops-master 10.0.18
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/.dockerignore +31 -0
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +2 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/pages/master-axes.d.ts +33 -0
- package/dist-client/pages/master-axes.js +176 -0
- package/dist-client/pages/master-axes.js.map +1 -0
- package/dist-client/pages/master-list.d.ts +68 -0
- package/dist-client/pages/master-list.js +267 -0
- package/dist-client/pages/master-list.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +8 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +5 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/service/asset/asset-lifecycle.d.ts +83 -0
- package/dist-server/service/asset/asset-lifecycle.js +99 -0
- package/dist-server/service/asset/asset-lifecycle.js.map +1 -0
- package/dist-server/service/asset/asset-master-resolver.d.ts +44 -0
- package/dist-server/service/asset/asset-master-resolver.js +140 -0
- package/dist-server/service/asset/asset-master-resolver.js.map +1 -0
- package/dist-server/service/asset/asset-master.d.ts +21 -0
- package/dist-server/service/asset/asset-master.js +25 -0
- package/dist-server/service/asset/asset-master.js.map +1 -0
- package/dist-server/service/asset/asset-query.d.ts +8 -0
- package/dist-server/service/asset/asset-query.js +50 -0
- package/dist-server/service/asset/asset-query.js.map +1 -0
- package/dist-server/service/asset/index.d.ts +6 -0
- package/dist-server/service/asset/index.js +10 -0
- package/dist-server/service/asset/index.js.map +1 -0
- package/dist-server/service/asset/physical-asset-class.d.ts +34 -0
- package/dist-server/service/asset/physical-asset-class.js +104 -0
- package/dist-server/service/asset/physical-asset-class.js.map +1 -0
- package/dist-server/service/asset/physical-asset.d.ts +53 -0
- package/dist-server/service/asset/physical-asset.js +123 -0
- package/dist-server/service/asset/physical-asset.js.map +1 -0
- package/dist-server/service/equipment/equipment-class.d.ts +34 -0
- package/dist-server/service/equipment/equipment-class.js +104 -0
- package/dist-server/service/equipment/equipment-class.js.map +1 -0
- package/dist-server/service/equipment/equipment-master-resolver.d.ts +60 -0
- package/dist-server/service/equipment/equipment-master-resolver.js +200 -0
- package/dist-server/service/equipment/equipment-master-resolver.js.map +1 -0
- package/dist-server/service/equipment/equipment-master.d.ts +29 -0
- package/dist-server/service/equipment/equipment-master.js +36 -0
- package/dist-server/service/equipment/equipment-master.js.map +1 -0
- package/dist-server/service/equipment/equipment-query.d.ts +8 -0
- package/dist-server/service/equipment/equipment-query.js +50 -0
- package/dist-server/service/equipment/equipment-query.js.map +1 -0
- package/dist-server/service/equipment/equipment.d.ts +45 -0
- package/dist-server/service/equipment/equipment.js +133 -0
- package/dist-server/service/equipment/equipment.js.map +1 -0
- package/dist-server/service/equipment/index.d.ts +8 -0
- package/dist-server/service/equipment/index.js +12 -0
- package/dist-server/service/equipment/index.js.map +1 -0
- package/dist-server/service/equipment/state-period-rules.d.ts +76 -0
- package/dist-server/service/equipment/state-period-rules.js +88 -0
- package/dist-server/service/equipment/state-period-rules.js.map +1 -0
- package/dist-server/service/equipment/stop-reason-query.d.ts +11 -0
- package/dist-server/service/equipment/stop-reason-query.js +39 -0
- package/dist-server/service/equipment/stop-reason-query.js.map +1 -0
- package/dist-server/service/equipment/stop-reason.d.ts +58 -0
- package/dist-server/service/equipment/stop-reason.js +114 -0
- package/dist-server/service/equipment/stop-reason.js.map +1 -0
- package/dist-server/service/index.d.ts +46 -0
- package/dist-server/service/index.js +80 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/location/index.d.ts +5 -0
- package/dist-server/service/location/index.js +9 -0
- package/dist-server/service/location/index.js.map +1 -0
- package/dist-server/service/location/location-master-resolver.d.ts +28 -0
- package/dist-server/service/location/location-master-resolver.js +80 -0
- package/dist-server/service/location/location-master-resolver.js.map +1 -0
- package/dist-server/service/location/location-master.d.ts +24 -0
- package/dist-server/service/location/location-master.js +27 -0
- package/dist-server/service/location/location-master.js.map +1 -0
- package/dist-server/service/location/location-query.d.ts +7 -0
- package/dist-server/service/location/location-query.js +41 -0
- package/dist-server/service/location/location-query.js.map +1 -0
- package/dist-server/service/location/operational-location.d.ts +52 -0
- package/dist-server/service/location/operational-location.js +132 -0
- package/dist-server/service/location/operational-location.js.map +1 -0
- package/dist-server/service/master-axis.d.ts +29 -0
- package/dist-server/service/master-axis.js +39 -0
- package/dist-server/service/master-axis.js.map +1 -0
- package/dist-server/service/master-crud.d.ts +44 -0
- package/dist-server/service/master-crud.js +73 -0
- package/dist-server/service/master-crud.js.map +1 -0
- package/dist-server/service/master-list.d.ts +12 -0
- package/dist-server/service/master-list.js +24 -0
- package/dist-server/service/master-list.js.map +1 -0
- package/dist-server/service/material/index.d.ts +6 -0
- package/dist-server/service/material/index.js +10 -0
- package/dist-server/service/material/index.js.map +1 -0
- package/dist-server/service/material/material-class.d.ts +34 -0
- package/dist-server/service/material/material-class.js +104 -0
- package/dist-server/service/material/material-class.js.map +1 -0
- package/dist-server/service/material/material-definition.d.ts +42 -0
- package/dist-server/service/material/material-definition.js +112 -0
- package/dist-server/service/material/material-definition.js.map +1 -0
- package/dist-server/service/material/material-master-resolver.d.ts +44 -0
- package/dist-server/service/material/material-master-resolver.js +140 -0
- package/dist-server/service/material/material-master-resolver.js.map +1 -0
- package/dist-server/service/material/material-master.d.ts +9 -0
- package/dist-server/service/material/material-master.js +24 -0
- package/dist-server/service/material/material-master.js.map +1 -0
- package/dist-server/service/material/material-query.d.ts +8 -0
- package/dist-server/service/material/material-query.js +50 -0
- package/dist-server/service/material/material-query.js.map +1 -0
- package/dist-server/service/operation/index.d.ts +5 -0
- package/dist-server/service/operation/index.js +9 -0
- package/dist-server/service/operation/index.js.map +1 -0
- package/dist-server/service/operation/operation-definition.d.ts +52 -0
- package/dist-server/service/operation/operation-definition.js +142 -0
- package/dist-server/service/operation/operation-definition.js.map +1 -0
- package/dist-server/service/operation/operation-master-resolver.d.ts +28 -0
- package/dist-server/service/operation/operation-master-resolver.js +80 -0
- package/dist-server/service/operation/operation-master-resolver.js.map +1 -0
- package/dist-server/service/operation/operation-master.d.ts +21 -0
- package/dist-server/service/operation/operation-master.js +28 -0
- package/dist-server/service/operation/operation-master.js.map +1 -0
- package/dist-server/service/operation/operation-query.d.ts +7 -0
- package/dist-server/service/operation/operation-query.js +41 -0
- package/dist-server/service/operation/operation-query.js.map +1 -0
- package/dist-server/service/personnel/index.d.ts +6 -0
- package/dist-server/service/personnel/index.js +10 -0
- package/dist-server/service/personnel/index.js.map +1 -0
- package/dist-server/service/personnel/person.d.ts +51 -0
- package/dist-server/service/personnel/person.js +119 -0
- package/dist-server/service/personnel/person.js.map +1 -0
- package/dist-server/service/personnel/personnel-class.d.ts +54 -0
- package/dist-server/service/personnel/personnel-class.js +114 -0
- package/dist-server/service/personnel/personnel-class.js.map +1 -0
- package/dist-server/service/personnel/personnel-master-resolver.d.ts +44 -0
- package/dist-server/service/personnel/personnel-master-resolver.js +140 -0
- package/dist-server/service/personnel/personnel-master-resolver.js.map +1 -0
- package/dist-server/service/personnel/personnel-master.d.ts +39 -0
- package/dist-server/service/personnel/personnel-master.js +34 -0
- package/dist-server/service/personnel/personnel-master.js.map +1 -0
- package/dist-server/service/personnel/personnel-query.d.ts +21 -0
- package/dist-server/service/personnel/personnel-query.js +57 -0
- package/dist-server/service/personnel/personnel-query.js.map +1 -0
- package/dist-server/service/personnel/qualification.d.ts +97 -0
- package/dist-server/service/personnel/qualification.js +122 -0
- package/dist-server/service/personnel/qualification.js.map +1 -0
- package/dist-server/service/resource/resource-class.d.ts +25 -0
- package/dist-server/service/resource/resource-class.js +29 -0
- package/dist-server/service/resource/resource-class.js.map +1 -0
- package/dist-server/service/status/axis-stamp.d.ts +16 -0
- package/dist-server/service/status/axis-stamp.js +22 -0
- package/dist-server/service/status/axis-stamp.js.map +1 -0
- package/dist-server/service/status/index.d.ts +3 -0
- package/dist-server/service/status/index.js +7 -0
- package/dist-server/service/status/index.js.map +1 -0
- package/dist-server/service/status/master-status.d.ts +45 -0
- package/dist-server/service/status/master-status.js +129 -0
- package/dist-server/service/status/master-status.js.map +1 -0
- package/dist-server/service/test-spec/index.d.ts +5 -0
- package/dist-server/service/test-spec/index.js +9 -0
- package/dist-server/service/test-spec/index.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.d.ts +28 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.js +80 -0
- package/dist-server/service/test-spec/test-spec-master-resolver.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-master.d.ts +6 -0
- package/dist-server/service/test-spec/test-spec-master.js +18 -0
- package/dist-server/service/test-spec/test-spec-master.js.map +1 -0
- package/dist-server/service/test-spec/test-spec-query.d.ts +7 -0
- package/dist-server/service/test-spec/test-spec-query.js +41 -0
- package/dist-server/service/test-spec/test-spec-query.js.map +1 -0
- package/dist-server/service/test-spec/test-specification.d.ts +41 -0
- package/dist-server/service/test-spec/test-specification.js +106 -0
- package/dist-server/service/test-spec/test-specification.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +50 -0
- package/things-factory.config.js +12 -0
- package/translations/en.json +53 -0
- package/translations/ja.json +1 -0
- package/translations/ko.json +53 -0
- package/translations/ms.json +1 -0
- package/translations/zh.json +1 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Domain } from '@things-factory/shell';
|
|
2
|
+
import { User } from '@things-factory/auth-base';
|
|
3
|
+
/**
|
|
4
|
+
* 자리 — **ISA-95 `OperationalLocation`**.
|
|
5
|
+
*
|
|
6
|
+
* 표준 원문은 「자원이 놓이거나 놓일 것으로 예상되는 논리적·물리적 장소」다. 자기 계층을 재귀로 갖고,
|
|
7
|
+
* 설비는 자기 자리를 이것으로 가리킨다. 자리와 설비를 나눠 두는 것은 표준의 구조다.
|
|
8
|
+
*
|
|
9
|
+
* ── 용량을 지어내지 않는다 ──────────────────────────────────────────────────
|
|
10
|
+
* `capacity` 는 그 자리에 몇이 들어가는가다. 모르면 비워 둔다. 실측에서 임의로 1 을 넣었더니 물품
|
|
11
|
+
* 하나에 포화 경고가 났다 — 없는 것보다 나쁜 수다.
|
|
12
|
+
*/
|
|
13
|
+
export declare class OperationalLocation {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
domain?: Domain;
|
|
16
|
+
domainId?: string;
|
|
17
|
+
/** 표준 `ID` — 트윈으로 나갈 때 `locations[].id` 가 된다. */
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
/** 자리 타입 — 도메인 카탈로그가 정한 키(`raw-store` · `weld-station` 같은 것). */
|
|
21
|
+
type: string;
|
|
22
|
+
/**
|
|
23
|
+
* ISA-95 설비 계층 단 — `ProductionLine` · `WorkCell` · `StorageZone` · `ProcessCell` · `Unit` 등.
|
|
24
|
+
*
|
|
25
|
+
* 적지 않으면 타입으로 알아낸다. 적으면 그것이 기준이다 — 현장이 자기 계층을 더 잘 안다.
|
|
26
|
+
*/
|
|
27
|
+
level?: string;
|
|
28
|
+
/** 이 자리에 몇이 들어가나. **모르면 비운다.** */
|
|
29
|
+
capacity?: number;
|
|
30
|
+
/** 동시에 몇을 처리하나(대기 이론의 서버 수). 표준에 없는 우리 축이다. */
|
|
31
|
+
parallelism?: number;
|
|
32
|
+
/** 상위 자리 — 표준 `OperationalLocationChild`(재귀)의 반대 방향. */
|
|
33
|
+
parentId?: string;
|
|
34
|
+
/** 자리 속성 — 표준 `OperationalLocationProperty`. */
|
|
35
|
+
properties?: Record<string, unknown>[];
|
|
36
|
+
/** 이 자리에 걸리는 `TestSpecification` 참조들 — 구역 온도 기준 같은 것이 여기 붙는다. */
|
|
37
|
+
testSpecificationIds?: string[];
|
|
38
|
+
/** 언제부터 유효한가 — 표준 `EffectiveStartDate`. */
|
|
39
|
+
effectiveStart?: Date;
|
|
40
|
+
/**
|
|
41
|
+
* 언제까지 유효한가 — 표준 `EffectiveEndDate`.
|
|
42
|
+
*
|
|
43
|
+
* **없앨 때 행을 지우지 않고 이 칸을 채운다.** 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다.
|
|
44
|
+
*/
|
|
45
|
+
effectiveEnd?: Date;
|
|
46
|
+
createdAt?: Date;
|
|
47
|
+
updatedAt?: Date;
|
|
48
|
+
creator?: User;
|
|
49
|
+
creatorId?: string;
|
|
50
|
+
updater?: User;
|
|
51
|
+
updaterId?: string;
|
|
52
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OperationalLocation = 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
|
+
* 자리 — **ISA-95 `OperationalLocation`**.
|
|
11
|
+
*
|
|
12
|
+
* 표준 원문은 「자원이 놓이거나 놓일 것으로 예상되는 논리적·물리적 장소」다. 자기 계층을 재귀로 갖고,
|
|
13
|
+
* 설비는 자기 자리를 이것으로 가리킨다. 자리와 설비를 나눠 두는 것은 표준의 구조다.
|
|
14
|
+
*
|
|
15
|
+
* ── 용량을 지어내지 않는다 ──────────────────────────────────────────────────
|
|
16
|
+
* `capacity` 는 그 자리에 몇이 들어가는가다. 모르면 비워 둔다. 실측에서 임의로 1 을 넣었더니 물품
|
|
17
|
+
* 하나에 포화 경고가 났다 — 없는 것보다 나쁜 수다.
|
|
18
|
+
*/
|
|
19
|
+
let OperationalLocation = class OperationalLocation {
|
|
20
|
+
};
|
|
21
|
+
exports.OperationalLocation = OperationalLocation;
|
|
22
|
+
tslib_1.__decorate([
|
|
23
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
24
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID),
|
|
25
|
+
tslib_1.__metadata("design:type", String)
|
|
26
|
+
], OperationalLocation.prototype, "id", void 0);
|
|
27
|
+
tslib_1.__decorate([
|
|
28
|
+
(0, typeorm_1.ManyToOne)(type => shell_1.Domain),
|
|
29
|
+
(0, type_graphql_1.Field)(type => shell_1.Domain),
|
|
30
|
+
tslib_1.__metadata("design:type", shell_1.Domain)
|
|
31
|
+
], OperationalLocation.prototype, "domain", void 0);
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, typeorm_1.RelationId)((location) => location.domain),
|
|
34
|
+
tslib_1.__metadata("design:type", String)
|
|
35
|
+
], OperationalLocation.prototype, "domainId", void 0);
|
|
36
|
+
tslib_1.__decorate([
|
|
37
|
+
(0, typeorm_1.Column)(),
|
|
38
|
+
(0, type_graphql_1.Field)(),
|
|
39
|
+
tslib_1.__metadata("design:type", String)
|
|
40
|
+
], OperationalLocation.prototype, "name", void 0);
|
|
41
|
+
tslib_1.__decorate([
|
|
42
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
43
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
44
|
+
tslib_1.__metadata("design:type", String)
|
|
45
|
+
], OperationalLocation.prototype, "description", void 0);
|
|
46
|
+
tslib_1.__decorate([
|
|
47
|
+
(0, typeorm_1.Column)(),
|
|
48
|
+
(0, type_graphql_1.Field)(),
|
|
49
|
+
tslib_1.__metadata("design:type", String)
|
|
50
|
+
], OperationalLocation.prototype, "type", void 0);
|
|
51
|
+
tslib_1.__decorate([
|
|
52
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
53
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
54
|
+
tslib_1.__metadata("design:type", String)
|
|
55
|
+
], OperationalLocation.prototype, "level", void 0);
|
|
56
|
+
tslib_1.__decorate([
|
|
57
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
58
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { nullable: true }),
|
|
59
|
+
tslib_1.__metadata("design:type", Number)
|
|
60
|
+
], OperationalLocation.prototype, "capacity", void 0);
|
|
61
|
+
tslib_1.__decorate([
|
|
62
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
63
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { nullable: true }),
|
|
64
|
+
tslib_1.__metadata("design:type", Number)
|
|
65
|
+
], OperationalLocation.prototype, "parallelism", void 0);
|
|
66
|
+
tslib_1.__decorate([
|
|
67
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
68
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
69
|
+
tslib_1.__metadata("design:type", String)
|
|
70
|
+
], OperationalLocation.prototype, "parentId", void 0);
|
|
71
|
+
tslib_1.__decorate([
|
|
72
|
+
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
73
|
+
(0, type_graphql_1.Field)(type => String, { nullable: true, description: 'ResourceProperty[] as JSON text' }),
|
|
74
|
+
tslib_1.__metadata("design:type", Array)
|
|
75
|
+
], OperationalLocation.prototype, "properties", void 0);
|
|
76
|
+
tslib_1.__decorate([
|
|
77
|
+
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
78
|
+
(0, type_graphql_1.Field)(type => [String], { nullable: true }),
|
|
79
|
+
tslib_1.__metadata("design:type", Array)
|
|
80
|
+
], OperationalLocation.prototype, "testSpecificationIds", void 0);
|
|
81
|
+
tslib_1.__decorate([
|
|
82
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
83
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
84
|
+
tslib_1.__metadata("design:type", Date
|
|
85
|
+
/**
|
|
86
|
+
* 언제까지 유효한가 — 표준 `EffectiveEndDate`.
|
|
87
|
+
*
|
|
88
|
+
* **없앨 때 행을 지우지 않고 이 칸을 채운다.** 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다.
|
|
89
|
+
*/
|
|
90
|
+
)
|
|
91
|
+
], OperationalLocation.prototype, "effectiveStart", void 0);
|
|
92
|
+
tslib_1.__decorate([
|
|
93
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
94
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
95
|
+
tslib_1.__metadata("design:type", Date)
|
|
96
|
+
], OperationalLocation.prototype, "effectiveEnd", void 0);
|
|
97
|
+
tslib_1.__decorate([
|
|
98
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
99
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
100
|
+
tslib_1.__metadata("design:type", Date)
|
|
101
|
+
], OperationalLocation.prototype, "createdAt", void 0);
|
|
102
|
+
tslib_1.__decorate([
|
|
103
|
+
(0, typeorm_1.UpdateDateColumn)(),
|
|
104
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
105
|
+
tslib_1.__metadata("design:type", Date)
|
|
106
|
+
], OperationalLocation.prototype, "updatedAt", void 0);
|
|
107
|
+
tslib_1.__decorate([
|
|
108
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
109
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
|
|
110
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
111
|
+
], OperationalLocation.prototype, "creator", void 0);
|
|
112
|
+
tslib_1.__decorate([
|
|
113
|
+
(0, typeorm_1.RelationId)((location) => location.creator),
|
|
114
|
+
tslib_1.__metadata("design:type", String)
|
|
115
|
+
], OperationalLocation.prototype, "creatorId", void 0);
|
|
116
|
+
tslib_1.__decorate([
|
|
117
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
118
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
|
|
119
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
120
|
+
], OperationalLocation.prototype, "updater", void 0);
|
|
121
|
+
tslib_1.__decorate([
|
|
122
|
+
(0, typeorm_1.RelationId)((location) => location.updater),
|
|
123
|
+
tslib_1.__metadata("design:type", String)
|
|
124
|
+
], OperationalLocation.prototype, "updaterId", void 0);
|
|
125
|
+
exports.OperationalLocation = OperationalLocation = tslib_1.__decorate([
|
|
126
|
+
(0, typeorm_1.Entity)({ name: 'ops_operational_location' }),
|
|
127
|
+
(0, typeorm_1.Index)('ix_ops_operational_location_0', (location) => [location.domain, location.name], {
|
|
128
|
+
unique: true
|
|
129
|
+
}),
|
|
130
|
+
(0, type_graphql_1.ObjectType)({ description: 'ISA-95 OperationalLocation — where resources are placed' })
|
|
131
|
+
], OperationalLocation);
|
|
132
|
+
//# sourceMappingURL=operational-location.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operational-location.js","sourceRoot":"","sources":["../../../server/service/location/operational-location.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 } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\n/**\n * 자리 — **ISA-95 `OperationalLocation`**.\n *\n * 표준 원문은 「자원이 놓이거나 놓일 것으로 예상되는 논리적·물리적 장소」다. 자기 계층을 재귀로 갖고,\n * 설비는 자기 자리를 이것으로 가리킨다. 자리와 설비를 나눠 두는 것은 표준의 구조다.\n *\n * ── 용량을 지어내지 않는다 ──────────────────────────────────────────────────\n * `capacity` 는 그 자리에 몇이 들어가는가다. 모르면 비워 둔다. 실측에서 임의로 1 을 넣었더니 물품\n * 하나에 포화 경고가 났다 — 없는 것보다 나쁜 수다.\n */\n@Entity({ name: 'ops_operational_location' })\n@Index('ix_ops_operational_location_0', (location: OperationalLocation) => [location.domain, location.name], {\n unique: true\n})\n@ObjectType({ description: 'ISA-95 OperationalLocation — where resources are placed' })\nexport class OperationalLocation {\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((location: OperationalLocation) => location.domain)\n domainId?: string\n\n /** 표준 `ID` — 트윈으로 나갈 때 `locations[].id` 가 된다. */\n @Column()\n @Field()\n name: string\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n description?: string\n\n /** 자리 타입 — 도메인 카탈로그가 정한 키(`raw-store` · `weld-station` 같은 것). */\n @Column()\n @Field()\n type: string\n\n /**\n * ISA-95 설비 계층 단 — `ProductionLine` · `WorkCell` · `StorageZone` · `ProcessCell` · `Unit` 등.\n *\n * 적지 않으면 타입으로 알아낸다. 적으면 그것이 기준이다 — 현장이 자기 계층을 더 잘 안다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true })\n level?: string\n\n /** 이 자리에 몇이 들어가나. **모르면 비운다.** */\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true })\n capacity?: number\n\n /** 동시에 몇을 처리하나(대기 이론의 서버 수). 표준에 없는 우리 축이다. */\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true })\n parallelism?: number\n\n /** 상위 자리 — 표준 `OperationalLocationChild`(재귀)의 반대 방향. */\n @Column({ nullable: true })\n @Field({ nullable: true })\n parentId?: string\n\n /** 자리 속성 — 표준 `OperationalLocationProperty`. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => String, { nullable: true, description: 'ResourceProperty[] as JSON text' })\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 /** 언제부터 유효한가 — 표준 `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((location: OperationalLocation) => location.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((location: OperationalLocation) => location.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ObjectLiteral } from 'typeorm';
|
|
2
|
+
/**
|
|
3
|
+
* 마스터 열두 축의 **한 줄짜리 선언** — 축마다 다른 것만 적는다.
|
|
4
|
+
*
|
|
5
|
+
* ── 왜 표로 두나 ───────────────────────────────────────────────────────────
|
|
6
|
+
* 축이 열둘인데 조회와 저장은 모양이 같다. 축마다 리졸버를 통째로 베끼면 같은 코드가 열두 벌이 되고,
|
|
7
|
+
* 규칙 하나를 고칠 때 열두 곳을 고쳐야 한다. 그러다 한 곳을 빠뜨리면 그 축만 다르게 동작하는데
|
|
8
|
+
* 오류는 나지 않는다.
|
|
9
|
+
*
|
|
10
|
+
* 그래서 **다른 것만** 적는다 — 어느 표인가, 무엇으로 찾는가, 없앨 때 지우는가 끝을 채우는가.
|
|
11
|
+
*
|
|
12
|
+
* ── 왜 유효 기간 여부가 여기 있나 ──────────────────────────────────────────
|
|
13
|
+
* 지난 기록이 가리키는 축은 지우면 안 된다. 그것이 축마다 다르므로 축의 성질로 적는다. 정지 사유는
|
|
14
|
+
* 유효 기간이 있고, 등급도 있다. 지금 열둘 모두 유효 기간을 갖는다 — 그래도 칸을 둔다. 없는 축이
|
|
15
|
+
* 생기면 그때 이 표만 고치면 된다.
|
|
16
|
+
*/
|
|
17
|
+
export interface MasterAxis {
|
|
18
|
+
/** GraphQL 이름의 바탕. `person` → `persons` · `updateMultiplePerson`. */
|
|
19
|
+
key: string;
|
|
20
|
+
entity: {
|
|
21
|
+
new (): ObjectLiteral;
|
|
22
|
+
};
|
|
23
|
+
/** 검색어가 걸리는 칸들. */
|
|
24
|
+
searchables: string[];
|
|
25
|
+
/** 없앨 때 행을 지우지 않고 `effectiveEnd` 를 채우나. */
|
|
26
|
+
hasEffectivePeriod: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare const MASTER_AXES: readonly MasterAxis[];
|
|
29
|
+
export declare function masterAxisOf(key: string): MasterAxis;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MASTER_AXES = void 0;
|
|
4
|
+
exports.masterAxisOf = masterAxisOf;
|
|
5
|
+
const equipment_1 = require("./equipment/equipment");
|
|
6
|
+
const equipment_class_1 = require("./equipment/equipment-class");
|
|
7
|
+
const stop_reason_1 = require("./equipment/stop-reason");
|
|
8
|
+
const material_class_1 = require("./material/material-class");
|
|
9
|
+
const material_definition_1 = require("./material/material-definition");
|
|
10
|
+
const operation_definition_1 = require("./operation/operation-definition");
|
|
11
|
+
const operational_location_1 = require("./location/operational-location");
|
|
12
|
+
const person_1 = require("./personnel/person");
|
|
13
|
+
const personnel_class_1 = require("./personnel/personnel-class");
|
|
14
|
+
const physical_asset_1 = require("./asset/physical-asset");
|
|
15
|
+
const physical_asset_class_1 = require("./asset/physical-asset-class");
|
|
16
|
+
const test_specification_1 = require("./test-spec/test-specification");
|
|
17
|
+
exports.MASTER_AXES = [
|
|
18
|
+
{ key: 'personnelClass', entity: personnel_class_1.PersonnelClass, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
19
|
+
{ key: 'person', entity: person_1.Person, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
20
|
+
{ key: 'equipmentClass', entity: equipment_class_1.EquipmentClass, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
21
|
+
{ key: 'equipment', entity: equipment_1.Equipment, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
22
|
+
{ key: 'stopReason', entity: stop_reason_1.StopReason, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
23
|
+
{ key: 'physicalAssetClass', entity: physical_asset_class_1.PhysicalAssetClass, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
24
|
+
{ key: 'physicalAsset', entity: physical_asset_1.PhysicalAsset, searchables: ['name', 'description', 'identity'], hasEffectivePeriod: true },
|
|
25
|
+
{ key: 'materialClass', entity: material_class_1.MaterialClass, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
26
|
+
{ key: 'materialDefinition', entity: material_definition_1.MaterialDefinition, searchables: ['name', 'description', 'identity'], hasEffectivePeriod: true },
|
|
27
|
+
{ key: 'operationalLocation', entity: operational_location_1.OperationalLocation, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
28
|
+
{ key: 'operationDefinition', entity: operation_definition_1.OperationDefinition, searchables: ['name', 'description'], hasEffectivePeriod: true },
|
|
29
|
+
{ key: 'testSpecification', entity: test_specification_1.TestSpecification, searchables: ['name', 'description'], hasEffectivePeriod: true }
|
|
30
|
+
];
|
|
31
|
+
function masterAxisOf(key) {
|
|
32
|
+
const axis = exports.MASTER_AXES.find(candidate => candidate.key === key);
|
|
33
|
+
if (!axis) {
|
|
34
|
+
/* 없는 축을 조용히 지나치지 않는다 — 지나치면 그 축의 화면이 빈 목록을 보이고 아무도 모른다. */
|
|
35
|
+
throw new Error(`masterAxisOf: unknown master axis "${key}"`);
|
|
36
|
+
}
|
|
37
|
+
return axis;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=master-axis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"master-axis.js","sourceRoot":"","sources":["../../server/service/master-axis.ts"],"names":[],"mappings":";;;AAwDA,oCASC;AA/DD,qDAAiD;AACjD,iEAA4D;AAC5D,yDAAoD;AACpD,8DAAyD;AACzD,wEAAmE;AACnE,2EAAsE;AACtE,0EAAqE;AACrE,+CAA2C;AAC3C,iEAA4D;AAC5D,2DAAsD;AACtD,uEAAiE;AACjE,uEAAkE;AA4BrD,QAAA,WAAW,GAA0B;IAChD,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,gCAAc,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IACjH,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAM,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IACjG,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,gCAAc,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IACjH,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,qBAAS,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IACvG,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,wBAAU,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IACzG,EAAE,GAAG,EAAE,oBAAoB,EAAE,MAAM,EAAE,yCAAkB,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IACzH,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,8BAAa,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IAC3H,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,8BAAa,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IAC/G,EAAE,GAAG,EAAE,oBAAoB,EAAE,MAAM,EAAE,wCAAkB,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IACrI,EAAE,GAAG,EAAE,qBAAqB,EAAE,MAAM,EAAE,0CAAmB,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IAC3H,EAAE,GAAG,EAAE,qBAAqB,EAAE,MAAM,EAAE,0CAAmB,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;IAC3H,EAAE,GAAG,EAAE,mBAAmB,EAAE,MAAM,EAAE,sCAAiB,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;CACxH,CAAA;AAED,SAAgB,YAAY,CAAC,GAAW;IACtC,MAAM,IAAI,GAAG,mBAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;IAEjE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,2DAA2D;QAC3D,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,GAAG,CAAC,CAAA;IAC/D,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import { ObjectLiteral } from 'typeorm'\n\nimport { Equipment } from './equipment/equipment'\nimport { EquipmentClass } from './equipment/equipment-class'\nimport { StopReason } from './equipment/stop-reason'\nimport { MaterialClass } from './material/material-class'\nimport { MaterialDefinition } from './material/material-definition'\nimport { OperationDefinition } from './operation/operation-definition'\nimport { OperationalLocation } from './location/operational-location'\nimport { Person } from './personnel/person'\nimport { PersonnelClass } from './personnel/personnel-class'\nimport { PhysicalAsset } from './asset/physical-asset'\nimport { PhysicalAssetClass } from './asset/physical-asset-class'\nimport { TestSpecification } from './test-spec/test-specification'\n\n/**\n * 마스터 열두 축의 **한 줄짜리 선언** — 축마다 다른 것만 적는다.\n *\n * ── 왜 표로 두나 ───────────────────────────────────────────────────────────\n * 축이 열둘인데 조회와 저장은 모양이 같다. 축마다 리졸버를 통째로 베끼면 같은 코드가 열두 벌이 되고,\n * 규칙 하나를 고칠 때 열두 곳을 고쳐야 한다. 그러다 한 곳을 빠뜨리면 그 축만 다르게 동작하는데\n * 오류는 나지 않는다.\n *\n * 그래서 **다른 것만** 적는다 — 어느 표인가, 무엇으로 찾는가, 없앨 때 지우는가 끝을 채우는가.\n *\n * ── 왜 유효 기간 여부가 여기 있나 ──────────────────────────────────────────\n * 지난 기록이 가리키는 축은 지우면 안 된다. 그것이 축마다 다르므로 축의 성질로 적는다. 정지 사유는\n * 유효 기간이 있고, 등급도 있다. 지금 열둘 모두 유효 기간을 갖는다 — 그래도 칸을 둔다. 없는 축이\n * 생기면 그때 이 표만 고치면 된다.\n */\n\nexport interface MasterAxis {\n /** GraphQL 이름의 바탕. `person` → `persons` · `updateMultiplePerson`. */\n key: string\n entity: { new (): ObjectLiteral }\n /** 검색어가 걸리는 칸들. */\n searchables: string[]\n /** 없앨 때 행을 지우지 않고 `effectiveEnd` 를 채우나. */\n hasEffectivePeriod: boolean\n}\n\nexport const MASTER_AXES: readonly MasterAxis[] = [\n { key: 'personnelClass', entity: PersonnelClass, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'person', entity: Person, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'equipmentClass', entity: EquipmentClass, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'equipment', entity: Equipment, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'stopReason', entity: StopReason, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'physicalAssetClass', entity: PhysicalAssetClass, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'physicalAsset', entity: PhysicalAsset, searchables: ['name', 'description', 'identity'], hasEffectivePeriod: true },\n { key: 'materialClass', entity: MaterialClass, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'materialDefinition', entity: MaterialDefinition, searchables: ['name', 'description', 'identity'], hasEffectivePeriod: true },\n { key: 'operationalLocation', entity: OperationalLocation, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'operationDefinition', entity: OperationDefinition, searchables: ['name', 'description'], hasEffectivePeriod: true },\n { key: 'testSpecification', entity: TestSpecification, searchables: ['name', 'description'], hasEffectivePeriod: true }\n]\n\nexport function masterAxisOf(key: string): MasterAxis {\n const axis = MASTER_AXES.find(candidate => candidate.key === key)\n\n if (!axis) {\n /* 없는 축을 조용히 지나치지 않는다 — 지나치면 그 축의 화면이 빈 목록을 보이고 아무도 모른다. */\n throw new Error(`masterAxisOf: unknown master axis \"${key}\"`)\n }\n\n return axis\n}\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { EntityManager, ObjectLiteral } from 'typeorm';
|
|
2
|
+
import { Domain } from '@things-factory/shell';
|
|
3
|
+
/**
|
|
4
|
+
* 마스터를 채우고 고치는 **한 벌의 규칙** — 열두 축이 같은 함수를 쓴다.
|
|
5
|
+
*
|
|
6
|
+
* ── 왜 마스터는 그리드에서 고칠 수 있나 ────────────────────────────────────
|
|
7
|
+
* 업무 화면(실적 · 검사 · 처분)은 조회 전용이다. 그것은 **일어난 일의 기록**이라, 고칠 수 있으면
|
|
8
|
+
* 「그때 무엇이 있었나」가 「지금 무엇으로 적혀 있나」로 바뀐다.
|
|
9
|
+
*
|
|
10
|
+
* 마스터는 다르다. 「이 사람이 용접 자격을 갖는다」는 일어난 일이 아니라 **선언**이다. 선언은 바뀌고,
|
|
11
|
+
* 바뀐 것이 지금의 선언이다. 그래서 그리드에서 고친다.
|
|
12
|
+
*
|
|
13
|
+
* ── 지우는 것만 다르게 다룬다 ──────────────────────────────────────────────
|
|
14
|
+
* 유효 기간을 가진 축은 **행을 지우지 않는다.** 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다
|
|
15
|
+
* (어제 실적이 가리키던 설비가 사라지면 그 실적은 어느 설비의 것도 아니게 된다). 대신
|
|
16
|
+
* `effectiveEnd` 를 채워 오늘부터 유효하지 않게 한다.
|
|
17
|
+
*
|
|
18
|
+
* 유효 기간이 없는 축만 실제로 지운다.
|
|
19
|
+
*/
|
|
20
|
+
/** 그리드가 보내는 표식. `+` 새로 만든 행 · `M` 고친 행 · `-` 지운 행. */
|
|
21
|
+
export type CuFlag = '+' | 'M' | '-';
|
|
22
|
+
export interface MasterPatch {
|
|
23
|
+
id?: string;
|
|
24
|
+
cuFlag?: string;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
type EntityClass = {
|
|
28
|
+
new (): ObjectLiteral;
|
|
29
|
+
};
|
|
30
|
+
export interface SaveMasterOptions {
|
|
31
|
+
/**
|
|
32
|
+
* 유효 기간을 갖는 축인가.
|
|
33
|
+
*
|
|
34
|
+
* 참이면 지우기가 **`effectiveEnd` 를 채우는 것**이 된다. 거짓이면 행을 지운다.
|
|
35
|
+
*/
|
|
36
|
+
hasEffectivePeriod?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 그리드가 보낸 변경을 한 번에 적용한다.
|
|
40
|
+
*
|
|
41
|
+
* 한 트랜잭션에서 처리한다 — 절반만 반영되면 그리드가 보여 주는 것과 저장된 것이 갈린다.
|
|
42
|
+
*/
|
|
43
|
+
export declare function saveMasterPatches(manager: EntityManager, domain: Domain, entity: EntityClass, patches: readonly MasterPatch[], user: unknown, options?: SaveMasterOptions): Promise<ObjectLiteral[]>;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.saveMasterPatches = saveMasterPatches;
|
|
4
|
+
const typeorm_1 = require("typeorm");
|
|
5
|
+
/**
|
|
6
|
+
* 그리드가 보낸 변경을 한 번에 적용한다.
|
|
7
|
+
*
|
|
8
|
+
* 한 트랜잭션에서 처리한다 — 절반만 반영되면 그리드가 보여 주는 것과 저장된 것이 갈린다.
|
|
9
|
+
*/
|
|
10
|
+
async function saveMasterPatches(manager, domain, entity, patches, user, options = {}) {
|
|
11
|
+
const repository = manager.getRepository(entity);
|
|
12
|
+
const results = [];
|
|
13
|
+
const created = patches.filter(patch => flagOf(patch) === '+');
|
|
14
|
+
const updated = patches.filter(patch => flagOf(patch) === 'M');
|
|
15
|
+
const removed = patches.filter(patch => flagOf(patch) === '-');
|
|
16
|
+
for (const patch of created) {
|
|
17
|
+
/* 새 행의 `id` 는 그리드가 임시로 붙인 것이다 — 그대로 저장하면 그것이 진짜 키가 된다. */
|
|
18
|
+
const { cuFlag, id, ...values } = patch;
|
|
19
|
+
results.push(await repository.save({ ...values, domain, creator: user, updater: user }));
|
|
20
|
+
}
|
|
21
|
+
for (const patch of updated) {
|
|
22
|
+
const { cuFlag, id, ...values } = patch;
|
|
23
|
+
if (!id) {
|
|
24
|
+
throw new Error('saveMasterPatches: a changed row must carry its id');
|
|
25
|
+
}
|
|
26
|
+
const found = await repository.findOne({ where: { domain: { id: domain.id }, id } });
|
|
27
|
+
/*
|
|
28
|
+
* 없는 행을 고치라고 하면 만들지 않는다. 다른 사람이 지웠거나 다른 도메인의 행이고, 둘 다
|
|
29
|
+
* 조용히 새 행을 만들 일이 아니다.
|
|
30
|
+
*/
|
|
31
|
+
if (!found) {
|
|
32
|
+
throw new Error(`saveMasterPatches: no such row to change — ${String(id)}`);
|
|
33
|
+
}
|
|
34
|
+
results.push(await repository.save({ ...found, ...values, updater: user }));
|
|
35
|
+
}
|
|
36
|
+
if (removed.length) {
|
|
37
|
+
await retire(repository, domain, removed, user, options);
|
|
38
|
+
}
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 없앤다 — 유효 기간이 있으면 **끝을 채우고**, 없으면 지운다.
|
|
43
|
+
*/
|
|
44
|
+
async function retire(repository, domain, removed, user, options) {
|
|
45
|
+
const ids = removed.map(patch => patch.id).filter(Boolean);
|
|
46
|
+
if (!ids.length) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!options.hasEffectivePeriod) {
|
|
50
|
+
await repository.delete({ domain: { id: domain.id }, id: (0, typeorm_1.In)(ids) });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const rows = await repository.find({ where: { domain: { id: domain.id }, id: (0, typeorm_1.In)(ids) } });
|
|
54
|
+
const now = new Date();
|
|
55
|
+
for (const row of rows) {
|
|
56
|
+
/*
|
|
57
|
+
* 이미 끝이 적혀 있으면 그대로 둔다. 다시 오늘로 바꾸면 「언제부터 안 썼나」가 바뀐다.
|
|
58
|
+
*/
|
|
59
|
+
if (row.effectiveEnd) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
await repository.save({ ...row, effectiveEnd: now, updater: user });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function flagOf(patch) {
|
|
66
|
+
const flag = String(patch.cuFlag ?? '').toUpperCase();
|
|
67
|
+
if (flag === '+' || flag === 'M' || flag === '-') {
|
|
68
|
+
return flag;
|
|
69
|
+
}
|
|
70
|
+
/* 표식이 없으면 고침으로 본다 — 그리드가 표식을 안 붙이는 경우가 있고, 만드는 쪽으로 두면 행이 늘어난다. */
|
|
71
|
+
return 'M';
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=master-crud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"master-crud.js","sourceRoot":"","sources":["../../server/service/master-crud.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager, In, ObjectLiteral, Repository } from 'typeorm'\n\nimport { Domain } from '@things-factory/shell'\n\n/**\n * 마스터를 채우고 고치는 **한 벌의 규칙** — 열두 축이 같은 함수를 쓴다.\n *\n * ── 왜 마스터는 그리드에서 고칠 수 있나 ────────────────────────────────────\n * 업무 화면(실적 · 검사 · 처분)은 조회 전용이다. 그것은 **일어난 일의 기록**이라, 고칠 수 있으면\n * 「그때 무엇이 있었나」가 「지금 무엇으로 적혀 있나」로 바뀐다.\n *\n * 마스터는 다르다. 「이 사람이 용접 자격을 갖는다」는 일어난 일이 아니라 **선언**이다. 선언은 바뀌고,\n * 바뀐 것이 지금의 선언이다. 그래서 그리드에서 고친다.\n *\n * ── 지우는 것만 다르게 다룬다 ──────────────────────────────────────────────\n * 유효 기간을 가진 축은 **행을 지우지 않는다.** 지우면 그것을 가리키는 지난 기록이 가리킬 것을 잃는다\n * (어제 실적이 가리키던 설비가 사라지면 그 실적은 어느 설비의 것도 아니게 된다). 대신\n * `effectiveEnd` 를 채워 오늘부터 유효하지 않게 한다.\n *\n * 유효 기간이 없는 축만 실제로 지운다.\n */\n\n/** 그리드가 보내는 표식. `+` 새로 만든 행 · `M` 고친 행 · `-` 지운 행. */\nexport type CuFlag = '+' | 'M' | '-'\n\nexport interface MasterPatch {\n id?: string\n cuFlag?: string\n [key: string]: unknown\n}\n\ntype EntityClass = { new (): ObjectLiteral }\n\nexport interface SaveMasterOptions {\n /**\n * 유효 기간을 갖는 축인가.\n *\n * 참이면 지우기가 **`effectiveEnd` 를 채우는 것**이 된다. 거짓이면 행을 지운다.\n */\n hasEffectivePeriod?: boolean\n}\n\n/**\n * 그리드가 보낸 변경을 한 번에 적용한다.\n *\n * 한 트랜잭션에서 처리한다 — 절반만 반영되면 그리드가 보여 주는 것과 저장된 것이 갈린다.\n */\nexport async function saveMasterPatches(\n manager: EntityManager,\n domain: Domain,\n entity: EntityClass,\n patches: readonly MasterPatch[],\n user: unknown,\n options: SaveMasterOptions = {}\n): Promise<ObjectLiteral[]> {\n const repository = manager.getRepository(entity)\n const results: ObjectLiteral[] = []\n\n const created = patches.filter(patch => flagOf(patch) === '+')\n const updated = patches.filter(patch => flagOf(patch) === 'M')\n const removed = patches.filter(patch => flagOf(patch) === '-')\n\n for (const patch of created) {\n /* 새 행의 `id` 는 그리드가 임시로 붙인 것이다 — 그대로 저장하면 그것이 진짜 키가 된다. */\n const { cuFlag, id, ...values } = patch\n\n results.push(await repository.save({ ...values, domain, creator: user, updater: user }))\n }\n\n for (const patch of updated) {\n const { cuFlag, id, ...values } = patch\n\n if (!id) {\n throw new Error('saveMasterPatches: a changed row must carry its id')\n }\n\n const found = await repository.findOne({ where: { domain: { id: domain.id }, id } })\n\n /*\n * 없는 행을 고치라고 하면 만들지 않는다. 다른 사람이 지웠거나 다른 도메인의 행이고, 둘 다\n * 조용히 새 행을 만들 일이 아니다.\n */\n if (!found) {\n throw new Error(`saveMasterPatches: no such row to change — ${String(id)}`)\n }\n\n results.push(await repository.save({ ...found, ...values, updater: user }))\n }\n\n if (removed.length) {\n await retire(repository, domain, removed, user, options)\n }\n\n return results\n}\n\n/**\n * 없앤다 — 유효 기간이 있으면 **끝을 채우고**, 없으면 지운다.\n */\nasync function retire(\n repository: Repository<ObjectLiteral>,\n domain: Domain,\n removed: readonly MasterPatch[],\n user: unknown,\n options: SaveMasterOptions\n): Promise<void> {\n const ids = removed.map(patch => patch.id).filter(Boolean) as string[]\n\n if (!ids.length) {\n return\n }\n\n if (!options.hasEffectivePeriod) {\n await repository.delete({ domain: { id: domain.id }, id: In(ids) })\n return\n }\n\n const rows = await repository.find({ where: { domain: { id: domain.id }, id: In(ids) } })\n const now = new Date()\n\n for (const row of rows) {\n /*\n * 이미 끝이 적혀 있으면 그대로 둔다. 다시 오늘로 바꾸면 「언제부터 안 썼나」가 바뀐다.\n */\n if (row.effectiveEnd) {\n continue\n }\n\n await repository.save({ ...row, effectiveEnd: now, updater: user })\n }\n}\n\nfunction flagOf(patch: MasterPatch): CuFlag {\n const flag = String(patch.cuFlag ?? '').toUpperCase()\n\n if (flag === '+' || flag === 'M' || flag === '-') {\n return flag\n }\n\n /* 표식이 없으면 고침으로 본다 — 그리드가 표식을 안 붙이는 경우가 있고, 만드는 쪽으로 두면 행이 늘어난다. */\n return 'M'\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ObjectLiteral } from 'typeorm';
|
|
2
|
+
import { Domain, ListParam } from '@things-factory/shell';
|
|
3
|
+
/**
|
|
4
|
+
* 마스터 한 축을 목록으로 읽는다 — **열두 축이 같은 함수를 쓴다.**
|
|
5
|
+
*
|
|
6
|
+
* 총 건수를 함께 낸다. 화면이 「몇 건 중 몇 건을 보고 있나」를 말하려면 그 값이 있어야 하고, 없으면
|
|
7
|
+
* 잘린 목록과 「이게 전부」를 구별할 수 없다.
|
|
8
|
+
*/
|
|
9
|
+
export declare function listMaster(axisKey: string, params: ListParam, domain: Domain): Promise<{
|
|
10
|
+
items: ObjectLiteral[];
|
|
11
|
+
total: number;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listMaster = listMaster;
|
|
4
|
+
const shell_1 = require("@things-factory/shell");
|
|
5
|
+
const master_axis_1 = require("./master-axis");
|
|
6
|
+
/**
|
|
7
|
+
* 마스터 한 축을 목록으로 읽는다 — **열두 축이 같은 함수를 쓴다.**
|
|
8
|
+
*
|
|
9
|
+
* 총 건수를 함께 낸다. 화면이 「몇 건 중 몇 건을 보고 있나」를 말하려면 그 값이 있어야 하고, 없으면
|
|
10
|
+
* 잘린 목록과 「이게 전부」를 구별할 수 없다.
|
|
11
|
+
*/
|
|
12
|
+
async function listMaster(axisKey, params, domain) {
|
|
13
|
+
const axis = (0, master_axis_1.masterAxisOf)(axisKey);
|
|
14
|
+
const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({
|
|
15
|
+
repository: (0, shell_1.getRepository)(axis.entity),
|
|
16
|
+
params,
|
|
17
|
+
domain,
|
|
18
|
+
searchables: axis.searchables,
|
|
19
|
+
alias: 'm'
|
|
20
|
+
});
|
|
21
|
+
const [items, total] = await queryBuilder.getManyAndCount();
|
|
22
|
+
return { items, total };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=master-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"master-list.js","sourceRoot":"","sources":["../../server/service/master-list.ts"],"names":[],"mappings":";;AAYA,gCAkBC;AA5BD,iDAAuG;AAEvG,+CAA4C;AAE5C;;;;;GAKG;AACI,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,MAAiB,EACjB,MAAc;IAEd,MAAM,IAAI,GAAG,IAAA,0BAAY,EAAC,OAAO,CAAC,CAAA;IAElC,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;QACjD,UAAU,EAAE,IAAA,qBAAa,EAAC,IAAI,CAAC,MAAM,CAAC;QACtC,MAAM;QACN,MAAM;QACN,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,KAAK,EAAE,GAAG;KACX,CAAC,CAAA;IAEF,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAA;IAE3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AACzB,CAAC","sourcesContent":["import { ObjectLiteral } from 'typeorm'\n\nimport { Domain, ListParam, getQueryBuilderFromListParams, getRepository } from '@things-factory/shell'\n\nimport { masterAxisOf } from './master-axis'\n\n/**\n * 마스터 한 축을 목록으로 읽는다 — **열두 축이 같은 함수를 쓴다.**\n *\n * 총 건수를 함께 낸다. 화면이 「몇 건 중 몇 건을 보고 있나」를 말하려면 그 값이 있어야 하고, 없으면\n * 잘린 목록과 「이게 전부」를 구별할 수 없다.\n */\nexport async function listMaster(\n axisKey: string,\n params: ListParam,\n domain: Domain\n): Promise<{ items: ObjectLiteral[]; total: number }> {\n const axis = masterAxisOf(axisKey)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(axis.entity),\n params,\n domain,\n searchables: axis.searchables,\n alias: 'm'\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { MaterialClass } from './material-class';
|
|
2
|
+
import { MaterialDefinition } from './material-definition';
|
|
3
|
+
import { MaterialQuery } from './material-query';
|
|
4
|
+
import { MaterialClassResolver, MaterialDefinitionResolver } from './material-master-resolver';
|
|
5
|
+
export declare const entities: (typeof MaterialClass | typeof MaterialDefinition)[];
|
|
6
|
+
export declare const resolvers: (typeof MaterialClassResolver | typeof MaterialDefinitionResolver | typeof MaterialQuery)[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolvers = exports.entities = void 0;
|
|
4
|
+
const material_class_1 = require("./material-class");
|
|
5
|
+
const material_definition_1 = require("./material-definition");
|
|
6
|
+
const material_query_1 = require("./material-query");
|
|
7
|
+
const material_master_resolver_1 = require("./material-master-resolver");
|
|
8
|
+
exports.entities = [material_class_1.MaterialClass, material_definition_1.MaterialDefinition];
|
|
9
|
+
exports.resolvers = [material_query_1.MaterialQuery, material_master_resolver_1.MaterialClassResolver, material_master_resolver_1.MaterialDefinitionResolver];
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/material/index.ts"],"names":[],"mappings":";;;AAAA,qDAAgD;AAChD,+DAA0D;AAC1D,qDAAgD;AAChD,yEAA8F;AAEjF,QAAA,QAAQ,GAAG,CAAC,8BAAa,EAAE,wCAAkB,CAAC,CAAA;AAC9C,QAAA,SAAS,GAAG,CAAC,8BAAa,EAAE,gDAAqB,EAAE,qDAA0B,CAAC,CAAA","sourcesContent":["import { MaterialClass } from './material-class'\nimport { MaterialDefinition } from './material-definition'\nimport { MaterialQuery } from './material-query'\nimport { MaterialClassResolver, MaterialDefinitionResolver } from './material-master-resolver'\n\nexport const entities = [MaterialClass, MaterialDefinition]\nexport const resolvers = [MaterialQuery, MaterialClassResolver, MaterialDefinitionResolver]\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Domain } from '@things-factory/shell';
|
|
2
|
+
import { User } from '@things-factory/auth-base';
|
|
3
|
+
/**
|
|
4
|
+
* 품목 등급 — **ISA-95 `MaterialClass`**.
|
|
5
|
+
*
|
|
6
|
+
* 「원자재」·「완제품」처럼 품목을 묶는 상위 개념이다. 레시피가 특정 품번 대신 등급으로 투입을 적을 수 있고,
|
|
7
|
+
* 화면이 재고를 그 단위로 모은다.
|
|
8
|
+
*
|
|
9
|
+
* 구조는 인원 등급 · 설비 등급과 같다(표준이 넷을 같은 모양으로 정의한다).
|
|
10
|
+
*/
|
|
11
|
+
export declare class MaterialClass {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
domain?: Domain;
|
|
14
|
+
domainId?: string;
|
|
15
|
+
/** 표준 `MaterialClassID`. */
|
|
16
|
+
name: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
/** 상위 등급들 — 표준 `MaterialClassBaseID`(복수). 「6축 용접기」가 「용접기」를 상속한다. */
|
|
19
|
+
baseIds?: string[];
|
|
20
|
+
/** 이 등급의 적격을 정하는 `TestSpecification` 참조들 — 표준 `TestSpecificationID`. */
|
|
21
|
+
testSpecificationIds?: string[];
|
|
22
|
+
/** 등급 속성 — 표준 `MaterialClassProperty`. */
|
|
23
|
+
properties?: Record<string, unknown>[];
|
|
24
|
+
/** 언제부터 유효한가 — 표준 `EffectiveStartDate`. */
|
|
25
|
+
effectiveStart?: Date;
|
|
26
|
+
/** 언제까지 유효한가 — 표준 `EffectiveEndDate`. */
|
|
27
|
+
effectiveEnd?: Date;
|
|
28
|
+
createdAt?: Date;
|
|
29
|
+
updatedAt?: Date;
|
|
30
|
+
creator?: User;
|
|
31
|
+
creatorId?: string;
|
|
32
|
+
updater?: User;
|
|
33
|
+
updaterId?: string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MaterialClass = 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
|
+
* 품목 등급 — **ISA-95 `MaterialClass`**.
|
|
11
|
+
*
|
|
12
|
+
* 「원자재」·「완제품」처럼 품목을 묶는 상위 개념이다. 레시피가 특정 품번 대신 등급으로 투입을 적을 수 있고,
|
|
13
|
+
* 화면이 재고를 그 단위로 모은다.
|
|
14
|
+
*
|
|
15
|
+
* 구조는 인원 등급 · 설비 등급과 같다(표준이 넷을 같은 모양으로 정의한다).
|
|
16
|
+
*/
|
|
17
|
+
let MaterialClass = class MaterialClass {
|
|
18
|
+
};
|
|
19
|
+
exports.MaterialClass = MaterialClass;
|
|
20
|
+
tslib_1.__decorate([
|
|
21
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
22
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID),
|
|
23
|
+
tslib_1.__metadata("design:type", String)
|
|
24
|
+
], MaterialClass.prototype, "id", void 0);
|
|
25
|
+
tslib_1.__decorate([
|
|
26
|
+
(0, typeorm_1.ManyToOne)(type => shell_1.Domain),
|
|
27
|
+
(0, type_graphql_1.Field)(type => shell_1.Domain),
|
|
28
|
+
tslib_1.__metadata("design:type", shell_1.Domain)
|
|
29
|
+
], MaterialClass.prototype, "domain", void 0);
|
|
30
|
+
tslib_1.__decorate([
|
|
31
|
+
(0, typeorm_1.RelationId)((klass) => klass.domain),
|
|
32
|
+
tslib_1.__metadata("design:type", String)
|
|
33
|
+
], MaterialClass.prototype, "domainId", void 0);
|
|
34
|
+
tslib_1.__decorate([
|
|
35
|
+
(0, typeorm_1.Column)(),
|
|
36
|
+
(0, type_graphql_1.Field)(),
|
|
37
|
+
tslib_1.__metadata("design:type", String)
|
|
38
|
+
], MaterialClass.prototype, "name", void 0);
|
|
39
|
+
tslib_1.__decorate([
|
|
40
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
41
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
42
|
+
tslib_1.__metadata("design:type", String)
|
|
43
|
+
], MaterialClass.prototype, "description", void 0);
|
|
44
|
+
tslib_1.__decorate([
|
|
45
|
+
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
46
|
+
(0, type_graphql_1.Field)(type => [String], { nullable: true }),
|
|
47
|
+
tslib_1.__metadata("design:type", Array)
|
|
48
|
+
], MaterialClass.prototype, "baseIds", void 0);
|
|
49
|
+
tslib_1.__decorate([
|
|
50
|
+
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
51
|
+
(0, type_graphql_1.Field)(type => [String], { nullable: true }),
|
|
52
|
+
tslib_1.__metadata("design:type", Array)
|
|
53
|
+
], MaterialClass.prototype, "testSpecificationIds", void 0);
|
|
54
|
+
tslib_1.__decorate([
|
|
55
|
+
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
56
|
+
(0, type_graphql_1.Field)(type => String, { nullable: true, description: 'ResourceProperty[] as JSON text' }),
|
|
57
|
+
tslib_1.__metadata("design:type", Array)
|
|
58
|
+
], MaterialClass.prototype, "properties", void 0);
|
|
59
|
+
tslib_1.__decorate([
|
|
60
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
61
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
62
|
+
tslib_1.__metadata("design:type", Date
|
|
63
|
+
/** 언제까지 유효한가 — 표준 `EffectiveEndDate`. */
|
|
64
|
+
)
|
|
65
|
+
], MaterialClass.prototype, "effectiveStart", void 0);
|
|
66
|
+
tslib_1.__decorate([
|
|
67
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
68
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
69
|
+
tslib_1.__metadata("design:type", Date)
|
|
70
|
+
], MaterialClass.prototype, "effectiveEnd", void 0);
|
|
71
|
+
tslib_1.__decorate([
|
|
72
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
73
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
74
|
+
tslib_1.__metadata("design:type", Date)
|
|
75
|
+
], MaterialClass.prototype, "createdAt", void 0);
|
|
76
|
+
tslib_1.__decorate([
|
|
77
|
+
(0, typeorm_1.UpdateDateColumn)(),
|
|
78
|
+
(0, type_graphql_1.Field)({ nullable: true }),
|
|
79
|
+
tslib_1.__metadata("design:type", Date)
|
|
80
|
+
], MaterialClass.prototype, "updatedAt", void 0);
|
|
81
|
+
tslib_1.__decorate([
|
|
82
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
83
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
|
|
84
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
85
|
+
], MaterialClass.prototype, "creator", void 0);
|
|
86
|
+
tslib_1.__decorate([
|
|
87
|
+
(0, typeorm_1.RelationId)((klass) => klass.creator),
|
|
88
|
+
tslib_1.__metadata("design:type", String)
|
|
89
|
+
], MaterialClass.prototype, "creatorId", 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
|
+
], MaterialClass.prototype, "updater", void 0);
|
|
95
|
+
tslib_1.__decorate([
|
|
96
|
+
(0, typeorm_1.RelationId)((klass) => klass.updater),
|
|
97
|
+
tslib_1.__metadata("design:type", String)
|
|
98
|
+
], MaterialClass.prototype, "updaterId", void 0);
|
|
99
|
+
exports.MaterialClass = MaterialClass = tslib_1.__decorate([
|
|
100
|
+
(0, typeorm_1.Entity)({ name: 'ops_material_class' }),
|
|
101
|
+
(0, typeorm_1.Index)('ix_ops_material_class_0', (klass) => [klass.domain, klass.name], { unique: true }),
|
|
102
|
+
(0, type_graphql_1.ObjectType)({ description: 'ISA-95 MaterialClass — a grouping of material definitions' })
|
|
103
|
+
], MaterialClass);
|
|
104
|
+
//# sourceMappingURL=material-class.js.map
|