@things-factory/worklist 10.1.185 → 10.1.186
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/my-work-menus.d.ts +0 -5
- package/dist-client/my-work-menus.js +1 -2
- package/dist-client/my-work-menus.js.map +1 -1
- package/dist-client/pages/activity-catalog/activity-catalog-page.d.ts +18 -74
- package/dist-client/pages/activity-catalog/activity-catalog-page.js +292 -527
- package/dist-client/pages/activity-catalog/activity-catalog-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -1
- package/dist-client/pages/work-door/door-links.d.ts +1 -9
- package/dist-client/pages/work-door/door-links.js +1 -11
- package/dist-client/pages/work-door/door-links.js.map +1 -1
- package/dist-client/pages/work-door/door-sentence.d.ts +26 -14
- package/dist-client/pages/work-door/door-sentence.js +58 -60
- package/dist-client/pages/work-door/door-sentence.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +0 -3
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/activity/activity-query.js +2 -31
- package/dist-server/service/activity/activity-query.js.map +1 -1
- package/dist-server/service/activity/approval-line-seats.d.ts +12 -0
- package/dist-server/service/activity/approval-line-seats.js +68 -0
- package/dist-server/service/activity/approval-line-seats.js.map +1 -0
- package/dist-server/service/activity/index.d.ts +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.js +2 -54
- package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
- package/dist-server/service/activity-instance/index.d.ts +1 -1
- package/dist-server/service/index.d.ts +3 -3
- package/dist-server/service/work-door/work-door-resolver.js +7 -2
- package/dist-server/service/work-door/work-door-resolver.js.map +1 -1
- package/dist-server/service/work-door/work-door-service.d.ts +8 -1
- package/dist-server/service/work-door/work-door-service.js +11 -2
- package/dist-server/service/work-door/work-door-service.js.map +1 -1
- package/dist-server/service/work-door/work-door-type.d.ts +2 -0
- package/dist-server/service/work-door/work-door-type.js +8 -0
- package/dist-server/service/work-door/work-door-type.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/tests/work-door-door-words.test.ts +1 -1
- package/things-factory.config.js +1 -6
- package/translations/en.json +11 -45
- package/translations/es.json +11 -45
- package/translations/ja.json +11 -45
- package/translations/ko.json +11 -45
- package/translations/ms.json +11 -45
- package/translations/zh.json +11 -45
- package/tests/work-door-sentence.test.ts +0 -199
|
@@ -43,7 +43,7 @@ async function workDoorsFor(manager, domain) {
|
|
|
43
43
|
*/
|
|
44
44
|
const follows = door.lineFollows;
|
|
45
45
|
const lineOwner = follows ? await (0, activity_lookup_js_1.activityNamedIn)(manager, domain, follows) : activity;
|
|
46
|
-
|
|
46
|
+
const judged = (0, work_door_1.judgeDoor)({
|
|
47
47
|
name,
|
|
48
48
|
kind: door.kind,
|
|
49
49
|
whenNoLine: door.whenNoLine,
|
|
@@ -66,7 +66,16 @@ async function workDoorsFor(manager, domain) {
|
|
|
66
66
|
borrowedFrom: activity.domainId === domain.id ? undefined : await subdomainOf(manager, activity.domainId)
|
|
67
67
|
}
|
|
68
68
|
: undefined
|
|
69
|
-
})
|
|
69
|
+
});
|
|
70
|
+
/*
|
|
71
|
+
* The line that applies, as stored, with the domain it was set in - the status screen names its
|
|
72
|
+
* seats. It is the followed door's line when this one follows, so the names match what raising
|
|
73
|
+
* this door actually goes through. Only for a door that stands: a missing or unused door goes
|
|
74
|
+
* through no line.
|
|
75
|
+
*/
|
|
76
|
+
const line = lineOwner?.approvalLine;
|
|
77
|
+
const lineStands = door.kind === 'approval' && (judged.standing === 'on' || judged.standing === 'off');
|
|
78
|
+
doors.push(lineStands && line?.length ? { ...judged, line: { seats: line, domainId: lineOwner.domainId } } : judged);
|
|
70
79
|
}
|
|
71
80
|
return doors;
|
|
72
81
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-door-service.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-service.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"work-door-service.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager, In } from 'typeorm'\n\nimport { Role } from '@things-factory/auth-base'\nimport { Domain } from '@things-factory/shell'\n\nimport { activityNamedIn, seatReader } from './activity-lookup.js'\nimport { judgeApprovalLine } from './approval-line-standing.js'\nimport { declaredDoors, offeredSeatNames } from './work-door-declaration.js'\nimport { WorkDoor, judgeDoor } from './work-door'\nimport { WorkDoorNotUsed } from './work-door-not-used'\n\n/** A judged door and the approval line that applies to it, as stored, for the status screen to name. */\nexport type WorkDoorRead = WorkDoor & { line?: { seats: unknown[]; domainId: string } }\n\n/**\n * 이 공장의 문 열둘을 읽어 판정한다 — **한 벌.**\n *\n * ── 왜 resolver 밖에 두나 ──────────────────────────────────────────────────\n * 이 판정을 묻는 자리가 둘이 됐다. 화면(`workDoors`)과 성숙도 표다. 각자 읽으면 둘이 다른 수를\n * 말하게 되고, **어느 쪽이 맞는지 보는 사람이 알 길이 없다.** 성숙도 표는 이 제품이 스스로에 대해\n * 하는 말이라 화면과 어긋나면 그 표 전체를 못 믿는다.\n *\n * ── 부모까지 보는 규칙은 상신하는 쪽의 것을 그대로 쓴다 ────────────────────\n * 상신이 `activityNamedIn` 으로 양식을 찾으므로, 보는 쪽이 다른 규칙으로 찾으면 **「없다」고\n * 말하는데 실제로는 서는** 상태가 생긴다.\n */\nexport async function workDoorsFor(manager: EntityManager, domain: Domain): Promise<WorkDoorRead[]> {\n /* 공장이 「안 쓴다」고 말한 것을 한 번에 읽는다. 문마다 읽으면 열두 번 묻는다. */\n const declared = new Map(\n (await manager.find(WorkDoorNotUsed, { where: { domain: { id: domain.id } } })).map(one => [\n one.doorName,\n one.because\n ])\n )\n\n const doors: WorkDoorRead[] = []\n\n /*\n * **포트 하나를 문 열일곱이 함께 쓴다.** 포트가 읽은 역할을 기억하므로 같은 역할을 여러 번 묻지\n * 않는다 — 결재선 대부분이 공장장으로 끝난다. 이 판정 동안만 산다.\n */\n const reader = seatReader(manager)\n\n for (const door of declaredDoors()) {\n const name = door.name\n const activity = await activityNamedIn(manager, domain, name)\n /*\n * **결재선을 빌려 쓰는 문**은 따르는 문의 결재선으로 센다(§`LINE_FOLLOWS`). 자기 칸을 세면, 올리는\n * 쪽은 발행 승인의 결재선으로 서는데 현황은 「결재자 없음」이라고 말한다.\n */\n const follows = door.lineFollows\n const lineOwner = follows ? await activityNamedIn(manager, domain, follows) : activity\n\n const judged = judgeDoor({\n name,\n kind: door.kind,\n whenNoLine: door.whenNoLine,\n whenNoLineBecause: door.because,\n notUsedBecause: declared.get(name),\n follows,\n /* 상신하는 쪽과 **같은 함수**로 센다. 여기서 따로 세면 화면과 관문이 갈린다. */\n approvalStanding: activity\n ? await judgeApprovalLine(lineOwner?.approvalLine as Parameters<typeof judgeApprovalLine>[0], reader)\n : undefined,\n installed: activity\n ? {\n approvalLine: lineOwner?.approvalLine as unknown[] | undefined,\n assigneeRole: await roleNameOf(manager, (activity as { assigneeRoleId?: string }).assigneeRoleId),\n /*\n * **빌려 온 것일 때만** 채운다. `Activity` 는 `domainId` 만 들고 있어 이름은 따로\n * 읽는데, 자기 도메인이면 읽지도 않고 비운다 — 자기 이름을 채우면 화면이 모든 줄에\n * 「우리 공장에서 정했습니다」를 달고, 「결재자 없음」 옆에서 그 말이 거짓이 된다.\n */\n borrowedFrom:\n activity.domainId === domain.id ? undefined : await subdomainOf(manager, activity.domainId)\n }\n : undefined\n })\n\n /*\n * The line that applies, as stored, with the domain it was set in - the status screen names its\n * seats. It is the followed door's line when this one follows, so the names match what raising\n * this door actually goes through. Only for a door that stands: a missing or unused door goes\n * through no line.\n */\n const line = lineOwner?.approvalLine as unknown[] | undefined\n const lineStands = door.kind === 'approval' && (judged.standing === 'on' || judged.standing === 'off')\n\n doors.push(lineStands && line?.length ? { ...judged, line: { seats: line, domainId: lineOwner!.domainId } } : judged)\n }\n\n return doors\n}\n\n/**\n * 그 역할의 이름. 없으면 없다 — 지어내지 않는다.\n *\n * 문마다 부르지 않고 배정 문에서만 부른다. 배정 문이 하나도 없는 지금은 한 번도 안 돈다.\n */\nasync function roleNameOf(manager: EntityManager, roleId?: string): Promise<string | undefined> {\n if (!roleId) {\n return undefined\n }\n\n const found = await manager.findOne(Role, { where: { id: roleId } })\n\n return found?.name\n}\n\n/**\n * 부모 도메인의 이름. 못 읽으면 지어내지 않고 비운다 — 「본사」라고 적으면 없는 이름이 화면에 남는다.\n *\n * 원문 SQL 로 안 읽는다. 자리표시자 철자가 드라이버마다 달라(`?` · `$1`) sqlite 에서는 통과하고\n * postgres 에서만 죽는다 — 그 부류는 여기서 절대 못 잡는다.\n */\nasync function subdomainOf(manager: EntityManager, domainId: string): Promise<string | undefined> {\n const found = await manager.findOne(Domain, { where: { id: domainId } })\n\n return found?.subdomain\n}\n\n/**\n * 이 제품이 내놓는 역할 자리 중 이 공장에 선 것이 몇인가.\n *\n * 결재선은 **역할을 가리킨다**(`[{type:'Role', value:<역할 id>}]`). 그러니 역할이 없는 공장에서는\n * 결재선을 만들 수 없다 — 양식 화면까지 가서야 그걸 알게 된다. 문 현황과 함께 내서 화면이 순서를\n * 말하게 한다.\n *\n * 공장이 스스로 만든 다른 역할은 안 센다. 이 수가 말하는 것은 「이 제품이 내놓은 자리」이고,\n * 그 밖의 역할로 결재선을 짜는 것도 물론 된다.\n */\nexport async function seatsStanding(manager: EntityManager, domain: Domain): Promise<number> {\n const offered = offeredSeatNames()\n const here = await manager.find(Role, { where: { domain: { id: domain.id } } })\n const names = new Set(here.map(one => one.name))\n\n return offered.filter(one => names.has(one)).length\n}\n\n/** 이 설치본의 앱들이 내놓는 자리의 수 — 화면이 목록을 따로 들지 않게 여기서 센다. */\nexport function seatsOffered(): number {\n return offeredSeatNames().length\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ApprovalLineItem } from '@things-factory/organization';
|
|
1
2
|
import type { WorkDoor } from './work-door.js';
|
|
2
3
|
/**
|
|
3
4
|
* 「이 공장에서 어느 결재 문이 서 있나」를 화면에 낼 모양.
|
|
@@ -58,6 +59,7 @@ export declare class WorkDoorType {
|
|
|
58
59
|
followsLabelKey?: string;
|
|
59
60
|
assigneeRole?: string;
|
|
60
61
|
notUsedBecause?: string;
|
|
62
|
+
approvalLine?: ApprovalLineItem[];
|
|
61
63
|
}
|
|
62
64
|
export declare class WorkDoorsType {
|
|
63
65
|
doors: WorkDoorType[];
|
|
@@ -4,6 +4,7 @@ exports.WorkDoorsType = exports.WorkDoorType = exports.WhenNoLineBecauseValue =
|
|
|
4
4
|
exports.toDoorType = toDoorType;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const organization_1 = require("@things-factory/organization");
|
|
7
8
|
/**
|
|
8
9
|
* 「이 공장에서 어느 결재 문이 서 있나」를 화면에 낼 모양.
|
|
9
10
|
*
|
|
@@ -126,6 +127,13 @@ tslib_1.__decorate([
|
|
|
126
127
|
(0, type_graphql_1.Field)({ nullable: true, description: 'what the plant wrote when it said it does not use this door — shown as written' }),
|
|
127
128
|
tslib_1.__metadata("design:type", String)
|
|
128
129
|
], WorkDoorType.prototype, "notUsedBecause", void 0);
|
|
130
|
+
tslib_1.__decorate([
|
|
131
|
+
(0, type_graphql_1.Field)(type => [organization_1.ApprovalLineItem], {
|
|
132
|
+
nullable: true,
|
|
133
|
+
description: 'the approval line raising this door goes through, seat by seat — the followed door\'s line when it follows one'
|
|
134
|
+
}),
|
|
135
|
+
tslib_1.__metadata("design:type", Array)
|
|
136
|
+
], WorkDoorType.prototype, "approvalLine", void 0);
|
|
129
137
|
exports.WorkDoorType = WorkDoorType = tslib_1.__decorate([
|
|
130
138
|
(0, type_graphql_1.ObjectType)({ description: 'One approval form and whether this plant has approvers on it' })
|
|
131
139
|
], WorkDoorType);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-door-type.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, Int, ObjectType, registerEnumType } from 'type-graphql'\n\nimport type { WorkDoor } from './work-door.js'\n\n/**\n * 「이 공장에서 어느 결재 문이 서 있나」를 화면에 낼 모양.\n *\n * **사실만 낸다. 문장은 화면이 번역으로 짓는다.** 서버가 한국어 문장을 지어 보내던 때 영어·일본어·\n * 중국어·말레이어 사용자도 한국어를 읽었고, 화면이 상태별로 달리 그리려면 그 문장을 다시 뜯어 읽어야\n * 했다. 열거형 값 셋은 `registerEnumType` 이 **멤버 이름**을 싣는다 — 화면이 `door-words.ts` 한 곳에서\n * 옮긴다.\n */\n\nexport enum DoorStandingValue {\n /** 채워졌다. */\n On = 'on',\n /** 양식은 섰는데 받을 사람이 없다. 조치 대상. */\n Off = 'off',\n /** 양식이 아예 안 섰다 — 설정이 아니라 결함이다. 조치 대상. */\n Missing = 'missing',\n /** 이 공장이 안 쓰기로 했다. 조치 대상이 아니다. */\n NotUsed = 'not-used'\n}\n\n/** 결재냐 배정이냐 — 비었을 때 결과가 반대라 화면이 갈라 그려야 한다. */\nexport enum DoorKindValue {\n Approval = 'approval',\n Assignment = 'assignment'\n}\n\n/** 왜 그 상태인가 — 까닭마다 관리자가 할 일이 다르다(§`DoorReason`). */\nexport enum DoorReasonValue {\n NotUsed = 'not-used',\n Missing = 'missing',\n LineEmpty = 'line-empty',\n RoleEmpty = 'role-empty',\n PersonAbsent = 'person-absent',\n NoAssignee = 'no-assignee',\n LineFilled = 'line-filled',\n AssigneeBound = 'assignee-bound'\n}\n\n/** 결재선이 비면 이 문이 어떻게 하나 — 선언 그대로(ADR-0077 결정 1). */\nexport enum WhenNoLineValue {\n Run = 'run',\n Refuse = 'refuse',\n AsEstablished = 'as-established'\n}\n\n/** 결재를 요구하는 까닭 — `refuse` · `as-established` 문만. */\nexport enum WhenNoLineBecauseValue {\n Irreversible = 'irreversible',\n ApprovalIsTheAct = 'approval-is-the-act',\n LowersAControl = 'lowers-a-control'\n}\n\nregisterEnumType(DoorReasonValue, {\n name: 'DoorReason',\n description: 'Why a door stands where it does — each reason asks for a different fix'\n})\n\nregisterEnumType(WhenNoLineValue, {\n name: 'WhenNoLine',\n description: 'What an approval door does when its approval line is empty, as the application declared it'\n})\n\nregisterEnumType(WhenNoLineBecauseValue, {\n name: 'WhenNoLineBecause',\n description: 'Why an approval door will not run without an approval line'\n})\n\nregisterEnumType(DoorKindValue, {\n name: 'DoorKind',\n description: 'Whether the plant fills an approval line or an assignee role on this door'\n})\n\nregisterEnumType(DoorStandingValue, {\n name: 'DoorStanding',\n description: 'Whether this plant has an approval step standing for that form'\n})\n\n@ObjectType({ description: 'One approval form and whether this plant has approvers on it' })\nexport class WorkDoorType {\n @Field({ description: 'the form name — the key the callback is found by' })\n name: string\n\n @Field({ description: 'the translation key of its label — computed from the name, never declared' })\n labelKey: string\n\n @Field(type => DoorKindValue)\n kind: DoorKindValue\n\n @Field(type => DoorStandingValue)\n standing: DoorStandingValue\n\n @Field(type => DoorReasonValue)\n reason: DoorReasonValue\n\n @Field(type => Int, { description: 'how many approvers — zero for an assignment door or an empty line' })\n approvers: number\n\n @Field({ nullable: true, description: 'which domain the approval line came from — a plant may use its parent\\'s' })\n from?: string\n\n @Field(type => WhenNoLineValue, { nullable: true, description: 'approval doors only' })\n whenNoLine?: WhenNoLineValue\n\n @Field(type => WhenNoLineBecauseValue, { nullable: true, description: 'refuse and as-established doors only' })\n whenNoLineBecause?: WhenNoLineBecauseValue\n\n @Field({ nullable: true, description: 'the label key of the door whose approval line this one follows' })\n followsLabelKey?: string\n\n @Field({ nullable: true, description: 'the role an assignment door is bound to' })\n assigneeRole?: string\n\n @Field({ nullable: true, description: 'what the plant wrote when it said it does not use this door — shown as written' })\n notUsedBecause?: string\n}\n\n@ObjectType({ description: 'Every approval form this product installs, and where this plant stands on each' })\nexport class WorkDoorsType {\n @Field(type => [WorkDoorType])\n doors: WorkDoorType[]\n\n @Field(type => Int, { description: 'how many still need filling — not-used doors are never counted' })\n todo: number\n\n @Field(type => Int, { description: 'doors standing' })\n on: number\n\n @Field(type => Int, { description: 'forms installed with nobody on them' })\n off: number\n\n @Field(type => Int, { description: 'forms that never installed' })\n missing: number\n\n @Field(type => Int, { description: 'doors this plant said it does not use' })\n notUsed: number\n\n /**\n * 이 제품이 내놓는 역할 자리 중 **이 공장에 실제로 선 것.**\n *\n * ── 왜 문 목록에 자리 수가 붙나 ────────────────────────────────────────\n * 문이 비었다는 말만 하면 사람은 양식 화면으로 간다. 그런데 **고를 역할이 없으면 그 화면의\n * 결재선 칸이 빈 목록**이다. 헛걸음하고 돌아와서, 무엇이 잘못됐는지 모른 채 이 화면을 다시 본다.\n *\n * 두 수를 함께 내면 화면이 순서를 말할 수 있다 — 자리부터 세우고, 그다음에 결재선을 건다.\n */\n @Field(type => Int, { description: 'how many of the role seats this product offers actually exist here' })\n seatsStanding: number\n\n @Field(type => Int, { description: 'how many role seats this product offers' })\n seatsOffered: number\n}\n\n/**\n * 판단의 모양을 화면의 모양으로. 판단부의 낱말(`'line-empty'`)을 열거형 **값**으로 찾아 멤버를 싣는다 —\n * 값과 낱말이 같게 적혀 있으니 표를 따로 들지 않는다. 못 찾으면 던진다: 새 낱말이 전선에서 조용히\n * 사라지면 화면이 「모른다」조차 못 그린다.\n */\nexport function toDoorType(door: WorkDoor): WorkDoorType {\n return {\n name: door.name,\n labelKey: door.labelKey,\n kind: member(DoorKindValue, door.kind),\n standing: member(DoorStandingValue, door.standing),\n reason: member(DoorReasonValue, door.reason),\n approvers: door.approvers,\n from: door.from,\n whenNoLine: door.whenNoLine ? member(WhenNoLineValue, door.whenNoLine) : undefined,\n whenNoLineBecause: door.whenNoLineBecause ? member(WhenNoLineBecauseValue, door.whenNoLineBecause) : undefined,\n followsLabelKey: door.followsLabelKey,\n assigneeRole: door.assigneeRole,\n notUsedBecause: door.notUsedBecause\n }\n}\n\nfunction member<T extends Record<string, string>>(values: T, word: string): T[keyof T] {\n const found = Object.values(values).find(one => one === word)\n\n if (!found) {\n throw new Error(`work door: no wire value for \"${word}\"`)\n }\n\n return found as T[keyof T]\n}\n"]}
|
|
1
|
+
{"version":3,"file":"work-door-type.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, Int, ObjectType, registerEnumType } from 'type-graphql'\n\nimport { ApprovalLineItem } from '@things-factory/organization'\n\nimport type { WorkDoor } from './work-door.js'\n\n/**\n * 「이 공장에서 어느 결재 문이 서 있나」를 화면에 낼 모양.\n *\n * **사실만 낸다. 문장은 화면이 번역으로 짓는다.** 서버가 한국어 문장을 지어 보내던 때 영어·일본어·\n * 중국어·말레이어 사용자도 한국어를 읽었고, 화면이 상태별로 달리 그리려면 그 문장을 다시 뜯어 읽어야\n * 했다. 열거형 값 셋은 `registerEnumType` 이 **멤버 이름**을 싣는다 — 화면이 `door-words.ts` 한 곳에서\n * 옮긴다.\n */\n\nexport enum DoorStandingValue {\n /** 채워졌다. */\n On = 'on',\n /** 양식은 섰는데 받을 사람이 없다. 조치 대상. */\n Off = 'off',\n /** 양식이 아예 안 섰다 — 설정이 아니라 결함이다. 조치 대상. */\n Missing = 'missing',\n /** 이 공장이 안 쓰기로 했다. 조치 대상이 아니다. */\n NotUsed = 'not-used'\n}\n\n/** 결재냐 배정이냐 — 비었을 때 결과가 반대라 화면이 갈라 그려야 한다. */\nexport enum DoorKindValue {\n Approval = 'approval',\n Assignment = 'assignment'\n}\n\n/** 왜 그 상태인가 — 까닭마다 관리자가 할 일이 다르다(§`DoorReason`). */\nexport enum DoorReasonValue {\n NotUsed = 'not-used',\n Missing = 'missing',\n LineEmpty = 'line-empty',\n RoleEmpty = 'role-empty',\n PersonAbsent = 'person-absent',\n NoAssignee = 'no-assignee',\n LineFilled = 'line-filled',\n AssigneeBound = 'assignee-bound'\n}\n\n/** 결재선이 비면 이 문이 어떻게 하나 — 선언 그대로(ADR-0077 결정 1). */\nexport enum WhenNoLineValue {\n Run = 'run',\n Refuse = 'refuse',\n AsEstablished = 'as-established'\n}\n\n/** 결재를 요구하는 까닭 — `refuse` · `as-established` 문만. */\nexport enum WhenNoLineBecauseValue {\n Irreversible = 'irreversible',\n ApprovalIsTheAct = 'approval-is-the-act',\n LowersAControl = 'lowers-a-control'\n}\n\nregisterEnumType(DoorReasonValue, {\n name: 'DoorReason',\n description: 'Why a door stands where it does — each reason asks for a different fix'\n})\n\nregisterEnumType(WhenNoLineValue, {\n name: 'WhenNoLine',\n description: 'What an approval door does when its approval line is empty, as the application declared it'\n})\n\nregisterEnumType(WhenNoLineBecauseValue, {\n name: 'WhenNoLineBecause',\n description: 'Why an approval door will not run without an approval line'\n})\n\nregisterEnumType(DoorKindValue, {\n name: 'DoorKind',\n description: 'Whether the plant fills an approval line or an assignee role on this door'\n})\n\nregisterEnumType(DoorStandingValue, {\n name: 'DoorStanding',\n description: 'Whether this plant has an approval step standing for that form'\n})\n\n@ObjectType({ description: 'One approval form and whether this plant has approvers on it' })\nexport class WorkDoorType {\n @Field({ description: 'the form name — the key the callback is found by' })\n name: string\n\n @Field({ description: 'the translation key of its label — computed from the name, never declared' })\n labelKey: string\n\n @Field(type => DoorKindValue)\n kind: DoorKindValue\n\n @Field(type => DoorStandingValue)\n standing: DoorStandingValue\n\n @Field(type => DoorReasonValue)\n reason: DoorReasonValue\n\n @Field(type => Int, { description: 'how many approvers — zero for an assignment door or an empty line' })\n approvers: number\n\n @Field({ nullable: true, description: 'which domain the approval line came from — a plant may use its parent\\'s' })\n from?: string\n\n @Field(type => WhenNoLineValue, { nullable: true, description: 'approval doors only' })\n whenNoLine?: WhenNoLineValue\n\n @Field(type => WhenNoLineBecauseValue, { nullable: true, description: 'refuse and as-established doors only' })\n whenNoLineBecause?: WhenNoLineBecauseValue\n\n @Field({ nullable: true, description: 'the label key of the door whose approval line this one follows' })\n followsLabelKey?: string\n\n @Field({ nullable: true, description: 'the role an assignment door is bound to' })\n assigneeRole?: string\n\n @Field({ nullable: true, description: 'what the plant wrote when it said it does not use this door — shown as written' })\n notUsedBecause?: string\n\n @Field(type => [ApprovalLineItem], {\n nullable: true,\n description: 'the approval line raising this door goes through, seat by seat — the followed door\\'s line when it follows one'\n })\n approvalLine?: ApprovalLineItem[]\n}\n\n@ObjectType({ description: 'Every approval form this product installs, and where this plant stands on each' })\nexport class WorkDoorsType {\n @Field(type => [WorkDoorType])\n doors: WorkDoorType[]\n\n @Field(type => Int, { description: 'how many still need filling — not-used doors are never counted' })\n todo: number\n\n @Field(type => Int, { description: 'doors standing' })\n on: number\n\n @Field(type => Int, { description: 'forms installed with nobody on them' })\n off: number\n\n @Field(type => Int, { description: 'forms that never installed' })\n missing: number\n\n @Field(type => Int, { description: 'doors this plant said it does not use' })\n notUsed: number\n\n /**\n * 이 제품이 내놓는 역할 자리 중 **이 공장에 실제로 선 것.**\n *\n * ── 왜 문 목록에 자리 수가 붙나 ────────────────────────────────────────\n * 문이 비었다는 말만 하면 사람은 양식 화면으로 간다. 그런데 **고를 역할이 없으면 그 화면의\n * 결재선 칸이 빈 목록**이다. 헛걸음하고 돌아와서, 무엇이 잘못됐는지 모른 채 이 화면을 다시 본다.\n *\n * 두 수를 함께 내면 화면이 순서를 말할 수 있다 — 자리부터 세우고, 그다음에 결재선을 건다.\n */\n @Field(type => Int, { description: 'how many of the role seats this product offers actually exist here' })\n seatsStanding: number\n\n @Field(type => Int, { description: 'how many role seats this product offers' })\n seatsOffered: number\n}\n\n/**\n * 판단의 모양을 화면의 모양으로. 판단부의 낱말(`'line-empty'`)을 열거형 **값**으로 찾아 멤버를 싣는다 —\n * 값과 낱말이 같게 적혀 있으니 표를 따로 들지 않는다. 못 찾으면 던진다: 새 낱말이 전선에서 조용히\n * 사라지면 화면이 「모른다」조차 못 그린다.\n */\nexport function toDoorType(door: WorkDoor): WorkDoorType {\n return {\n name: door.name,\n labelKey: door.labelKey,\n kind: member(DoorKindValue, door.kind),\n standing: member(DoorStandingValue, door.standing),\n reason: member(DoorReasonValue, door.reason),\n approvers: door.approvers,\n from: door.from,\n whenNoLine: door.whenNoLine ? member(WhenNoLineValue, door.whenNoLine) : undefined,\n whenNoLineBecause: door.whenNoLineBecause ? member(WhenNoLineBecauseValue, door.whenNoLineBecause) : undefined,\n followsLabelKey: door.followsLabelKey,\n assigneeRole: door.assigneeRole,\n notUsedBecause: door.notUsedBecause\n }\n}\n\nfunction member<T extends Record<string, string>>(values: T, word: string): T[keyof T] {\n const found = Object.values(values).find(one => one === word)\n\n if (!found) {\n throw new Error(`work door: no wire value for \"${word}\"`)\n }\n\n return found as T[keyof T]\n}\n"]}
|