@things-factory/ops-master 10.1.29 → 10.1.33
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/pages/master/master-options.d.ts +7 -0
- package/dist-client/pages/master/master-options.js +8 -1
- package/dist-client/pages/master/master-options.js.map +1 -1
- package/dist-client/pages/master/operational-location.js +6 -1
- package/dist-client/pages/master/operational-location.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/asset/index.d.ts +2 -2
- package/dist-server/service/equipment/index.d.ts +2 -2
- package/dist-server/service/index.d.ts +2 -2
- package/dist-server/service/location/index.d.ts +1 -1
- package/dist-server/service/location/operational-location.d.ts +27 -0
- package/dist-server/service/location/operational-location.js +5 -0
- package/dist-server/service/location/operational-location.js.map +1 -1
- package/dist-server/service/material/index.d.ts +2 -2
- package/dist-server/service/operation/index.d.ts +1 -1
- package/dist-server/service/personnel/index.d.ts +2 -2
- package/dist-server/service/personnel/personnel-class.d.ts +1 -1
- package/dist-server/service/personnel/personnel-class.js +1 -1
- package/dist-server/service/personnel/personnel-class.js.map +1 -1
- package/dist-server/service/recipe/index.d.ts +2 -2
- package/dist-server/service/test-spec/index.d.ts +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/translations/en.json +1 -0
- package/translations/ja.json +1 -0
- package/translations/ko.json +1 -0
- package/translations/ms.json +1 -0
- package/translations/zh.json +1 -0
|
@@ -2,5 +2,5 @@ import { AssetQuery } from './asset-query';
|
|
|
2
2
|
import { PhysicalAsset } from './physical-asset';
|
|
3
3
|
import { PhysicalAssetClass } from './physical-asset-class';
|
|
4
4
|
import { PhysicalAssetClassResolver, PhysicalAssetResolver } from './asset-master-resolver';
|
|
5
|
-
export declare const entities: (typeof
|
|
6
|
-
export declare const resolvers: (typeof
|
|
5
|
+
export declare const entities: (typeof PhysicalAssetClass | typeof PhysicalAsset)[];
|
|
6
|
+
export declare const resolvers: (typeof AssetQuery | typeof PhysicalAssetClassResolver | typeof PhysicalAssetResolver)[];
|
|
@@ -4,5 +4,5 @@ import { EquipmentQuery } from './equipment-query';
|
|
|
4
4
|
import { StopReason } from './stop-reason';
|
|
5
5
|
import { StopReasonQuery } from './stop-reason-query';
|
|
6
6
|
import { EquipmentClassResolver, EquipmentResolver, StopReasonResolver } from './equipment-master-resolver';
|
|
7
|
-
export declare const entities: (typeof
|
|
8
|
-
export declare const resolvers: (typeof
|
|
7
|
+
export declare const entities: (typeof StopReason | typeof EquipmentClass | typeof Equipment)[];
|
|
8
|
+
export declare const resolvers: (typeof StopReasonQuery | typeof EquipmentQuery | typeof EquipmentClassResolver | typeof EquipmentResolver | typeof StopReasonResolver)[];
|
|
@@ -51,7 +51,7 @@ export * from './status/axis-stamp';
|
|
|
51
51
|
export * from './status/master-status';
|
|
52
52
|
export * from './quality/nonconformance-cause';
|
|
53
53
|
import { MasterConformanceResolver } from './master-conformance-resolver';
|
|
54
|
-
export declare const entities: (typeof import("./
|
|
54
|
+
export declare const entities: (typeof import("./test-spec/test-specification").TestSpecification | typeof import("./recipe").RouteDefinition | typeof import("./recipe").RecipeDefinition | typeof import("./asset/physical-asset-class").PhysicalAssetClass | typeof import("./asset/physical-asset").PhysicalAsset | typeof import("./personnel/person").Person | typeof import("./location/operational-location").OperationalLocation | typeof import("./operation/operation-definition").OperationDefinition | typeof import("./material/material-definition").MaterialDefinition | typeof import("./quality/nonconformance-cause").NonconformanceCause | typeof import("./equipment/equipment").Equipment)[];
|
|
55
55
|
export declare const schema: {
|
|
56
|
-
resolverClasses: (typeof import("./
|
|
56
|
+
resolverClasses: (typeof import("./quality/nonconformance-cause-resolver").NonconformanceCauseResolver | typeof import("./equipment/stop-reason-query").StopReasonQuery | typeof import("./status/master-status").OpsMasterStatusQuery | typeof import("./test-spec/test-spec-query").TestSpecificationQuery | typeof import("./recipe/recipe-query").RecipeQuery | typeof import("./operation/operation-readiness-resolver").OperationReadinessResolver | typeof import("./operation/operation-query").OperationQuery | typeof import("./material/material-query").MaterialQuery | typeof import("./location/location-query").LocationQuery | typeof import("./asset/asset-query").AssetQuery | typeof import("./equipment/equipment-query").EquipmentQuery | typeof import("./personnel/personnel-query").PersonnelQuery | typeof MasterConformanceResolver | typeof import("./test-spec/test-spec-master-resolver").TestSpecificationResolver | typeof import("./recipe/recipe-master-resolver").RecipeDefinitionResolver | typeof import("./recipe/recipe-master-resolver").RouteDefinitionResolver | typeof import("./operation/operation-master-resolver").OperationDefinitionResolver | typeof import("./location/location-master-resolver").OperationalLocationResolver | typeof import("./material/material-master-resolver").MaterialClassResolver | typeof import("./material/material-master-resolver").MaterialDefinitionResolver | typeof import("./asset/asset-master-resolver").PhysicalAssetClassResolver | typeof import("./asset/asset-master-resolver").PhysicalAssetResolver | typeof import("./equipment/equipment-master-resolver").EquipmentClassResolver | typeof import("./equipment/equipment-master-resolver").EquipmentResolver | typeof import("./equipment/equipment-master-resolver").StopReasonResolver | typeof import("./personnel/personnel-master-resolver").PersonnelClassResolver | typeof import("./personnel/personnel-master-resolver").PersonResolver)[];
|
|
57
57
|
};
|
|
@@ -2,4 +2,4 @@ import { LocationQuery } from './location-query';
|
|
|
2
2
|
import { OperationalLocation } from './operational-location';
|
|
3
3
|
import { OperationalLocationResolver } from './location-master-resolver';
|
|
4
4
|
export declare const entities: (typeof OperationalLocation)[];
|
|
5
|
-
export declare const resolvers: (typeof
|
|
5
|
+
export declare const resolvers: (typeof LocationQuery | typeof OperationalLocationResolver)[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DomainSystem } from '@operato/ops-contract';
|
|
1
2
|
import { Domain } from '@things-factory/shell';
|
|
2
3
|
import { User } from '@things-factory/auth-base';
|
|
3
4
|
/**
|
|
@@ -19,6 +20,32 @@ export declare class OperationalLocation {
|
|
|
19
20
|
description?: string;
|
|
20
21
|
/** 자리 타입 — 도메인 카탈로그가 정한 키(`raw-store` · `weld-station` 같은 것). */
|
|
21
22
|
type: string;
|
|
23
|
+
/**
|
|
24
|
+
* **이 자리의 주인 영역** — 창고(`wms`) · 야드(`yms`) · 공장(`mes`) · 에너지(`ems`)(ADR-0081).
|
|
25
|
+
*
|
|
26
|
+
* ── 왜 칸이어야 하나 (2026-09-19 에 세어 보고 정함) ─────────────────────────
|
|
27
|
+
* 한 현장에 제품이 둘 서면 「이 자리는 누구 것인가」를 물어야 한다. 창고의 재고는 **창고가 주인인 자리에
|
|
28
|
+
* 선 것**이고, 라인 쪽 자리에 선 물건은 공장의 것이다. 그 답이 없으면 불출한 자재가 창고 재고에 그대로
|
|
29
|
+
* 남아 가용 수와 할당 후보에 든다.
|
|
30
|
+
*
|
|
31
|
+
* 있는 칸으로는 가를 수 없다 — 전부 **추론**이 된다.
|
|
32
|
+
*
|
|
33
|
+
* ```
|
|
34
|
+
* type WMS 타입(dock · storage …)과 MES 타입(raw-store · weld-station …)이 한 칸에 섞인다.
|
|
35
|
+
* 현장이 자기 타입을 선언할 수 있어(DomainDefinition.locationTypes) 새 타입이 생기는 날 틀린다
|
|
36
|
+
* level ISA-95 단이라 같은 문제다
|
|
37
|
+
* properties 열린 Record 라 읽는 쪽마다 키를 정하고, 그러면 방언이 된다
|
|
38
|
+
* parentId 「창고 아래」로 가를 수는 있으나 그 뿌리가 누구 것인지는 여전히 선언이 없다
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* ── 모르면 모르는 것이다 ───────────────────────────────────────────────────
|
|
42
|
+
* 비어 있으면 **어느 제품의 재고에도 들지 않는다.** `type` 을 보고 채우는 대체값을 두지 않는다 — 그 추론이
|
|
43
|
+
* 틀리는 날 남의 자리에 선 물건이 우리 재고가 되고, 아무도 오류를 보지 못한다. 선언되지 않은 자리의 수는
|
|
44
|
+
* 화면이 말한다.
|
|
45
|
+
*
|
|
46
|
+
* 낱말은 계약의 `DOMAIN_SYSTEMS` 다. 글자로 다시 적지 않는다.
|
|
47
|
+
*/
|
|
48
|
+
system?: DomainSystem;
|
|
22
49
|
/**
|
|
23
50
|
* ISA-95 설비 계층 단 — `ProductionLine` · `WorkCell` · `StorageZone` · `ProcessCell` · `Unit` 등.
|
|
24
51
|
*
|
|
@@ -48,6 +48,11 @@ tslib_1.__decorate([
|
|
|
48
48
|
(0, type_graphql_1.Field)(),
|
|
49
49
|
tslib_1.__metadata("design:type", String)
|
|
50
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, description: 'Which system owns this place: wms | yms | mes | ems' }),
|
|
54
|
+
tslib_1.__metadata("design:type", String)
|
|
55
|
+
], OperationalLocation.prototype, "system", void 0);
|
|
51
56
|
tslib_1.__decorate([
|
|
52
57
|
(0, typeorm_1.Column)({ nullable: true }),
|
|
53
58
|
(0, type_graphql_1.Field)({ nullable: true }),
|
|
@@ -1 +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, ScalarObject } 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/*\n * 상위로 찾는 색인.\n *\n * 화면이 계층을 한 단씩 걷는다 — 「이 자리의 자식」을 부를 때마다 이 칸으로 거른다. 그리고 줄마다 하위\n * 개수를 세므로(`childCount`), 색인이 없으면 한 화면에 표 전체 훑기가 스무 번 일어난다.\n */\n@Index('ix_ops_operational_location_1', (location: OperationalLocation) => [location.domain, location.parentId])\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 /**\n * 바로 아래에 몇이 있나. **저장하지 않는다** — 목록 리졸버가 채운다(`attachChildCounts`).\n *\n * 계층을 한 단씩 걷는 화면이 이 값으로 「그 줄에 들어갈 것이 있나」를 말한다. 세어서 넣는 값이라\n * 컬럼이 아니다 — 컬럼으로 두면 자식이 생기고 없어질 때마다 이 줄을 함께 고쳐야 하고, 한 번 빠뜨리면\n * 틀린 개수가 남는다.\n */\n @Field(type => Int, { nullable: true, description: 'How many locations sit directly under this one' })\n childCount?: number\n\n /** 자리 속성 — 표준 `OperationalLocationProperty`. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'ResourceProperty[]' })\n properties?: Record<string, unknown>[]\n\n /**\n * 이 자리에서 도는 **근무조 이름들** — 아래 단이 물려받는다.\n *\n * ── 왜 자리가 드나 (2026-09-07) ─────────────────────────────────────────\n * 근무조는 지금까지 도메인 단위 선언이고 **어디에 걸리는지가 없었다.** 그래서 씨앗이 설비마다\n * 사본을 뿌렸고(`Equipment.workCalendar`), 한 공장 22대가 같은 값을 22벌 들고 있었다. 3교대를\n * 2교대로 바꾸면 22줄을 고쳐야 하고, 한 줄을 빠뜨리면 그 설비만 조용히 옛 근무로 계산된다.\n *\n * 근무조는 **사람의 일정**이다. 사람은 기계 한 대가 아니라 라인·셀에 배치된다. 그래서 자리가\n * 들고 아래가 물려받는다 — 공장에 한 줄 적으면 그 아래 전부가 그것으로 돈다.\n *\n * ── 비어 있는 것이 정상이다 ───────────────────────────────────────────────\n * 채우는 것은 **위와 다를 때뿐**이다. 라인 하나만 주간이면 그 라인에만 적는다. 아무 데도 안 적으면\n * 도메인의 근무조 전부로 떨어져 지금 거동 그대로다 — 이 칸이 생겼다고 기존 공장이 바뀌지 않는다.\n *\n * ── 설비에는 적지 않는다 ──────────────────────────────────────────────────\n * 「이 기계만 24시간 돈다」는 근무조가 다른 것이 아니라 **자기 가동 계획이 다른 것**이다(에이징\n * 로가 그렇다). 그 사실은 `Equipment.workCalendar` — 이 설비가 가동하도록 계획된 시간 — 에 적힌다.\n * 근무조로 적으면 아무도 근무하지 않는 시간이 근무 시간으로 기록된다.\n *\n * ── 거는 단은 work center 급 이상이다 — 규칙이지 제약이 아니다 ────────────\n * ISA-95 Part 1 이 일정과 능력을 work center 에 둔다. 사람은 라인에 배치되지 기계 한 대에\n * 배치되지 않으므로, `Site` · `Area` · `ProductionLine` · `WorkCenter` 가 이 칸을 든다.\n *\n * **거절하지는 않는다.** 아래 단에 적어도 상속이 그것을 먼저 만나 그냥 돈다. 셀 단위 근무가\n * 실제로 있는 현장에서 저장을 막으면 그 현장은 모델링 자체가 안 된다 — 적합성 표에 줄 하나가\n * 서는 것보다 나쁘다. 어긋난 것은 성숙도가 이름과 함께 낸다.\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => [String], {\n nullable: true,\n description: 'work shift names that run here — locations below inherit this unless they say their own'\n })\n workShiftNames?: string[]\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"]}
|
|
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 { type DomainSystem } from '@operato/ops-contract'\n\nimport { Domain, ScalarObject } 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/*\n * 상위로 찾는 색인.\n *\n * 화면이 계층을 한 단씩 걷는다 — 「이 자리의 자식」을 부를 때마다 이 칸으로 거른다. 그리고 줄마다 하위\n * 개수를 세므로(`childCount`), 색인이 없으면 한 화면에 표 전체 훑기가 스무 번 일어난다.\n */\n@Index('ix_ops_operational_location_1', (location: OperationalLocation) => [location.domain, location.parentId])\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 * **이 자리의 주인 영역** — 창고(`wms`) · 야드(`yms`) · 공장(`mes`) · 에너지(`ems`)(ADR-0081).\n *\n * ── 왜 칸이어야 하나 (2026-09-19 에 세어 보고 정함) ─────────────────────────\n * 한 현장에 제품이 둘 서면 「이 자리는 누구 것인가」를 물어야 한다. 창고의 재고는 **창고가 주인인 자리에\n * 선 것**이고, 라인 쪽 자리에 선 물건은 공장의 것이다. 그 답이 없으면 불출한 자재가 창고 재고에 그대로\n * 남아 가용 수와 할당 후보에 든다.\n *\n * 있는 칸으로는 가를 수 없다 — 전부 **추론**이 된다.\n *\n * ```\n * type WMS 타입(dock · storage …)과 MES 타입(raw-store · weld-station …)이 한 칸에 섞인다.\n * 현장이 자기 타입을 선언할 수 있어(DomainDefinition.locationTypes) 새 타입이 생기는 날 틀린다\n * level ISA-95 단이라 같은 문제다\n * properties 열린 Record 라 읽는 쪽마다 키를 정하고, 그러면 방언이 된다\n * parentId 「창고 아래」로 가를 수는 있으나 그 뿌리가 누구 것인지는 여전히 선언이 없다\n * ```\n *\n * ── 모르면 모르는 것이다 ───────────────────────────────────────────────────\n * 비어 있으면 **어느 제품의 재고에도 들지 않는다.** `type` 을 보고 채우는 대체값을 두지 않는다 — 그 추론이\n * 틀리는 날 남의 자리에 선 물건이 우리 재고가 되고, 아무도 오류를 보지 못한다. 선언되지 않은 자리의 수는\n * 화면이 말한다.\n *\n * 낱말은 계약의 `DOMAIN_SYSTEMS` 다. 글자로 다시 적지 않는다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Which system owns this place: wms | yms | mes | ems' })\n system?: DomainSystem\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 /**\n * 바로 아래에 몇이 있나. **저장하지 않는다** — 목록 리졸버가 채운다(`attachChildCounts`).\n *\n * 계층을 한 단씩 걷는 화면이 이 값으로 「그 줄에 들어갈 것이 있나」를 말한다. 세어서 넣는 값이라\n * 컬럼이 아니다 — 컬럼으로 두면 자식이 생기고 없어질 때마다 이 줄을 함께 고쳐야 하고, 한 번 빠뜨리면\n * 틀린 개수가 남는다.\n */\n @Field(type => Int, { nullable: true, description: 'How many locations sit directly under this one' })\n childCount?: number\n\n /** 자리 속성 — 표준 `OperationalLocationProperty`. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'ResourceProperty[]' })\n properties?: Record<string, unknown>[]\n\n /**\n * 이 자리에서 도는 **근무조 이름들** — 아래 단이 물려받는다.\n *\n * ── 왜 자리가 드나 (2026-09-07) ─────────────────────────────────────────\n * 근무조는 지금까지 도메인 단위 선언이고 **어디에 걸리는지가 없었다.** 그래서 씨앗이 설비마다\n * 사본을 뿌렸고(`Equipment.workCalendar`), 한 공장 22대가 같은 값을 22벌 들고 있었다. 3교대를\n * 2교대로 바꾸면 22줄을 고쳐야 하고, 한 줄을 빠뜨리면 그 설비만 조용히 옛 근무로 계산된다.\n *\n * 근무조는 **사람의 일정**이다. 사람은 기계 한 대가 아니라 라인·셀에 배치된다. 그래서 자리가\n * 들고 아래가 물려받는다 — 공장에 한 줄 적으면 그 아래 전부가 그것으로 돈다.\n *\n * ── 비어 있는 것이 정상이다 ───────────────────────────────────────────────\n * 채우는 것은 **위와 다를 때뿐**이다. 라인 하나만 주간이면 그 라인에만 적는다. 아무 데도 안 적으면\n * 도메인의 근무조 전부로 떨어져 지금 거동 그대로다 — 이 칸이 생겼다고 기존 공장이 바뀌지 않는다.\n *\n * ── 설비에는 적지 않는다 ──────────────────────────────────────────────────\n * 「이 기계만 24시간 돈다」는 근무조가 다른 것이 아니라 **자기 가동 계획이 다른 것**이다(에이징\n * 로가 그렇다). 그 사실은 `Equipment.workCalendar` — 이 설비가 가동하도록 계획된 시간 — 에 적힌다.\n * 근무조로 적으면 아무도 근무하지 않는 시간이 근무 시간으로 기록된다.\n *\n * ── 거는 단은 work center 급 이상이다 — 규칙이지 제약이 아니다 ────────────\n * ISA-95 Part 1 이 일정과 능력을 work center 에 둔다. 사람은 라인에 배치되지 기계 한 대에\n * 배치되지 않으므로, `Site` · `Area` · `ProductionLine` · `WorkCenter` 가 이 칸을 든다.\n *\n * **거절하지는 않는다.** 아래 단에 적어도 상속이 그것을 먼저 만나 그냥 돈다. 셀 단위 근무가\n * 실제로 있는 현장에서 저장을 막으면 그 현장은 모델링 자체가 안 된다 — 적합성 표에 줄 하나가\n * 서는 것보다 나쁘다. 어긋난 것은 성숙도가 이름과 함께 낸다.\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => [String], {\n nullable: true,\n description: 'work shift names that run here — locations below inherit this unless they say their own'\n })\n workShiftNames?: string[]\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"]}
|
|
@@ -2,5 +2,5 @@ import { MaterialClass } from './material-class';
|
|
|
2
2
|
import { MaterialDefinition } from './material-definition';
|
|
3
3
|
import { MaterialQuery } from './material-query';
|
|
4
4
|
import { MaterialClassResolver, MaterialDefinitionResolver } from './material-master-resolver';
|
|
5
|
-
export declare const entities: (typeof
|
|
6
|
-
export declare const resolvers: (typeof
|
|
5
|
+
export declare const entities: (typeof MaterialDefinition | typeof MaterialClass)[];
|
|
6
|
+
export declare const resolvers: (typeof MaterialQuery | typeof MaterialClassResolver | typeof MaterialDefinitionResolver)[];
|
|
@@ -3,4 +3,4 @@ import { OperationQuery } from './operation-query';
|
|
|
3
3
|
import { OperationDefinitionResolver } from './operation-master-resolver';
|
|
4
4
|
import { OperationReadinessResolver } from './operation-readiness-resolver';
|
|
5
5
|
export declare const entities: (typeof OperationDefinition)[];
|
|
6
|
-
export declare const resolvers: (typeof
|
|
6
|
+
export declare const resolvers: (typeof OperationReadinessResolver | typeof OperationQuery | typeof OperationDefinitionResolver)[];
|
|
@@ -2,5 +2,5 @@ import { Person } from './person';
|
|
|
2
2
|
import { PersonnelClass } from './personnel-class';
|
|
3
3
|
import { PersonnelQuery } from './personnel-query';
|
|
4
4
|
import { PersonnelClassResolver, PersonResolver } from './personnel-master-resolver';
|
|
5
|
-
export declare const entities: (typeof
|
|
6
|
-
export declare const resolvers: (typeof
|
|
5
|
+
export declare const entities: (typeof PersonnelClass | typeof Person)[];
|
|
6
|
+
export declare const resolvers: (typeof PersonnelQuery | typeof PersonnelClassResolver | typeof PersonResolver)[];
|
|
@@ -12,7 +12,7 @@ import { User } from '@things-factory/auth-base';
|
|
|
12
12
|
*
|
|
13
13
|
* 그리고 트윈 커널에 `personnelClasses` 자리가 있는데, 지금까지 붙인 원본에는 그 사실이 없었다.
|
|
14
14
|
* 그래서 「자격자가 둘뿐이라 설비가 논다」를 말할 수 없었다
|
|
15
|
-
* (`operato-
|
|
15
|
+
* (`operato-application/design/charters/operato-plant.md` §5).
|
|
16
16
|
*
|
|
17
17
|
* ── 필드 이름을 새로 짓지 않는다 ────────────────────────────────────────────
|
|
18
18
|
* 커널 계약의 `ResourceClassDef` 와 같은 이름을 쓴다(`@operato/ops-contract`). 같은 사실에 이름이
|
|
@@ -18,7 +18,7 @@ const auth_base_1 = require("@things-factory/auth-base");
|
|
|
18
18
|
*
|
|
19
19
|
* 그리고 트윈 커널에 `personnelClasses` 자리가 있는데, 지금까지 붙인 원본에는 그 사실이 없었다.
|
|
20
20
|
* 그래서 「자격자가 둘뿐이라 설비가 논다」를 말할 수 없었다
|
|
21
|
-
* (`operato-
|
|
21
|
+
* (`operato-application/design/charters/operato-plant.md` §5).
|
|
22
22
|
*
|
|
23
23
|
* ── 필드 이름을 새로 짓지 않는다 ────────────────────────────────────────────
|
|
24
24
|
* 커널 계약의 `ResourceClassDef` 와 같은 이름을 쓴다(`@operato/ops-contract`). 같은 사실에 이름이
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"personnel-class.js","sourceRoot":"","sources":["../../../server/service/personnel/personnel-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 `PersonnelClass`**.\n *\n * 등급은 자격이다. 「용접 자격」이 등급이고, 그 자격을 가진 사람이 개체다. 공정은 특정인을 지목하지\n * 않고 등급으로 요구한다 — 「용접 자격자 2명」.\n *\n * ── 왜 이 패키지가 이것을 갖나 ──────────────────────────────────────────────\n * 인원은 제품의 사실이 아니라 현장의 사실이다. 같은 사람이 MES 에서도 WMS 에서도 일한다. 제품마다\n * 표를 두면 한 사실에 표가 둘이 된다.\n *\n * 그리고 트윈 커널에 `personnelClasses` 자리가 있는데, 지금까지 붙인 원본에는 그 사실이 없었다.\n * 그래서 「자격자가 둘뿐이라 설비가 논다」를 말할 수 없었다\n * (`operato-
|
|
1
|
+
{"version":3,"file":"personnel-class.js","sourceRoot":"","sources":["../../../server/service/personnel/personnel-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 `PersonnelClass`**.\n *\n * 등급은 자격이다. 「용접 자격」이 등급이고, 그 자격을 가진 사람이 개체다. 공정은 특정인을 지목하지\n * 않고 등급으로 요구한다 — 「용접 자격자 2명」.\n *\n * ── 왜 이 패키지가 이것을 갖나 ──────────────────────────────────────────────\n * 인원은 제품의 사실이 아니라 현장의 사실이다. 같은 사람이 MES 에서도 WMS 에서도 일한다. 제품마다\n * 표를 두면 한 사실에 표가 둘이 된다.\n *\n * 그리고 트윈 커널에 `personnelClasses` 자리가 있는데, 지금까지 붙인 원본에는 그 사실이 없었다.\n * 그래서 「자격자가 둘뿐이라 설비가 논다」를 말할 수 없었다\n * (`operato-application/design/charters/operato-plant.md` §5).\n *\n * ── 필드 이름을 새로 짓지 않는다 ────────────────────────────────────────────\n * 커널 계약의 `ResourceClassDef` 와 같은 이름을 쓴다(`@operato/ops-contract`). 같은 사실에 이름이\n * 둘이면 옮길 때마다 번역이 생기고, 번역이 있으면 틀릴 자리가 생긴다.\n */\n@Entity({ name: 'ops_personnel_class' })\n@Index('ix_ops_personnel_class_0', (klass: PersonnelClass) => [klass.domain, klass.name], { unique: true })\n@ObjectType({ description: 'ISA-95 PersonnelClass — a qualification that operations require' })\nexport class PersonnelClass {\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: PersonnelClass) => klass.domain)\n domainId?: string\n\n /** 표준 `PersonnelClassID` — 트윈으로 나갈 때 `ResourceClassDef.id` 가 된다. */\n @Column()\n @Field()\n name: string\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n description?: string\n\n /**\n * 상위 등급들 — 표준 `PersonnelClassBaseID`(복수).\n *\n * 「6축 용접 자격」이 「용접 자격」을 상속한다. 배정 판단이 이 상속을 타므로, 상위 등급으로 요구해도\n * 하위 자격자가 잡힌다.\n */\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 /** 등급 속성 — 표준 `PersonnelClassProperty`. 개체 속성이 `classPropertyId` 로 이것을 구체화한다. */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'ResourceProperty[]' })\n properties?: Record<string, unknown>[]\n\n /**\n * 언제부터 유효한가 — 표준 `EffectiveStartDate`.\n *\n * 자격 규정은 미래 시점으로 선언된다(「9월부터 이 자격이 필요하다」). 이 자리가 없으면 그 선언을\n * 받을 수 없거나, 받고 나서 오늘 배정에 바로 적용된다.\n */\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: PersonnelClass) => 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: PersonnelClass) => klass.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -2,8 +2,8 @@ import { RecipeDefinition } from './recipe-definition';
|
|
|
2
2
|
import { RouteDefinition } from './route-definition';
|
|
3
3
|
import { RecipeDefinitionResolver, RouteDefinitionResolver } from './recipe-master-resolver';
|
|
4
4
|
import { RecipeQuery } from './recipe-query';
|
|
5
|
-
export declare const entities: (typeof
|
|
6
|
-
export declare const resolvers: (typeof
|
|
5
|
+
export declare const entities: (typeof RouteDefinition | typeof RecipeDefinition)[];
|
|
6
|
+
export declare const resolvers: (typeof RecipeQuery | typeof RecipeDefinitionResolver | typeof RouteDefinitionResolver)[];
|
|
7
7
|
export * from './recipe-definition';
|
|
8
8
|
export * from './route-definition';
|
|
9
9
|
export * from './recipe-master';
|
|
@@ -2,4 +2,4 @@ import { TestSpecification } from './test-specification';
|
|
|
2
2
|
import { TestSpecificationQuery } from './test-spec-query';
|
|
3
3
|
import { TestSpecificationResolver } from './test-spec-master-resolver';
|
|
4
4
|
export declare const entities: (typeof TestSpecification)[];
|
|
5
|
-
export declare const resolvers: (typeof
|
|
5
|
+
export declare const resolvers: (typeof TestSpecificationQuery | typeof TestSpecificationResolver)[];
|