@things-factory/worklist 10.1.270 → 10.1.271
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/components/activity-thread-timeline.d.ts +2 -2
- package/dist-client/pages/activity-instance/activity-instance-view.d.ts +2 -2
- package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view.d.ts +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-approval/_abort.js +2 -0
- package/dist-server/controllers/activity-approval/_abort.js.map +1 -1
- package/dist-server/controllers/activity-approval/claim.js +6 -1
- package/dist-server/controllers/activity-approval/claim.js.map +1 -1
- package/dist-server/controllers/common.js +2 -0
- package/dist-server/controllers/common.js.map +1 -1
- package/dist-server/service/activity-approval/index.d.ts +1 -1
- package/dist-server/service/approval-notice/approval-notice.d.ts +12 -0
- package/dist-server/service/approval-notice/approval-notice.js +19 -0
- package/dist-server/service/approval-notice/approval-notice.js.map +1 -1
- package/dist-server/service/index.d.ts +3 -3
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/tests/approval-notice-db.test.ts +3 -1
- package/tests/delegate-approval.test.ts +3 -1
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports._abort = _abort;
|
|
4
4
|
const activity_thread_js_1 = require("../../service/activity-thread/activity-thread.js");
|
|
5
5
|
const opinion_js_1 = require("./opinion.js");
|
|
6
|
+
const approval_notice_js_1 = require("../../service/approval-notice/approval-notice.js");
|
|
6
7
|
const activity_approval_js_1 = require("../../service/activity-approval/activity-approval.js");
|
|
7
8
|
async function _abort({ activityApproval, comment }, context) {
|
|
8
9
|
const { user, tx } = context.state;
|
|
@@ -24,6 +25,7 @@ async function _abort({ activityApproval, comment }, context) {
|
|
|
24
25
|
terminatedAt: new Date(),
|
|
25
26
|
terminator: user
|
|
26
27
|
});
|
|
28
|
+
await (0, approval_notice_js_1.closeApprovalNotices)(tx, [activityApproval]);
|
|
27
29
|
return result;
|
|
28
30
|
}
|
|
29
31
|
//# sourceMappingURL=_abort.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_abort.js","sourceRoot":"","sources":["../../../server/controllers/activity-approval/_abort.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"_abort.js","sourceRoot":"","sources":["../../../server/controllers/activity-approval/_abort.ts"],"names":[],"mappings":";;AAKA,wBA4BC;AAjCD,yFAAuG;AACvG,6CAA6C;AAC7C,yFAAuF;AACvF,+FAAiH;AAE1G,KAAK,UAAU,MAAM,CAC1B,EAAE,gBAAgB,EAAE,OAAO,EAA2D,EACtF,OAAwB;IAExB,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAElC,IAAI,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uCAAgB,CAAC,CAAC,IAAI,CAAC;QACzD,GAAG,gBAAgB;QACnB,QAAQ,EAAE,+CAAwB,CAAC,OAAO;QAC1C,GAAG,IAAA,2BAAc,EAAC,OAAO,CAAC;QAC1B,WAAW,EAAE,OAAO;QACpB,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,IAAI,IAAI,EAAE;QACxB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAA;IAEF,MAAM,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAC,IAAI,CAAC;QAC1C,GAAG,gBAAgB,CAAC,cAAc;QAClC,WAAW,EAAE,OAAO;QACpB,MAAM,EAAE,OAAO;QACf,KAAK,EAAE,yCAAoB,CAAC,OAAO;QACnC,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,IAAI,IAAI,EAAE;QACxB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAA;IAEF,MAAM,IAAA,yCAAoB,EAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAClD,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread.js'\nimport { stampedComment } from './opinion.js'\nimport { closeApprovalNotices } from '../../service/approval-notice/approval-notice.js'\nimport { ActivityApproval, ActivityApprovalJudgment } from '../../service/activity-approval/activity-approval.js'\n\nexport async function _abort(\n { activityApproval, comment }: { activityApproval: ActivityApproval; comment: string },\n context: ResolverContext\n): Promise<ActivityApproval> {\n const { user, tx } = context.state\n\n var result = await tx.getRepository(ActivityApproval).save({\n ...activityApproval,\n judgment: ActivityApprovalJudgment.Aborted,\n ...stampedComment(comment),\n transaction: 'abort',\n updater: user,\n terminatedAt: new Date(),\n terminator: user\n })\n\n await tx.getRepository(ActivityThread).save({\n ...activityApproval.activityThread,\n transaction: 'abort',\n reason: comment,\n state: ActivityThreadStatus.Aborted,\n updater: user,\n terminatedAt: new Date(),\n terminator: user\n })\n\n await closeApprovalNotices(tx, [activityApproval])\n return result\n}\n"]}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.claimPendingApproval = claimPendingApproval;
|
|
4
4
|
const activity_approval_js_1 = require("../../service/activity-approval/activity-approval.js");
|
|
5
|
+
const approval_notice_js_1 = require("../../service/approval-notice/approval-notice.js");
|
|
5
6
|
/**
|
|
6
7
|
* 이 결재를 내가 잡는다 — **대기 중인 것만, 한 번만.**
|
|
7
8
|
*
|
|
@@ -72,6 +73,10 @@ async function claimPendingApproval(tx, approval, judgment) {
|
|
|
72
73
|
* Elsewhere the same `?? 0` was a defect — a missing count drawn as 「0 waiting」 — so the two
|
|
73
74
|
* are worth telling apart rather than tidying into one habit.
|
|
74
75
|
*/
|
|
75
|
-
|
|
76
|
+
const claimed = (result.affected ?? 0) > 0;
|
|
77
|
+
/* the turn is no one's any more - its notices leave the screens (ADR-0164 amendment 1) */
|
|
78
|
+
if (claimed)
|
|
79
|
+
await (0, approval_notice_js_1.closeApprovalNotices)(tx, [approval]);
|
|
80
|
+
return claimed;
|
|
76
81
|
}
|
|
77
82
|
//# sourceMappingURL=claim.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claim.js","sourceRoot":"","sources":["../../../server/controllers/activity-approval/claim.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"claim.js","sourceRoot":"","sources":["../../../server/controllers/activity-approval/claim.ts"],"names":[],"mappings":";;AA4CA,oDAyCC;AAnFD,+FAAiH;AACjH,yFAAuF;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACI,KAAK,UAAU,oBAAoB,CACxC,EAAiB,EACjB,QAA0B,EAC1B,QAAkC;IAElC;;;;OAIG;IACH,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAA;IACxF,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,EAAE;SACpB,kBAAkB,EAAE;SACpB,MAAM,CAAC,uCAAgB,CAAC;SACxB,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC;SACjB,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;QACvC;;;WAGG;SACF,QAAQ,CAAC,2CAA2C,EAAE,EAAE,OAAO,EAAE,+CAAwB,CAAC,OAAO,EAAE,CAAC;SACpG,OAAO,EAAE,CAAA;IAEZ;;;;;;;;;;OAUG;IACH,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;IAC1C,0FAA0F;IAC1F,IAAI,OAAO;QAAE,MAAM,IAAA,yCAAoB,EAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IACvD,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import { EntityManager } from 'typeorm'\n\nimport { ActivityApproval, ActivityApprovalJudgment } from '../../service/activity-approval/activity-approval.js'\nimport { closeApprovalNotices } from '../../service/approval-notice/approval-notice.js'\n\n/**\n * 이 결재를 내가 잡는다 — **대기 중인 것만, 한 번만.**\n *\n * ── 왜 필요한가 ────────────────────────────────────────────────────────────\n * 승인·반려·위임이 다 같은 모양으로 시작한다. 읽고 → 「대기 중인가」 보고 → 저장한다. 그 사이에 아무\n * 잠금이 없다.\n *\n * 역할로 걸린 결재는 **여러 명이 같은 건을 본다.** 대기 목록에 뜬 것을 두 사람이 누르는 것은 공유\n * 대기열의 평범한 실패 방식이다. 지금은 둘 다 검사를 통과하고 **둘 다 다음 결재자를 만든다** — 같은\n * 차례의 결재가 두 벌 서서 결재선이 갈라진다. 오류는 안 난다.\n *\n * ── 검사와 쓰기를 한 문장으로 ──────────────────────────────────────────────\n * `WHERE judgment = ''` 를 갱신에 붙인다. 늦게 온 쪽은 0줄을 고치고, 그것으로 「남이 먼저 처리했다」를\n * 안다.\n *\n * 두 트랜잭션이 겹치면 뒤엣것이 행 잠금 앞에서 멈춰 섰다가, 앞엣것이 커밋한 뒤 조건을 **다시 보고**\n * 0줄을 얻는다. 세 드라이버 다 그렇게 동작한다 — postgres 는 잠금이 풀린 뒤 조건을 다시 보고, mysql\n * InnoDB 는 갱신 시 최신 커밋본을 읽고, sqlite 는 쓰기를 아예 직렬화한다.\n *\n * ── 잡고 나면 그 행은 이 트랜잭션 것이다 ───────────────────────────────────\n * 잡는 순간 행 잠금을 쥐므로, 나머지는 평범하게 저장해도 된다. 그래서 여기서는 **판정 하나만** 원자적으로\n * 바꾼다 — 지키려는 규칙이 「대기 중인 것만 처리할 수 있다」 하나이기 때문이다.\n *\n * ── 왜 `@VersionColumn` 이 아닌가 ──────────────────────────────────────────\n * 버전 칸은 컬럼을 늘려 마이그레이션이 필요하고, 이 규칙과 무관한 저장(의견 수정)까지 충돌시킨다.\n * 이미 코드에 있는 검사를 그대로 갱신 문장으로 옮기는 편이 정확하고, 스키마를 안 건드려 배포해도\n * 기존 데이터에 영향이 없다. (2026-08-31, 사용자 결정)\n *\n * ── 잡은 뒤의 저장은 안전하다 ─────────────────────────────────────────────\n * 부르는 쪽은 잡기 뒤에 `save({ ...approval, judgment, comment, … })` 로 나머지를 쓴다. 손에 든\n * `approval` 은 잡기 **전에** 읽은 것이라 판정이 낡았는데, 그 저장이 판정을 다시 명시하므로 되돌리지\n * 않는다. 그리고 잡는 순간 행 잠금을 쥐었으므로 그 사이에 남이 끼어들 수 없다.\n *\n * 한 문장으로 합치지 않은 이유는 관계 칸 때문이다 — `updater`·`terminator`·`originalApproval` 이\n * 엔티티 객체이고, `save()` 는 이것을 FK 로 풀어 주지만 `UpdateQueryBuilder.set()` 은 버전에 따라\n * 다르다. 풀리지 않으면 「누가 처리했나」가 비고 **오류는 안 난다.**\n *\n * @returns 잡았으면 참. 거짓이면 **남이 먼저 처리했다** — 부르는 쪽이 던져서 트랜잭션을 물려야 한다.\n */\nexport async function claimPendingApproval(\n tx: EntityManager,\n approval: ActivityApproval,\n judgment: ActivityApprovalJudgment\n): Promise<boolean> {\n /*\n * 대기로 잡으면 조건이 통과하는데 판정이 그대로라 **두 번째 호출도 통과한다.** 잡는 뜻이 없어진다.\n *\n * `Pending` 은 빈 문자열이라 이 한 줄에 함께 걸린다 — 타입 검사도 그렇게 좁혀 준다.\n */\n if (!judgment) {\n throw new Error('claimPendingApproval: a claim must move the judgment out of pending')\n }\n\n const result = await tx\n .createQueryBuilder()\n .update(ActivityApproval)\n .set({ judgment })\n .where('id = :id', { id: approval.id })\n /*\n * 대기 중은 빈 문자열이다(`ActivityApprovalJudgment.Pending`). `IS NULL` 도 함께 보는 이유는 기본값이\n * 안 들어간 옛 행이 있을 수 있어서다 — 그런 행을 못 잡으면 그 결재는 영영 처리되지 않는다.\n */\n .andWhere('(judgment = :pending OR judgment IS NULL)', { pending: ActivityApprovalJudgment.Pending })\n .execute()\n\n /*\n * `?? 0` here is deliberate, and it is the opposite of the same expression elsewhere.\n *\n * A missing row count means we do not know whether this claim took. For a conditional update\n * that hands one person an approval, not knowing has to read as \"did not get it\": refusing a\n * claim costs a retry, while granting one on an unknown result lets two people judge the same\n * request. The unknown value maps to the conservative answer on purpose.\n *\n * Elsewhere the same `?? 0` was a defect — a missing count drawn as 「0 waiting」 — so the two\n * are worth telling apart rather than tidying into one habit.\n */\n const claimed = (result.affected ?? 0) > 0\n /* the turn is no one's any more - its notices leave the screens (ADR-0164 amendment 1) */\n if (claimed) await closeApprovalNotices(tx, [approval])\n return claimed\n}\n"]}
|
|
@@ -21,6 +21,7 @@ const activity_approval_js_1 = require("../service/activity-approval/activity-ap
|
|
|
21
21
|
const activity_installation_controller_js_1 = require("./activity-installation/activity-installation-controller.js");
|
|
22
22
|
const assignee_pool_js_1 = require("../service/activity-instance/assignee-pool.js");
|
|
23
23
|
const assignee_input_js_1 = require("./activity-instance/assignee-input.js");
|
|
24
|
+
const approval_notice_js_1 = require("../service/approval-notice/approval-notice.js");
|
|
24
25
|
async function updateActivityInstanceState(id, { causedBy }, context) {
|
|
25
26
|
const { tx } = context.state;
|
|
26
27
|
var activityInstance = await tx.getRepository(activity_instance_js_1.ActivityInstance).findOne({
|
|
@@ -87,6 +88,7 @@ async function closePendingReferences(instanceId, context) {
|
|
|
87
88
|
transaction: 'close',
|
|
88
89
|
terminatedAt: at
|
|
89
90
|
})));
|
|
91
|
+
await (0, approval_notice_js_1.closeApprovalNotices)(tx, open);
|
|
90
92
|
}
|
|
91
93
|
async function evalActivityInstanceState(id, context) {
|
|
92
94
|
const { tx, user } = context.state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../server/controllers/common.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\n\nimport { Role, User } from '@things-factory/auth-base'\n\nimport { Department, Employee, ApprovalLineItem, OrgMemberTargetType } from '@things-factory/organization'\nimport { ActivitySearchKeyItem } from '../service/activity/activity-search-key-item-type.js'\nimport { AssigneeItem, MultipleInstanceType } from '../service/activity/activity.js'\nimport { ActivityInstance, ActivityInstanceStatus } from '../service/activity-instance/activity-instance.js'\nimport { ActivityThread, ActivityThreadStatus } from '../service/activity-thread/activity-thread.js'\nimport { ActivityApproval, ActivityApprovalJudgment } from '../service/activity-approval/activity-approval.js'\nimport { ActivityInstallations } from './activity-installation/activity-installation-controller.js'\nimport { poolIdsOf, poolMembers } from '../service/activity-instance/assignee-pool.js'\nimport { ROLE_IS_NOT_AN_ASSIGNEE } from './activity-instance/assignee-input.js'\n\nexport type UpdateActivityInstanceStateAddendum = {\n causedBy?: ActivityThread[]\n}\n\nexport async function updateActivityInstanceState(\n id: string,\n { causedBy }: UpdateActivityInstanceStateAddendum,\n context: ResolverContext\n) {\n const { tx } = context.state\n\n var activityInstance = await tx.getRepository(ActivityInstance).findOne({\n where: { id },\n relations: [\n 'domain',\n 'activity',\n 'activityThreads',\n 'assigneeRoles',\n 'supervisoryRole',\n 'updater',\n 'creator',\n 'starter',\n 'terminator'\n ]\n })\n\n activityInstance.transaction = 'thread' /* activity thread에 의해서 변경된 것임을 의미 */\n Object.assign(activityInstance, await evalActivityInstanceState(id, context))\n\n /*\n * **건이 끝나면 참조도 닫는다.**\n *\n * 참조는 결재하지 않으므로 승인·반려로 끝나지 않는다. 닫아 주지 않으면 그 행이 `Pending` 으로 남아\n * 참조 목록에 영원히 나온다 — 오늘 결재자 쪽에서 고친 것과 같은 부류를, 참조를 넣으면서 새로 만들 뻔했다.\n *\n * 중단은 이미 닫힌다(§`activity-thread/_abort.ts` 가 대기 행을 `aborted` 로 닫는다). 여기서 닫는 것은\n * **정상 종료**다.\n */\n if (activityInstance.state === ActivityInstanceStatus.Ended) {\n await closePendingReferences(id, context)\n }\n\n /* callback에서 업무적인 처리도 하고, activityInstance를 일부(주로 input) 수정할 수 있는 기회도 제공. */\n await ActivityInstallations.callback(activityInstance.activity.name, activityInstance, causedBy, context)\n\n await tx.getRepository(ActivityInstance).save(activityInstance)\n}\n\n/**\n * 이 건의 아직 안 닫힌 참조들을 닫는다 — **판정한 것이 아니라 건이 끝난 것이다.**\n *\n * 의견을 냈는지는 `comment` 가 말한다. 비어 있으면 「통지받았고 말하지 않았다」이고, **그것은 동의가\n * 아니다** — 나중에 결재 이력을 읽는 사람이 침묵을 동의로 읽으면 안 된다.\n *\n * `terminator` 를 적지 않는다. 그 사람이 끝낸 것이 아니라 건이 끝난 것이다.\n */\nasync function closePendingReferences(instanceId: string, context: ResolverContext): Promise<void> {\n const { tx } = context.state\n\n const threads = await tx.getRepository(ActivityThread).find({\n where: { activityInstance: { id: instanceId } }\n })\n if (!threads.length) return\n\n const repo = tx.getRepository(ActivityApproval)\n const open = await repo.find({\n where: threads.map(t => ({\n activityThread: { id: t.id },\n participation: 'reference',\n judgment: ActivityApprovalJudgment.Pending\n }))\n })\n if (!open.length) return\n\n const at = new Date()\n await repo.save(\n open.map(row => ({\n ...row,\n judgment: ActivityApprovalJudgment.Closed,\n transaction: 'close',\n terminatedAt: at\n })) as any\n )\n}\n\nexport async function evalActivityInstanceState(\n id: string,\n context: ResolverContext\n): Promise<Partial<ActivityInstance>> {\n const { tx, user } = context.state\n\n const activityInstance = await tx.getRepository(ActivityInstance).findOne({\n where: { id },\n relations: ['activityThreads', 'activity']\n })\n const { threadsMin, activityThreads, state, dueAt } = activityInstance\n\n const validThreads = activityThreads.filter(thread => thread.isValid())\n const pendingStartedThreads = activityThreads.filter(thread => thread.isPendingStarted())\n const pendingEndedThreads = activityThreads.filter(thread => thread.isPendingEnded())\n\n switch (true) {\n case state === ActivityInstanceStatus.Draft:\n case state === ActivityInstanceStatus.Ended:\n case state === ActivityInstanceStatus.Aborted:\n return {}\n case validThreads.length === 0:\n return {\n state: ActivityInstanceStatus.Issued\n }\n case threadsMin > validThreads.length:\n return {\n state: ActivityInstanceStatus.Unassigned\n }\n case pendingStartedThreads.length > 0:\n return {\n state: ActivityInstanceStatus.Assigned,\n assignedAt: new Date()\n }\n case pendingEndedThreads.length > 0:\n var started = !dueAt || dueAt.getTime() > Date.now()\n var changed =\n (started && state !== ActivityInstanceStatus.Started) || (!started && state !== ActivityInstanceStatus.Pending)\n\n return !changed\n ? null\n : started\n ? {\n state: ActivityInstanceStatus.Started,\n startedAt: new Date(),\n starter: user\n }\n : {\n state: ActivityInstanceStatus.Pending\n }\n default:\n return {\n state: activityThreads.some(thread => thread.state == ActivityThreadStatus.Aborted)\n ? ActivityInstanceStatus.Aborted\n : ActivityInstanceStatus.Ended,\n reason: '',\n output: [MultipleInstanceType.Parallel, MultipleInstanceType.Sequential].includes(\n activityInstance.activity.multiple\n )\n ? activityThreads\n .filter(thread => thread.state === ActivityThreadStatus.Ended)\n .reduce((sum, thread) => {\n sum[thread.assigneeId] = thread.output\n return sum\n }, {} as any)\n : activityThreads[0].output,\n terminatedAt: new Date(),\n terminator: user\n }\n }\n}\n\nexport async function createActivityThreadWithUnassigned(\n transaction: string,\n activityInstance: ActivityInstance,\n context: ResolverContext\n): Promise<ActivityThread> {\n const result = await saveWaitingThread(transaction, activityInstance, context)\n\n await updateActivityInstanceState(activityInstance.id, { causedBy: [result] }, context)\n\n return result\n}\n\n/**\n * Someone of the pool has just taken a thread of this case - by pick, or by claiming the waiting thread. Is\n * the case still short of people (fewer threads someone holds than `threadsMin`)? Then the rest of the pool\n * is left one waiting thread to take; once it has enough, none.\n *\n * The waiting thread is what puts the case on the pool's to-do lists (my-open-threads.ts). Left behind after\n * the case had its people, it kept the case on the list of everyone in the pool; gone while the case still\n * waited, nobody else in the pool saw it any more.\n *\n * `threads` are the case's threads as they stand once the taker holds theirs, read under the hold on the case.\n * The case's state is not worked out here - the taker does that once, after writing its own thread.\n */\nexport async function leaveTheRestOfThePoolOneWaiting(\n transaction: string,\n activityInstance: ActivityInstance,\n threads: ActivityThread[],\n context: ResolverContext\n): Promise<void> {\n const held = threads.filter(thread => thread.isValid()).length\n const waiting = threads.some(thread => thread.state === ActivityThreadStatus.Unassigned)\n\n if (held < activityInstance.threadsMin && !waiting) {\n await saveWaitingThread(transaction, activityInstance, context)\n }\n}\n\nasync function saveWaitingThread(\n transaction: string,\n activityInstance: ActivityInstance,\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n const threadRepo = tx.getRepository(ActivityThread)\n const now = new Date()\n\n return await threadRepo.save({\n version: 1,\n domain,\n state: ActivityThreadStatus.Unassigned,\n activityInstance,\n transaction,\n output: activityInstance.output,\n dueAt: activityInstance.dueAt,\n assignedAt: now,\n creator: user,\n updater: user,\n createdAt: now\n })\n}\n\nexport async function createActivityThreadForUser(\n transaction: string,\n activityInstance: ActivityInstance,\n assignee: User,\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n const threadRepo = tx.getRepository(ActivityThread)\n const now = new Date()\n\n const result = await threadRepo.save({\n version: 1,\n domain,\n assignee,\n state: ActivityThreadStatus.Assigned,\n activityInstance,\n transaction,\n output: activityInstance.output,\n dueAt: activityInstance.dueAt,\n assignedAt: now,\n creator: user,\n updater: user,\n createdAt: now\n })\n\n await updateActivityInstanceState(activityInstance.id, { causedBy: [result] }, context)\n\n return result\n}\n\nexport async function createActivityThreadsForUsers(\n transaction: string,\n activityInstance: ActivityInstance,\n assignees: User[],\n context: ResolverContext\n): Promise<ActivityThread[]> {\n const { domain, user, tx } = context.state\n\n const threadRepo = tx.getRepository(ActivityThread)\n const now = new Date()\n\n const distinct = assignees.filter((assignee, idx) => {\n return assignee && !assignees.slice(0, idx).find(x => x.id == assignee.id)\n })\n\n const result = await threadRepo.save(\n distinct.map(assignee => {\n return {\n version: 1,\n assignee,\n state: ActivityThreadStatus.Assigned,\n activityInstance,\n domain,\n transaction,\n output: activityInstance.output,\n creator: user,\n updater: user,\n dueAt: activityInstance.dueAt,\n assignedAt: now\n } as any\n })\n )\n\n await updateActivityInstanceState(activityInstance.id, { causedBy: result }, context)\n\n return result\n}\n\nexport async function createActivityThreadsForAllRoleUsers(\n transaction: string,\n activityInstance: ActivityInstance,\n context: ResolverContext\n): Promise<ActivityThread[]> {\n const { tx } = context.state\n\n /* Everyone the pool reaches - any one of its roles, each person once (assignee-pool.ts). */\n const poolIds = poolIdsOf(activityInstance)\n const roles = poolIds.length ? await tx.getRepository(Role).find({ where: { id: In(poolIds) }, relations: ['users'] }) : []\n const assignees = poolMembers(roles)\n\n if (assignees.length === 0) {\n throw new Error(context.t('error.no user holds the assignee roles', { roles: roles.map(role => role.name).join(', ') }))\n }\n\n // create activity-thread for all of users having given role\n return await createActivityThreadsForUsers(transaction, activityInstance, assignees, context)\n}\n\nexport async function getSystemUserFromMyDepartmentManager(context: ResolverContext): Promise<User> {\n const { domain, user, tx } = context.state\n\n const employee = await tx.getRepository(Employee).findOneBy({\n domain: { id: domain.id },\n user: { id: user.id }\n })\n\n if (!employee || !employee.departmentId) {\n return\n }\n\n const department = await tx.getRepository(Department).findOne({\n where: {\n id: employee.departmentId\n }\n })\n\n if (!department || !department.managerId) return\n\n const manager = await tx.getRepository(Employee).findOne({\n where: {\n domain: { id: domain.id },\n id: department.managerId\n },\n relations: ['user']\n })\n\n return manager?.user\n}\n\nexport async function getSystemUserFromMySupervosor(context: ResolverContext): Promise<User> {\n const { domain, user, tx } = context.state\n\n const employee = await tx.getRepository(Employee).findOneBy({\n domain: { id: domain.id },\n user: { id: user.id }\n })\n\n if (!employee || !employee.supervisorId) {\n return\n }\n\n const supervisor = await tx.getRepository(Employee).findOne({\n where: {\n id: employee.supervisorId\n },\n relations: ['user']\n })\n\n return supervisor?.user\n}\n\nexport async function getSystemUserFromOrgMemberItem(\n item: AssigneeItem | ApprovalLineItem,\n context: ResolverContext\n): Promise<User> {\n const { domain, user, tx } = context.state\n\n const { type, approver, assignee, value } = item as AssigneeItem & ApprovalLineItem\n const id = approver?.id || assignee?.id || value\n\n if (type == OrgMemberTargetType.Employee) {\n /* This domain's only - an id from another tenant made that tenant's person an approver here. */\n const employee =\n id && (await tx.getRepository(Employee).findOne({ where: { domain: { id: domain.id }, id }, relations: ['user'] }))\n\n if (!employee || !employee.user) {\n return\n }\n return employee.user\n } else if (type == OrgMemberTargetType.Department) {\n const department =\n id && (await tx.getRepository(Department).findOne({ where: { domain: { id: domain.id }, id }, relations: ['manager'] }))\n\n if (!department || !department.manager) {\n return\n }\n return await tx.getRepository(User).findOneBy({ id: department.manager.userId })\n } else if (type == OrgMemberTargetType.Role) {\n /*\n * A role is not one person. This answered the role's first user - an unordered relation, so an\n * arbitrary one - and issue() gave that person work meant for the whole role. Each caller decides\n * what a role means there before asking this: the approval line seats the role (create-approval.ts),\n * assignees refuse it (assignee-input.ts). Reaching here is a caller that skipped that step.\n */\n throw Object.assign(new Error(context.t('error.activity-instance a role is not an assignee')), {\n code: ROLE_IS_NOT_AN_ASSIGNEE\n })\n } else if (type == OrgMemberTargetType.Myself) {\n return user\n } else if (type == OrgMemberTargetType.MyDepartment) {\n return await getSystemUserFromMyDepartmentManager(context)\n } else if (type == OrgMemberTargetType.MySupervisor) {\n return await getSystemUserFromMySupervosor(context)\n }\n}\n\nexport function fillActivitySearchKeys(searchKeys: ActivitySearchKeyItem[], input: { [key: string]: any }) {\n if (!input || typeof input !== 'object') {\n return\n }\n\n return searchKeys?.reduce((sum, key, index) => {\n const value = input[key.inputKey]\n if (value != null) {\n sum[`key0${index + 1}`] = value instanceof Array ? value[0] : value\n }\n return sum\n }, {})\n}\n"]}
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../server/controllers/common.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\n\nimport { Role, User } from '@things-factory/auth-base'\n\nimport { Department, Employee, ApprovalLineItem, OrgMemberTargetType } from '@things-factory/organization'\nimport { ActivitySearchKeyItem } from '../service/activity/activity-search-key-item-type.js'\nimport { AssigneeItem, MultipleInstanceType } from '../service/activity/activity.js'\nimport { ActivityInstance, ActivityInstanceStatus } from '../service/activity-instance/activity-instance.js'\nimport { ActivityThread, ActivityThreadStatus } from '../service/activity-thread/activity-thread.js'\nimport { ActivityApproval, ActivityApprovalJudgment } from '../service/activity-approval/activity-approval.js'\nimport { ActivityInstallations } from './activity-installation/activity-installation-controller.js'\nimport { poolIdsOf, poolMembers } from '../service/activity-instance/assignee-pool.js'\nimport { ROLE_IS_NOT_AN_ASSIGNEE } from './activity-instance/assignee-input.js'\nimport { closeApprovalNotices } from '../service/approval-notice/approval-notice.js'\n\nexport type UpdateActivityInstanceStateAddendum = {\n causedBy?: ActivityThread[]\n}\n\nexport async function updateActivityInstanceState(\n id: string,\n { causedBy }: UpdateActivityInstanceStateAddendum,\n context: ResolverContext\n) {\n const { tx } = context.state\n\n var activityInstance = await tx.getRepository(ActivityInstance).findOne({\n where: { id },\n relations: [\n 'domain',\n 'activity',\n 'activityThreads',\n 'assigneeRoles',\n 'supervisoryRole',\n 'updater',\n 'creator',\n 'starter',\n 'terminator'\n ]\n })\n\n activityInstance.transaction = 'thread' /* activity thread에 의해서 변경된 것임을 의미 */\n Object.assign(activityInstance, await evalActivityInstanceState(id, context))\n\n /*\n * **건이 끝나면 참조도 닫는다.**\n *\n * 참조는 결재하지 않으므로 승인·반려로 끝나지 않는다. 닫아 주지 않으면 그 행이 `Pending` 으로 남아\n * 참조 목록에 영원히 나온다 — 오늘 결재자 쪽에서 고친 것과 같은 부류를, 참조를 넣으면서 새로 만들 뻔했다.\n *\n * 중단은 이미 닫힌다(§`activity-thread/_abort.ts` 가 대기 행을 `aborted` 로 닫는다). 여기서 닫는 것은\n * **정상 종료**다.\n */\n if (activityInstance.state === ActivityInstanceStatus.Ended) {\n await closePendingReferences(id, context)\n }\n\n /* callback에서 업무적인 처리도 하고, activityInstance를 일부(주로 input) 수정할 수 있는 기회도 제공. */\n await ActivityInstallations.callback(activityInstance.activity.name, activityInstance, causedBy, context)\n\n await tx.getRepository(ActivityInstance).save(activityInstance)\n}\n\n/**\n * 이 건의 아직 안 닫힌 참조들을 닫는다 — **판정한 것이 아니라 건이 끝난 것이다.**\n *\n * 의견을 냈는지는 `comment` 가 말한다. 비어 있으면 「통지받았고 말하지 않았다」이고, **그것은 동의가\n * 아니다** — 나중에 결재 이력을 읽는 사람이 침묵을 동의로 읽으면 안 된다.\n *\n * `terminator` 를 적지 않는다. 그 사람이 끝낸 것이 아니라 건이 끝난 것이다.\n */\nasync function closePendingReferences(instanceId: string, context: ResolverContext): Promise<void> {\n const { tx } = context.state\n\n const threads = await tx.getRepository(ActivityThread).find({\n where: { activityInstance: { id: instanceId } }\n })\n if (!threads.length) return\n\n const repo = tx.getRepository(ActivityApproval)\n const open = await repo.find({\n where: threads.map(t => ({\n activityThread: { id: t.id },\n participation: 'reference',\n judgment: ActivityApprovalJudgment.Pending\n }))\n })\n if (!open.length) return\n\n const at = new Date()\n await repo.save(\n open.map(row => ({\n ...row,\n judgment: ActivityApprovalJudgment.Closed,\n transaction: 'close',\n terminatedAt: at\n })) as any\n )\n await closeApprovalNotices(tx, open)\n}\n\nexport async function evalActivityInstanceState(\n id: string,\n context: ResolverContext\n): Promise<Partial<ActivityInstance>> {\n const { tx, user } = context.state\n\n const activityInstance = await tx.getRepository(ActivityInstance).findOne({\n where: { id },\n relations: ['activityThreads', 'activity']\n })\n const { threadsMin, activityThreads, state, dueAt } = activityInstance\n\n const validThreads = activityThreads.filter(thread => thread.isValid())\n const pendingStartedThreads = activityThreads.filter(thread => thread.isPendingStarted())\n const pendingEndedThreads = activityThreads.filter(thread => thread.isPendingEnded())\n\n switch (true) {\n case state === ActivityInstanceStatus.Draft:\n case state === ActivityInstanceStatus.Ended:\n case state === ActivityInstanceStatus.Aborted:\n return {}\n case validThreads.length === 0:\n return {\n state: ActivityInstanceStatus.Issued\n }\n case threadsMin > validThreads.length:\n return {\n state: ActivityInstanceStatus.Unassigned\n }\n case pendingStartedThreads.length > 0:\n return {\n state: ActivityInstanceStatus.Assigned,\n assignedAt: new Date()\n }\n case pendingEndedThreads.length > 0:\n var started = !dueAt || dueAt.getTime() > Date.now()\n var changed =\n (started && state !== ActivityInstanceStatus.Started) || (!started && state !== ActivityInstanceStatus.Pending)\n\n return !changed\n ? null\n : started\n ? {\n state: ActivityInstanceStatus.Started,\n startedAt: new Date(),\n starter: user\n }\n : {\n state: ActivityInstanceStatus.Pending\n }\n default:\n return {\n state: activityThreads.some(thread => thread.state == ActivityThreadStatus.Aborted)\n ? ActivityInstanceStatus.Aborted\n : ActivityInstanceStatus.Ended,\n reason: '',\n output: [MultipleInstanceType.Parallel, MultipleInstanceType.Sequential].includes(\n activityInstance.activity.multiple\n )\n ? activityThreads\n .filter(thread => thread.state === ActivityThreadStatus.Ended)\n .reduce((sum, thread) => {\n sum[thread.assigneeId] = thread.output\n return sum\n }, {} as any)\n : activityThreads[0].output,\n terminatedAt: new Date(),\n terminator: user\n }\n }\n}\n\nexport async function createActivityThreadWithUnassigned(\n transaction: string,\n activityInstance: ActivityInstance,\n context: ResolverContext\n): Promise<ActivityThread> {\n const result = await saveWaitingThread(transaction, activityInstance, context)\n\n await updateActivityInstanceState(activityInstance.id, { causedBy: [result] }, context)\n\n return result\n}\n\n/**\n * Someone of the pool has just taken a thread of this case - by pick, or by claiming the waiting thread. Is\n * the case still short of people (fewer threads someone holds than `threadsMin`)? Then the rest of the pool\n * is left one waiting thread to take; once it has enough, none.\n *\n * The waiting thread is what puts the case on the pool's to-do lists (my-open-threads.ts). Left behind after\n * the case had its people, it kept the case on the list of everyone in the pool; gone while the case still\n * waited, nobody else in the pool saw it any more.\n *\n * `threads` are the case's threads as they stand once the taker holds theirs, read under the hold on the case.\n * The case's state is not worked out here - the taker does that once, after writing its own thread.\n */\nexport async function leaveTheRestOfThePoolOneWaiting(\n transaction: string,\n activityInstance: ActivityInstance,\n threads: ActivityThread[],\n context: ResolverContext\n): Promise<void> {\n const held = threads.filter(thread => thread.isValid()).length\n const waiting = threads.some(thread => thread.state === ActivityThreadStatus.Unassigned)\n\n if (held < activityInstance.threadsMin && !waiting) {\n await saveWaitingThread(transaction, activityInstance, context)\n }\n}\n\nasync function saveWaitingThread(\n transaction: string,\n activityInstance: ActivityInstance,\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n const threadRepo = tx.getRepository(ActivityThread)\n const now = new Date()\n\n return await threadRepo.save({\n version: 1,\n domain,\n state: ActivityThreadStatus.Unassigned,\n activityInstance,\n transaction,\n output: activityInstance.output,\n dueAt: activityInstance.dueAt,\n assignedAt: now,\n creator: user,\n updater: user,\n createdAt: now\n })\n}\n\nexport async function createActivityThreadForUser(\n transaction: string,\n activityInstance: ActivityInstance,\n assignee: User,\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n const threadRepo = tx.getRepository(ActivityThread)\n const now = new Date()\n\n const result = await threadRepo.save({\n version: 1,\n domain,\n assignee,\n state: ActivityThreadStatus.Assigned,\n activityInstance,\n transaction,\n output: activityInstance.output,\n dueAt: activityInstance.dueAt,\n assignedAt: now,\n creator: user,\n updater: user,\n createdAt: now\n })\n\n await updateActivityInstanceState(activityInstance.id, { causedBy: [result] }, context)\n\n return result\n}\n\nexport async function createActivityThreadsForUsers(\n transaction: string,\n activityInstance: ActivityInstance,\n assignees: User[],\n context: ResolverContext\n): Promise<ActivityThread[]> {\n const { domain, user, tx } = context.state\n\n const threadRepo = tx.getRepository(ActivityThread)\n const now = new Date()\n\n const distinct = assignees.filter((assignee, idx) => {\n return assignee && !assignees.slice(0, idx).find(x => x.id == assignee.id)\n })\n\n const result = await threadRepo.save(\n distinct.map(assignee => {\n return {\n version: 1,\n assignee,\n state: ActivityThreadStatus.Assigned,\n activityInstance,\n domain,\n transaction,\n output: activityInstance.output,\n creator: user,\n updater: user,\n dueAt: activityInstance.dueAt,\n assignedAt: now\n } as any\n })\n )\n\n await updateActivityInstanceState(activityInstance.id, { causedBy: result }, context)\n\n return result\n}\n\nexport async function createActivityThreadsForAllRoleUsers(\n transaction: string,\n activityInstance: ActivityInstance,\n context: ResolverContext\n): Promise<ActivityThread[]> {\n const { tx } = context.state\n\n /* Everyone the pool reaches - any one of its roles, each person once (assignee-pool.ts). */\n const poolIds = poolIdsOf(activityInstance)\n const roles = poolIds.length ? await tx.getRepository(Role).find({ where: { id: In(poolIds) }, relations: ['users'] }) : []\n const assignees = poolMembers(roles)\n\n if (assignees.length === 0) {\n throw new Error(context.t('error.no user holds the assignee roles', { roles: roles.map(role => role.name).join(', ') }))\n }\n\n // create activity-thread for all of users having given role\n return await createActivityThreadsForUsers(transaction, activityInstance, assignees, context)\n}\n\nexport async function getSystemUserFromMyDepartmentManager(context: ResolverContext): Promise<User> {\n const { domain, user, tx } = context.state\n\n const employee = await tx.getRepository(Employee).findOneBy({\n domain: { id: domain.id },\n user: { id: user.id }\n })\n\n if (!employee || !employee.departmentId) {\n return\n }\n\n const department = await tx.getRepository(Department).findOne({\n where: {\n id: employee.departmentId\n }\n })\n\n if (!department || !department.managerId) return\n\n const manager = await tx.getRepository(Employee).findOne({\n where: {\n domain: { id: domain.id },\n id: department.managerId\n },\n relations: ['user']\n })\n\n return manager?.user\n}\n\nexport async function getSystemUserFromMySupervosor(context: ResolverContext): Promise<User> {\n const { domain, user, tx } = context.state\n\n const employee = await tx.getRepository(Employee).findOneBy({\n domain: { id: domain.id },\n user: { id: user.id }\n })\n\n if (!employee || !employee.supervisorId) {\n return\n }\n\n const supervisor = await tx.getRepository(Employee).findOne({\n where: {\n id: employee.supervisorId\n },\n relations: ['user']\n })\n\n return supervisor?.user\n}\n\nexport async function getSystemUserFromOrgMemberItem(\n item: AssigneeItem | ApprovalLineItem,\n context: ResolverContext\n): Promise<User> {\n const { domain, user, tx } = context.state\n\n const { type, approver, assignee, value } = item as AssigneeItem & ApprovalLineItem\n const id = approver?.id || assignee?.id || value\n\n if (type == OrgMemberTargetType.Employee) {\n /* This domain's only - an id from another tenant made that tenant's person an approver here. */\n const employee =\n id && (await tx.getRepository(Employee).findOne({ where: { domain: { id: domain.id }, id }, relations: ['user'] }))\n\n if (!employee || !employee.user) {\n return\n }\n return employee.user\n } else if (type == OrgMemberTargetType.Department) {\n const department =\n id && (await tx.getRepository(Department).findOne({ where: { domain: { id: domain.id }, id }, relations: ['manager'] }))\n\n if (!department || !department.manager) {\n return\n }\n return await tx.getRepository(User).findOneBy({ id: department.manager.userId })\n } else if (type == OrgMemberTargetType.Role) {\n /*\n * A role is not one person. This answered the role's first user - an unordered relation, so an\n * arbitrary one - and issue() gave that person work meant for the whole role. Each caller decides\n * what a role means there before asking this: the approval line seats the role (create-approval.ts),\n * assignees refuse it (assignee-input.ts). Reaching here is a caller that skipped that step.\n */\n throw Object.assign(new Error(context.t('error.activity-instance a role is not an assignee')), {\n code: ROLE_IS_NOT_AN_ASSIGNEE\n })\n } else if (type == OrgMemberTargetType.Myself) {\n return user\n } else if (type == OrgMemberTargetType.MyDepartment) {\n return await getSystemUserFromMyDepartmentManager(context)\n } else if (type == OrgMemberTargetType.MySupervisor) {\n return await getSystemUserFromMySupervosor(context)\n }\n}\n\nexport function fillActivitySearchKeys(searchKeys: ActivitySearchKeyItem[], input: { [key: string]: any }) {\n if (!input || typeof input !== 'object') {\n return\n }\n\n return searchKeys?.reduce((sum, key, index) => {\n const value = input[key.inputKey]\n if (value != null) {\n sum[`key0${index + 1}`] = value instanceof Array ? value[0] : value\n }\n return sum\n }, {})\n}\n"]}
|
|
@@ -4,5 +4,5 @@ import { ActivityApprovalMutation } from "./activity-approval-mutation.js";
|
|
|
4
4
|
import { ActivityApprovalSubscription } from "./activity-approval-subscription.js";
|
|
5
5
|
import { ActivityApprovalSubscriber } from "./event-subscriber.js";
|
|
6
6
|
export declare const entities: (typeof ActivityApproval)[];
|
|
7
|
-
export declare const resolvers: (typeof
|
|
7
|
+
export declare const resolvers: (typeof ActivityApprovalQuery | typeof ActivityApprovalMutation | typeof ActivityApprovalSubscription)[];
|
|
8
8
|
export declare const subscribers: (typeof ActivityApprovalSubscriber)[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EntityManager } from 'typeorm';
|
|
1
2
|
import { type ApprovalNoticeKind } from './approval-notice-rules.js';
|
|
2
3
|
/**
|
|
3
4
|
* Tells of what just happened to approval `approvalId`, once the transaction has committed.
|
|
@@ -9,3 +10,14 @@ export declare function noticeApproval(context: ResolverContext, { kind, approva
|
|
|
9
10
|
kind: ApprovalNoticeKind;
|
|
10
11
|
approvalId: string;
|
|
11
12
|
}): Promise<void>;
|
|
13
|
+
/** What a turn notice tells of - the approval row whose turn it is. */
|
|
14
|
+
export declare const approvalNoticeKey: (approvalId: string) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Closes the turn notices of approval rows that are no longer waiting - judged, handed on, withdrawn or closed with
|
|
17
|
+
* their case (ADR-0164 amendment 1): everyone the turn was told to, a role's holders too, reads it as read and no screen
|
|
18
|
+
* shows it. In the transaction that moved the rows, so a refused move closes nothing.
|
|
19
|
+
*/
|
|
20
|
+
export declare function closeApprovalNotices(tx: EntityManager, rows: readonly {
|
|
21
|
+
id: string;
|
|
22
|
+
domainId?: string;
|
|
23
|
+
}[]): Promise<void>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.approvalNoticeKey = void 0;
|
|
3
4
|
exports.noticeApproval = noticeApproval;
|
|
5
|
+
exports.closeApprovalNotices = closeApprovalNotices;
|
|
4
6
|
/*
|
|
5
7
|
* The approval notice (ADR-0164) - the one place the worklist tells people of an approval's turn and judgment.
|
|
6
8
|
*
|
|
@@ -57,6 +59,8 @@ async function noticeApproval(context, { kind, approvalId }) {
|
|
|
57
59
|
words: lng => (0, approval_notice_rules_js_1.noticeWords)(translatorOf(lng), facts),
|
|
58
60
|
address,
|
|
59
61
|
link: (0, notification_1.noticeLinkOf)(context, address),
|
|
62
|
+
/* a turn is closed once its row is judged (`closeApprovalNotices`); a judgment told is read by its person */
|
|
63
|
+
key: (0, approval_notice_rules_js_1.isTurnNotice)(kind) ? (0, exports.approvalNoticeKey)(approval.id) : `approval-thread:${thread.id}`,
|
|
60
64
|
label: `approval notice ${kind} of ${approval.id}`
|
|
61
65
|
}, result => (0, notification_1.keepNoticeDelivery)(activity_approval_js_1.ActivityApproval, approval.id, 'notices', (0, notification_1.noticeDeliveryOf)(kind, result, receivers.length)));
|
|
62
66
|
}
|
|
@@ -64,6 +68,21 @@ async function noticeApproval(context, { kind, approvalId }) {
|
|
|
64
68
|
env_1.logger.error(`[worklist] approval notice ${kind} of ${approvalId} could not be made`, error);
|
|
65
69
|
}
|
|
66
70
|
}
|
|
71
|
+
/** What a turn notice tells of - the approval row whose turn it is. */
|
|
72
|
+
const approvalNoticeKey = (approvalId) => `approval:${approvalId}`;
|
|
73
|
+
exports.approvalNoticeKey = approvalNoticeKey;
|
|
74
|
+
/**
|
|
75
|
+
* Closes the turn notices of approval rows that are no longer waiting - judged, handed on, withdrawn or closed with
|
|
76
|
+
* their case (ADR-0164 amendment 1): everyone the turn was told to, a role's holders too, reads it as read and no screen
|
|
77
|
+
* shows it. In the transaction that moved the rows, so a refused move closes nothing.
|
|
78
|
+
*/
|
|
79
|
+
async function closeApprovalNotices(tx, rows) {
|
|
80
|
+
for (const row of rows) {
|
|
81
|
+
if (!row.domainId)
|
|
82
|
+
continue;
|
|
83
|
+
await (0, notification_1.closeNotices)(tx, { id: row.domainId }, 'approval', (0, exports.approvalNoticeKey)(row.id));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
67
86
|
/** Only a person who can sign in is told. */
|
|
68
87
|
function active(person) {
|
|
69
88
|
return person && person.status === auth_base_1.UserStatus.ACTIVATED ? { id: person.id, name: person.name, email: person.email, locale: person.locale } : null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval-notice.js","sourceRoot":"","sources":["../../../server/service/approval-notice/approval-notice.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"approval-notice.js","sourceRoot":"","sources":["../../../server/service/approval-notice/approval-notice.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The approval notice (ADR-0164) - the one place the worklist tells people of an approval's turn and judgment.\n *\n * The four places an approval moves call `noticeApproval`: createApproval (a turn or a reference), delegate (a\n * handed seat), approve with no one after (approved) and reject (rejected). Applications call nothing; a case that\n * goes through the approval line is told of. Sending is notification's (`sendNoticeWhenCommitted`); what it sent is kept\n * on the approval row (`notices`).\n */\nimport { User, UserStatus } from '@things-factory/auth-base'\nimport { logger } from '@things-factory/env'\nimport { translatorFor } from '@things-factory/i18n-base/translator'\nimport { closeNotices, keepNoticeDelivery, noticeDeliveryOf, noticeLinkOf, sendNoticeWhenCommitted } from '@things-factory/notification'\nimport type { EntityManager } from 'typeorm'\n\nimport { ActivityApproval } from '../activity-approval/activity-approval.js'\nimport { poolMembers } from '../activity-instance/assignee-pool.js'\nimport {\n approvalStep,\n isTurnNotice,\n noticeAddress,\n noticeReceivers,\n noticeWords,\n type ApprovalNoticeKind,\n type NoticeFacts,\n type NoticePerson,\n type Translate\n} from './approval-notice-rules.js'\n\n/**\n * Tells of what just happened to approval `approvalId`, once the transaction has committed.\n *\n * Who and what are settled here, inside the transaction, from rows it can see. Nothing here throws: a notice that\n * cannot be made is reported and the approval stands.\n */\nexport async function noticeApproval(context: ResolverContext, { kind, approvalId }: { kind: ApprovalNoticeKind; approvalId: string }): Promise<void> {\n try {\n const { user, tx } = context.state\n\n const approval = await tx.getRepository(ActivityApproval).findOne({\n where: { id: approvalId },\n relations: ['approver', 'approverRole', 'approverRole.users', 'activityThread', 'activityThread.assignee', 'activityThread.activityInstance']\n })\n const thread = approval?.activityThread\n const instance = thread?.activityInstance\n if (!approval || !thread || !instance) return\n\n const receivers = noticeReceivers({\n kind,\n approver: active(approval.approver),\n roleHolders: poolMembers(approval.approverRole ? [approval.approverRole] : []).map(active).filter(Boolean),\n requester: active(thread.assignee),\n actorId: user?.id\n })\n if (!receivers.length) return\n\n const facts: NoticeFacts = {\n kind,\n name: instance.name || '',\n requester: thread.assignee?.name,\n actor: user?.name,\n ...(isTurnNotice(kind) ? approvalStep(instance.approvalLine, approval.order) : {})\n }\n const address = noticeAddress(kind, { approvalId: approval.id, threadId: thread.id })\n\n sendNoticeWhenCommitted(context, {\n type: 'approval',\n level: kind === 'rejected' ? 'warn' : 'info',\n receivers,\n words: lng => noticeWords(translatorOf(lng), facts),\n address,\n link: noticeLinkOf(context, address),\n /* a turn is closed once its row is judged (`closeApprovalNotices`); a judgment told is read by its person */\n key: isTurnNotice(kind) ? approvalNoticeKey(approval.id) : `approval-thread:${thread.id}`,\n label: `approval notice ${kind} of ${approval.id}`\n }, result => keepNoticeDelivery(ActivityApproval, approval.id, 'notices', noticeDeliveryOf(kind, result, receivers.length)))\n } catch (error) {\n logger.error(`[worklist] approval notice ${kind} of ${approvalId} could not be made`, error)\n }\n}\n\n/** What a turn notice tells of - the approval row whose turn it is. */\nexport const approvalNoticeKey = (approvalId: string) => `approval:${approvalId}`\n\n/**\n * Closes the turn notices of approval rows that are no longer waiting - judged, handed on, withdrawn or closed with\n * their case (ADR-0164 amendment 1): everyone the turn was told to, a role's holders too, reads it as read and no screen\n * shows it. In the transaction that moved the rows, so a refused move closes nothing.\n */\nexport async function closeApprovalNotices(tx: EntityManager, rows: readonly { id: string; domainId?: string }[]): Promise<void> {\n for (const row of rows) {\n if (!row.domainId) continue\n await closeNotices(tx, { id: row.domainId }, 'approval', approvalNoticeKey(row.id))\n }\n}\n\n/** Only a person who can sign in is told. */\nfunction active(person?: User | null): NoticePerson | null {\n return person && person.status === UserStatus.ACTIVATED ? { id: person.id, name: person.name, email: person.email, locale: person.locale } : null\n}\n\n/** A sentence missing in the person's language is said in English, never as its key. */\nfunction translatorOf(lng: string): Translate {\n const own = translatorFor(lng)\n const english = translatorFor('en')\n return (key, options = {}) => own(key, { ...options, defaultValue: english(key, options) })\n}\n"]}
|
|
@@ -17,8 +17,8 @@ export * from './work-door/work-door-journal.js';
|
|
|
17
17
|
export * from './work-door/work-door-journal-service.js';
|
|
18
18
|
export * from './work-door/work-door-service.js';
|
|
19
19
|
export { waitingOn } from './approval-progress/waiting-on.js';
|
|
20
|
-
export declare const entities: (typeof import("./activity/activity.js").
|
|
21
|
-
export declare const subscribers: (typeof import("./activity-approval/event-subscriber.js").ActivityApprovalSubscriber | typeof import("./activity
|
|
20
|
+
export declare const entities: (typeof import("./activity-approval/activity-approval.js").ActivityApproval | typeof import("./activity-thread/activity-thread.js").ActivityThread | typeof import("./activity-instance/activity-instance.js").ActivityInstance | typeof import("./activity/activity.js").Activity | typeof import("./installable-activity/installable-activity.js").InstallableActivity | typeof import("./activity-template/activity-template.js").ActivityTemplate | typeof import("./activity/activity-history.js").ActivityHistory | typeof import("./activity-instance/activity-instance-history.js").ActivityInstanceHistory | typeof import("./activity-template/activity-template-history.js").ActivityTemplateHistory | typeof import("./activity-thread/activity-thread-history.js").ActivityThreadHistory | typeof import("./activity-summary/activity-summary.js").ActivitySummary | typeof import("./work-door/work-door-not-used.js").WorkDoorNotUsed | typeof import("./work-door/work-door-journal.js").WorkDoorJournal)[];
|
|
21
|
+
export declare const subscribers: (typeof import("./activity-approval/event-subscriber.js").ActivityApprovalSubscriber | typeof import("./activity/event-subscriber.js").ActivityHistoryEntitySubscriber | typeof import("./activity/declaration-guard-subscriber.js").ActivityDeclarationGuardSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceHistoryEntitySubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadSubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadHistoryEntitySubscriber)[];
|
|
22
22
|
export declare const schema: {
|
|
23
|
-
resolverClasses: (typeof import("./activity-
|
|
23
|
+
resolverClasses: (typeof import("./activity-stats/activity-stats-query.js").ActivityStatsQuery | typeof import("./activity-approval/activity-approval-query.js").ActivityApprovalQuery | typeof import("./activity-approval/activity-approval-mutation.js").ActivityApprovalMutation | typeof import("./activity-approval/activity-approval-subscription.js").ActivityApprovalSubscription | typeof import("./activity/activity-mutation.js").ActivityMutation | typeof import("./activity/activity-query.js").ActivityQuery | typeof import("./activity-instance/activity-instance-mutation.js").ActivityInstanceMutation | typeof import("./activity-instance/activity-instance-query.js").ActivityInstanceQuery | typeof import("./activity-instance/activity-instance-subscription.js").ActivityInstanceSubscription | typeof import("./activity-template/activity-template-mutation.js").ActivityTemplateMutation | typeof import("./activity-template/activity-template-query.js").ActivityTemplateQuery | typeof import("./activity-thread/activity-thread-mutation.js").ActivityThreadMutation | typeof import("./activity-thread/activity-thread-query.js").ActivityThreadQuery | typeof import("./activity-thread/activity-thread-history-query.js").ActivityThreadHistoryQuery | typeof import("./activity-thread/activity-thread-subscription.js").ActivityThreadSubscription | typeof import("./installable-activity/installable-activity-query.js").InstallableActivityQuery | typeof import("./installable-activity/installable-activity-mutation.js").InstallableActivityMutation | typeof import("./activity-summary/activity-summary-query.js").ActivitySummaryQuery | typeof import("./activity-summary/person-open-work.js").PersonOpenWorkQuery | typeof import("./work-door/work-door-resolver.js").WorkDoorResolver | typeof import("./approval-progress/approval-progress-query.js").ApprovalProgressQuery)[];
|
|
24
24
|
};
|