@things-factory/worklist 10.1.208 → 10.1.210

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.
Files changed (83) hide show
  1. package/dist-client/components/timeline-entries.js +2 -1
  2. package/dist-client/components/timeline-entries.js.map +1 -1
  3. package/dist-client/pages/activity-instance/activity-instance-view.d.ts +1 -1
  4. package/dist-client/pages/activity-thread/activity-thread-page.d.ts +1 -1
  5. package/dist-client/pages/activity-thread/activity-thread-page.js +36 -12
  6. package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
  7. package/dist-client/pages/activity-thread/activity-thread-view-page.js +1 -1
  8. package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
  9. package/dist-client/pages/todo/done-list-calendar-page.d.ts +16 -3
  10. package/dist-client/pages/todo/done-list-calendar-page.js +107 -19
  11. package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -1
  12. package/dist-client/pages/todo/draft-list-page.d.ts +1 -2
  13. package/dist-client/pages/todo/draft-list-page.js +11 -14
  14. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  15. package/dist-client/route.d.ts +1 -1
  16. package/dist-client/tsconfig.tsbuildinfo +1 -1
  17. package/dist-client/work-calendar-sources.d.ts +24 -6
  18. package/dist-client/work-calendar-sources.js +18 -6
  19. package/dist-client/work-calendar-sources.js.map +1 -1
  20. package/dist-server/controllers/activity-approval/check-authority.d.ts +2 -13
  21. package/dist-server/controllers/activity-approval/check-authority.js +2 -49
  22. package/dist-server/controllers/activity-approval/check-authority.js.map +1 -1
  23. package/dist-server/controllers/activity-approval/delegate.js +1 -8
  24. package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
  25. package/dist-server/controllers/activity-approval/delegation.d.ts +5 -15
  26. package/dist-server/controllers/activity-approval/delegation.js +2 -16
  27. package/dist-server/controllers/activity-approval/delegation.js.map +1 -1
  28. package/dist-server/controllers/activity-approval/resolve-judgeable-seats.d.ts +2 -2
  29. package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js +1 -1
  30. package/dist-server/controllers/activity-approval/resolve-judgeable-seats.js.map +1 -1
  31. package/dist-server/controllers/activity-approval/seat-standing.d.ts +66 -0
  32. package/dist-server/controllers/activity-approval/seat-standing.js +57 -0
  33. package/dist-server/controllers/activity-approval/seat-standing.js.map +1 -0
  34. package/dist-server/controllers/activity-instance/issue.js +9 -15
  35. package/dist-server/controllers/activity-instance/issue.js.map +1 -1
  36. package/dist-server/controllers/activity-thread/abort.js +7 -0
  37. package/dist-server/controllers/activity-thread/abort.js.map +1 -1
  38. package/dist-server/controllers/activity-thread/restart.js +4 -2
  39. package/dist-server/controllers/activity-thread/restart.js.map +1 -1
  40. package/dist-server/controllers/activity-thread/submit.js +5 -1
  41. package/dist-server/controllers/activity-thread/submit.js.map +1 -1
  42. package/dist-server/controllers/common.js +1 -1
  43. package/dist-server/controllers/common.js.map +1 -1
  44. package/dist-server/service/activity/index.d.ts +2 -2
  45. package/dist-server/service/activity-approval/index.d.ts +1 -1
  46. package/dist-server/service/activity-approval/my-pending-approvals.d.ts +5 -5
  47. package/dist-server/service/activity-approval/my-pending-approvals.js +5 -8
  48. package/dist-server/service/activity-approval/my-pending-approvals.js.map +1 -1
  49. package/dist-server/service/activity-instance/activity-instance-query.d.ts +1 -1
  50. package/dist-server/service/activity-instance/activity-instance-query.js +9 -4
  51. package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
  52. package/dist-server/service/activity-instance/index.d.ts +1 -1
  53. package/dist-server/service/activity-instance/request-box.d.ts +2 -0
  54. package/dist-server/service/activity-instance/request-box.js +18 -0
  55. package/dist-server/service/activity-instance/request-box.js.map +1 -0
  56. package/dist-server/service/activity-summary/activity-summary-query.js +3 -3
  57. package/dist-server/service/activity-summary/activity-summary-query.js.map +1 -1
  58. package/dist-server/service/activity-summary/index.d.ts +1 -1
  59. package/dist-server/service/activity-template/index.d.ts +2 -2
  60. package/dist-server/service/activity-thread/index.d.ts +1 -1
  61. package/dist-server/service/activity-thread/my-open-threads.d.ts +1 -2
  62. package/dist-server/service/activity-thread/my-open-threads.js +2 -3
  63. package/dist-server/service/activity-thread/my-open-threads.js.map +1 -1
  64. package/dist-server/service/index.d.ts +3 -3
  65. package/dist-server/service/subscription/subscription-filters.d.ts +2 -2
  66. package/dist-server/service/subscription/subscription-filters.js +2 -2
  67. package/dist-server/service/subscription/subscription-filters.js.map +1 -1
  68. package/dist-server/service/work-door/index.d.ts +1 -1
  69. package/dist-server/tsconfig.tsbuildinfo +1 -1
  70. package/package.json +2 -2
  71. package/shared/task-followup.d.ts +9 -0
  72. package/shared/task-followup.js +25 -0
  73. package/tests/delegate-approval.test.ts +7 -4
  74. package/tests/open-doors.test.ts +1 -1
  75. package/translations/en.json +7 -3
  76. package/translations/es.json +7 -3
  77. package/translations/ja.json +7 -3
  78. package/translations/ko.json +7 -3
  79. package/translations/ms.json +7 -3
  80. package/translations/zh.json +7 -3
  81. package/dist-server/controllers/activity-approval/own-request.d.ts +0 -162
  82. package/dist-server/controllers/activity-approval/own-request.js +0 -135
  83. package/dist-server/controllers/activity-approval/own-request.js.map +0 -1
@@ -12,7 +12,7 @@ const assignee_pool_js_1 = require("../../service/activity-instance/assignee-poo
12
12
  const entitlement_js_1 = require("./entitlement.js");
13
13
  const claim_draft_js_1 = require("./claim-draft.js");
14
14
  const approval_expectation_js_1 = require("./approval-expectation.js");
15
- const own_request_js_1 = require("../activity-approval/own-request.js");
15
+ const seat_standing_js_1 = require("../activity-approval/seat-standing.js");
16
16
  const resolve_judgeable_seats_js_1 = require("../activity-approval/resolve-judgeable-seats.js");
17
17
  async function issue(activityInstance, context) {
18
18
  const { domain, user, tx } = context.state;
@@ -157,22 +157,17 @@ async function issue(activityInstance, context) {
157
157
  }));
158
158
  }
159
159
  /*
160
- * **올린 사람 말고 설 사람이 있어야 올릴 수 있다.**
160
+ * **결재 자리마다 설 사람이 있어야 올릴 수 있다.** 아무도 못 서는 자리가 있으면 그 건은 거기서 영영
161
+ * 선다. 올리는 이 자리에서 막아야 결재선을 고칠 수 있는 사람이 무엇을 고쳐야 하는지 읽는다.
162
+ * 상신자도 결재 자리에 설 수 있다(2026-10-23, ADR-0052 ② 를 거둠).
161
163
  *
162
- * 결재는 누르는 자리에서도 막지만(§`own-request.ts`), 거기서만 막으면 결재선에 올린 사람밖에 없는
163
- * 건이 **아무에게도 안 간다.** 정비 완료 확인이 그 모양이면 설비가 정비중으로 남고 라인이 선다.
164
- *
165
- * 그래서 올리는 이 자리에서 먼저 본다. 여기서 걸리면 결재선을 고칠 수 있는 사람이 그 자리에서
166
- * 무엇을 고쳐야 하는지 읽는다. (ADR-0052 ②)
167
- *
168
- * 판단은 `own-request.ts` 가 들고, 자리를 푸는 것은 `resolve-judgeable-seats.ts` 가 한다 — 여기에
164
+ * 판단은 `seat-standing.ts` 가 들고, 자리를 푸는 것은 `resolve-judgeable-seats.ts` 가 한다 — 여기에
169
165
  * 조건을 적으면 위의 결재선 검사와 같은 이유로 시험할 수 없다.
170
166
  */
171
- const standing = (0, own_request_js_1.judgeSomeoneElseCanJudge)({
172
- issuerId: user?.id,
167
+ const standing = (0, seat_standing_js_1.judgeSeatsStand)({
173
168
  seats: await (0, resolve_judgeable_seats_js_1.resolveJudgeableSeats)(activityInstance.approvalLine ?? origin?.approvalLine, context)
174
169
  });
175
- if ((0, own_request_js_1.standingBroken)(standing)) {
170
+ if ((0, seat_standing_js_1.standingBroken)(standing)) {
176
171
  /*
177
172
  * 사유마다 한 문장씩 — **자리가 같다고 사유를 합치지 않는다.** 관리자가 할 일이 다르다: 하나는
178
173
  * 「그 자리에 다른 결재자를」이고 하나는 「그 역할에 사람을」이다. (ADR-0047 ② 의 낱말)
@@ -185,10 +180,9 @@ async function issue(activityInstance, context) {
185
180
  .join(', ');
186
181
  const said = {
187
182
  'approval-role-empty': `${seats} 결재 자리가 지목한 역할에 사람이 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 역할에 사람을 넣어 주십시오.`,
188
- 'approval-person-missing': `${seats} 결재 자리가 지목한 사람을 찾을 수 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 자리에 지금 있는 사람을 다시 지정해 주십시오.`,
189
- 'only-the-issuer-could-judge': `${seats} 결재 자리에 올린 사람 말고 설 사람이 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 자리에 다른 결재자를 넣거나, 그 역할을 가진 사람을 늘려 주십시오.`
183
+ 'approval-person-missing': `${seats} 결재 자리가 지목한 사람을 찾을 수 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 자리에 지금 있는 사람을 다시 지정해 주십시오.`
190
184
  }[refusal.because];
191
- return context.t(own_request_js_1.STANDING_REFUSAL_KEYS[refusal.because], { seats, defaultValue: said });
185
+ return context.t(seat_standing_js_1.STANDING_REFUSAL_KEYS[refusal.because], { seats, defaultValue: said });
192
186
  })
193
187
  .join(' '));
194
188
  }
@@ -1 +1 @@
1
- {"version":3,"file":"issue.js","sourceRoot":"","sources":["../../../server/controllers/activity-instance/issue.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Activity } from '../../service/activity/activity.js'\nimport { ActivityInstance, ActivityInstanceStatus } from '../../service/activity-instance/activity-instance.js'\nimport { ActivityInstanceIssue } from '../../service/activity-instance/activity-instance-type.js'\nimport {\n createActivityThreadWithUnassigned,\n createActivityThreadsForAllRoleUsers,\n createActivityThreadsForUsers,\n getSystemUserFromOrgMemberItem,\n createActivityThreadForUser,\n fillActivitySearchKeys\n} from '../common.js'\nimport { submit } from '../activity-thread/submit.js'\nimport { LINE_IS_SET, approvalLineInputRefusal } from './approval-line-input.js'\nimport { ROLE_IS_NOT_AN_ASSIGNEE, roleAssigneeRefusal } from './assignee-input.js'\nimport { poolIdsOf, resolvePoolRoles } from '../../service/activity-instance/assignee-pool.js'\nimport { assertMayWorkOnDraft } from './entitlement.js'\nimport { claimDraft } from './claim-draft.js'\nimport { expectationBroken, judgeApprovalExpectation } from './approval-expectation.js'\nimport { STANDING_REFUSAL_KEYS, judgeSomeoneElseCanJudge, standingBroken } from '../activity-approval/own-request.js'\nimport { resolveJudgeableSeats } from '../activity-approval/resolve-judgeable-seats.js'\n\nexport async function issue(\n activityInstance: ActivityInstanceIssue,\n context: ResolverContext\n): Promise<ActivityInstance> {\n const { domain, user, tx } = context.state\n const issuedAt = new Date()\n var {\n id,\n name,\n description,\n assignees,\n uiType,\n uiSource,\n viewType,\n viewSource,\n dueAt,\n priority,\n approvalLine,\n activityId,\n activityType,\n assigneeRoles,\n supervisoryRole,\n input\n } = activityInstance\n\n var origin = id\n ? await tx.getRepository(ActivityInstance).findOne({\n where: { domain: { id: domain.id }, id },\n relations: [\n 'domain',\n 'activity',\n 'assigneeRoles',\n 'supervisoryRole',\n 'updater',\n 'creator',\n 'starter',\n 'terminator'\n ]\n })\n : null\n\n /*\n 남의 초안은 못 내보낸다.\n\n 내보내는 순간 결재선과 담당자가 서고, 그것은 **다른 사람들의 의무**가 된다. 새로 시작하는\n 것(id 없음)은 주인이 없으므로 이 검사에 안 걸린다. 자격 규칙은 `entitlement.ts` 에 있다.\n */\n if (origin) {\n await assertMayWorkOnDraft(origin, context)\n }\n\n /* \n Prerequisites for a Task to Be Issued.\n - The previous state of the task should be Draft.\n */\n if (origin && origin.state !== ActivityInstanceStatus.Draft) {\n throw new Error(\n context.t(`error.activity-instance is already issued`, {\n id: id,\n state: origin.state\n })\n )\n }\n\n /*\n * An id that is not here is refused - not taken as a new case. Taken as new, a draft discarded a moment\n * ago came back under the same id, issued. And a draft that is here is claimed before anything else is\n * written, so a discard cannot slip in between - see claim-draft.ts.\n */\n if (id && !origin) {\n throw new Error(context.t('error.activity-instance not found', { activityInstance: id }))\n }\n\n if (origin) {\n await claimDraft(origin.id, context)\n }\n\n var repository = tx.getRepository(Activity)\n var activity =\n origin?.activity ||\n (await repository.findOne({\n where: { domain: domain.parentId ? { id: In([domain.id, domain.parentId]) } : { id: domain.id }, id: activityId },\n relations: ['assigneeRoles', 'supervisoryRole']\n }))\n\n if (!activity) {\n throw new Error(\n context.t('error.activity not found', {\n activity: activityId\n })\n )\n }\n\n /*\n * The activity's approval line is set on its detail screen and nowhere else (ruling 2026-09-24).\n * A line handed in must be absent or the same one - § approval-line-input.ts.\n */\n if (approvalLineInputRefusal(activity.approvalLine, approvalLine)) {\n throw Object.assign(new Error(context.t('error.activity-instance approval line is set')), { code: LINE_IS_SET })\n }\n\n if (!origin) {\n activityInstance.name = name || activity.name\n activityInstance.description = description || activity.description\n activityInstance.activityType = activityType || activity.activityType\n activityInstance.uiType = uiType || activity.uiType\n activityInstance.uiSource = uiSource || activity.uiSource\n activityInstance.viewType = viewType || activity.viewType\n activityInstance.viewSource = viewSource || activity.viewSource\n activityInstance.supervisoryRole = supervisoryRole || activity.supervisoryRole\n activityInstance.priority = priority ?? activity.priority\n\n activityInstance.adhocType = 'standard'\n activityInstance.refBy = activityId\n\n /*\n * 낸 쪽이 직접 주지 않았으면 액티비티의 선언을 따른다.\n *\n * 위의 `if (!assignees || !approvalLine)` 안에 두지 않는다 — 둘 다 준 건에서는 그 블록에 안 들어가고,\n * 그러면 이 축만 조용히 빠진다.\n */\n if (activityInstance.rejectionIsFinal === undefined || activityInstance.rejectionIsFinal === null) {\n activityInstance.rejectionIsFinal = activity.rejectionIsFinal ?? false\n }\n\n if (!assignees || !approvalLine) {\n if (!assignees) {\n assignees = activityInstance.assignees = activity.assignees\n }\n\n if (!approvalLine) {\n approvalLine = activityInstance.approvalLine = activity.approvalLine\n }\n\n if (!dueAt && activity.standardTime) {\n activityInstance.dueAt = new Date(issuedAt.getTime() + activity.standardTime * 1000)\n }\n }\n }\n\n /*\n * The pool - handed in, else the activity's for a new case (a draft keeps the one it was written with). Every\n * role is read in the case's domain, each once, or the case is refused by name: a role nobody here holds only\n * looks like a pool. § assignee-pool.ts\n */\n if (assigneeRoles) {\n activityInstance.assigneeRoles = await resolvePoolRoles(assigneeRoles, context)\n } else if (!origin) {\n activityInstance.assigneeRoles = await resolvePoolRoles(activity.assigneeRoles, context)\n }\n\n /*\n * A role is not an assignee - it became the role's first user. Seen after the activity's list is taken\n * over, so a list saved on the activity before this is refused too. § assignee-input.ts\n */\n if (roleAssigneeRefusal(assignees)) {\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 }\n\n /*\n * **결재를 받겠다고 낸 건은 결재선이 있어야 한다.**\n *\n * 액티비티의 결재선을 물려받은 뒤에 본다 — 낸 쪽이 직접 주지 않아도 액티비티가 들고 있으면 그것이\n * 이 건의 결재선이다. 물려받기 전에 보면 멀쩡한 건을 막는다.\n *\n * 초안을 다시 내는 경우 결재선은 원본이 들고 있으므로 그것까지 함께 본다.\n *\n * 판단은 `approval-expectation.ts` 가 든다 — 여기서 조건을 적으면 시험할 수 없다.\n */\n const expectation = judgeApprovalExpectation({\n requireApproval: activityInstance.requireApproval,\n approvalLine: activityInstance.approvalLine ?? origin?.approvalLine,\n activityName: activity.name\n })\n\n if (expectationBroken(expectation)) {\n throw new Error(\n context.t('error.approval line is empty but approval was required', {\n activity: expectation.activityName,\n defaultValue:\n `\"${expectation.activityName}\" 에 결재선이 없습니다. 이 건은 결재를 받기로 하고 낸 것이라 올리지 않습니다 — ` +\n '그대로 두면 결재 없이 확정됩니다.'\n })\n )\n }\n\n /*\n * **올린 사람 말고 설 사람이 있어야 올릴 수 있다.**\n *\n * 결재는 누르는 자리에서도 막지만(§`own-request.ts`), 거기서만 막으면 결재선에 올린 사람밖에 없는\n * 건이 **아무에게도 안 간다.** 정비 완료 확인이 그 모양이면 설비가 정비중으로 남고 라인이 선다.\n *\n * 그래서 올리는 이 자리에서 먼저 본다. 여기서 걸리면 결재선을 고칠 수 있는 사람이 그 자리에서\n * 무엇을 고쳐야 하는지 읽는다. (ADR-0052 ②)\n *\n * 판단은 `own-request.ts` 가 들고, 자리를 푸는 것은 `resolve-judgeable-seats.ts` 가 한다 — 여기에\n * 조건을 적으면 위의 결재선 검사와 같은 이유로 시험할 수 없다.\n */\n const standing = judgeSomeoneElseCanJudge({\n issuerId: user?.id,\n seats: await resolveJudgeableSeats(activityInstance.approvalLine ?? origin?.approvalLine, context)\n })\n\n if (standingBroken(standing)) {\n /*\n * 사유마다 한 문장씩 — **자리가 같다고 사유를 합치지 않는다.** 관리자가 할 일이 다르다: 하나는\n * 「그 자리에 다른 결재자를」이고 하나는 「그 역할에 사람을」이다. (ADR-0047 ② 의 낱말)\n */\n throw new Error(\n standing.refusals\n .map(refusal => {\n /* 이름이 안 풀린 자리는 결재선에 적힌 값이라도 보인다 — 관리자가 고칠 실마리가 그것뿐이다. */\n const seats = refusal.seats\n .map(seat => `${seat.order}차${seat.name ? ` (${seat.name})` : seat.pointsAt ? ` (${seat.pointsAt})` : ''}`)\n .join(', ')\n\n const said = {\n 'approval-role-empty': `${seats} 결재 자리가 지목한 역할에 사람이 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 역할에 사람을 넣어 주십시오.`,\n 'approval-person-missing': `${seats} 결재 자리가 지목한 사람을 찾을 수 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 자리에 지금 있는 사람을 다시 지정해 주십시오.`,\n 'only-the-issuer-could-judge': `${seats} 결재 자리에 올린 사람 말고 설 사람이 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 자리에 다른 결재자를 넣거나, 그 역할을 가진 사람을 늘려 주십시오.`\n }[refusal.because]\n\n return context.t(STANDING_REFUSAL_KEYS[refusal.because], { seats, defaultValue: said })\n })\n .join(' ')\n )\n }\n\n const activitySearchKeys = fillActivitySearchKeys(activity?.searchKeys, input)\n\n if (activity.startingType == 'post') {\n /* \n startingType이 'post'이면, \n activityInstance 이슈와 동시에 issuer에게 할당된 activityThread가 생성되고 submit까지 모두 완료되게 된다.\n 만일, 결재선이 있다면, 상신되게 된다.\n */\n const posted = await tx.getRepository(ActivityInstance).save({\n version: 1,\n creator: user,\n ...origin,\n ...activityInstance,\n transaction: 'post',\n activity,\n ...activitySearchKeys,\n state: ActivityInstanceStatus.Started,\n domain,\n issuer: user,\n updater: user,\n issuedAt,\n startedAt: issuedAt\n })\n\n const thread = await createActivityThreadForUser('post', posted, user, context)\n\n /* post 방식은 thread가 하나이므로, instance의 output을 그대로 thread의 output이라고 판단할 수 있다. 따라서, 아래 로직은 제거한다. */\n // const data = { ...activityInstance.input, ...activityInstance.output }\n // const output = (activity.model || [])\n // .filter(item => item.inout === 'inout' || item.inout === 'out')\n // .reduce((inout, item) => {\n // inout[item.tag] = data[item.tag]\n // return inout\n // }, {})\n\n await submit({ id: thread.id, output: activityInstance.output }, context)\n\n return await tx.getRepository(ActivityInstance).findOneBy({ id: posted.id })\n } else {\n const issued = await tx.getRepository(ActivityInstance).save({\n version: 1,\n creator: user,\n ...origin,\n ...activityInstance,\n transaction: 'issue',\n activity,\n ...activitySearchKeys,\n state: ActivityInstanceStatus.Issued,\n domain,\n issuer: user,\n updater: user,\n issuedAt\n })\n\n /*\n 1. 하나의 thread가 필요한 경우 (대부분)\n 조건 : activityInstance의 threadsMin이 1 이어야 한다.\n 로직 1 : getSystemUserFromOrgMemberItem 의 결과가 한명이라면 그대로 activityThread.assignee로 직접 할당한다.\n 로직 2 : getSystemUserFromOrgMemberItem 의 결과가 한명이 아니라면, assigneeRoles 가 있는 경우에만 처리가 가능하다.\n 이 경우에는 assignee를 비운다. - createActivityThreadWithUnassigned\n 2. 할당되지 않은 복수개의 thread가 필요한 경우\n 조건 : threadsMin이 1 이상이어야 한다.\n 로직 1 : getSystemUserFromOrgMemberItem 의 결과와 threadsMin 값이 같다면, 그대로 activityThread.assignee로 직접 할당한다. createActivityThreadsForAllRoleUsers\n 로직 2 : createActivityThreadWithUnassigned\n 3. 모든 assignee가 처리를 해야하는 경우\n 조건 : threadsMin이 0 이어야 한다.\n 로직 : getSystemUserFromOrgMemberItem 의 결과로 createActivityThreadsForUsers\n */\n\n // assignees가 복수인 것은 아무 의미가 없다.\n const assignedUsers = await Promise.all(\n (assignees || []).map(assignee => getSystemUserFromOrgMemberItem(assignee, context))\n )\n\n if (assignedUsers.length == 0) {\n if (poolIdsOf(issued).length) {\n if (issued.threadsMin === 0) {\n /* 풀의 역할들 중 하나라도 가진 사람 모두에게 — 한 사람에 한 번 */\n await createActivityThreadsForAllRoleUsers('issue', issued, context)\n } else {\n /* minimum threads 설정에 따른 pending assignment 상태로 activityThread를 만드는 경우 */\n await createActivityThreadWithUnassigned('issue', issued, context)\n }\n }\n } else {\n await createActivityThreadsForUsers('issue', issued, assignedUsers, context)\n }\n\n return await tx.getRepository(ActivityInstance).findOneBy({ id: issued.id })\n }\n}\n"]}
1
+ {"version":3,"file":"issue.js","sourceRoot":"","sources":["../../../server/controllers/activity-instance/issue.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Activity } from '../../service/activity/activity.js'\nimport { ActivityInstance, ActivityInstanceStatus } from '../../service/activity-instance/activity-instance.js'\nimport { ActivityInstanceIssue } from '../../service/activity-instance/activity-instance-type.js'\nimport {\n createActivityThreadWithUnassigned,\n createActivityThreadsForAllRoleUsers,\n createActivityThreadsForUsers,\n getSystemUserFromOrgMemberItem,\n createActivityThreadForUser,\n fillActivitySearchKeys\n} from '../common.js'\nimport { submit } from '../activity-thread/submit.js'\nimport { LINE_IS_SET, approvalLineInputRefusal } from './approval-line-input.js'\nimport { ROLE_IS_NOT_AN_ASSIGNEE, roleAssigneeRefusal } from './assignee-input.js'\nimport { poolIdsOf, resolvePoolRoles } from '../../service/activity-instance/assignee-pool.js'\nimport { assertMayWorkOnDraft } from './entitlement.js'\nimport { claimDraft } from './claim-draft.js'\nimport { expectationBroken, judgeApprovalExpectation } from './approval-expectation.js'\nimport { STANDING_REFUSAL_KEYS, judgeSeatsStand, standingBroken } from '../activity-approval/seat-standing.js'\nimport { resolveJudgeableSeats } from '../activity-approval/resolve-judgeable-seats.js'\n\nexport async function issue(\n activityInstance: ActivityInstanceIssue,\n context: ResolverContext\n): Promise<ActivityInstance> {\n const { domain, user, tx } = context.state\n const issuedAt = new Date()\n var {\n id,\n name,\n description,\n assignees,\n uiType,\n uiSource,\n viewType,\n viewSource,\n dueAt,\n priority,\n approvalLine,\n activityId,\n activityType,\n assigneeRoles,\n supervisoryRole,\n input\n } = activityInstance\n\n var origin = id\n ? await tx.getRepository(ActivityInstance).findOne({\n where: { domain: { id: domain.id }, id },\n relations: [\n 'domain',\n 'activity',\n 'assigneeRoles',\n 'supervisoryRole',\n 'updater',\n 'creator',\n 'starter',\n 'terminator'\n ]\n })\n : null\n\n /*\n 남의 초안은 못 내보낸다.\n\n 내보내는 순간 결재선과 담당자가 서고, 그것은 **다른 사람들의 의무**가 된다. 새로 시작하는\n 것(id 없음)은 주인이 없으므로 이 검사에 안 걸린다. 자격 규칙은 `entitlement.ts` 에 있다.\n */\n if (origin) {\n await assertMayWorkOnDraft(origin, context)\n }\n\n /* \n Prerequisites for a Task to Be Issued.\n - The previous state of the task should be Draft.\n */\n if (origin && origin.state !== ActivityInstanceStatus.Draft) {\n throw new Error(\n context.t(`error.activity-instance is already issued`, {\n id: id,\n state: origin.state\n })\n )\n }\n\n /*\n * An id that is not here is refused - not taken as a new case. Taken as new, a draft discarded a moment\n * ago came back under the same id, issued. And a draft that is here is claimed before anything else is\n * written, so a discard cannot slip in between - see claim-draft.ts.\n */\n if (id && !origin) {\n throw new Error(context.t('error.activity-instance not found', { activityInstance: id }))\n }\n\n if (origin) {\n await claimDraft(origin.id, context)\n }\n\n var repository = tx.getRepository(Activity)\n var activity =\n origin?.activity ||\n (await repository.findOne({\n where: { domain: domain.parentId ? { id: In([domain.id, domain.parentId]) } : { id: domain.id }, id: activityId },\n relations: ['assigneeRoles', 'supervisoryRole']\n }))\n\n if (!activity) {\n throw new Error(\n context.t('error.activity not found', {\n activity: activityId\n })\n )\n }\n\n /*\n * The activity's approval line is set on its detail screen and nowhere else (ruling 2026-09-24).\n * A line handed in must be absent or the same one - § approval-line-input.ts.\n */\n if (approvalLineInputRefusal(activity.approvalLine, approvalLine)) {\n throw Object.assign(new Error(context.t('error.activity-instance approval line is set')), { code: LINE_IS_SET })\n }\n\n if (!origin) {\n activityInstance.name = name || activity.name\n activityInstance.description = description || activity.description\n activityInstance.activityType = activityType || activity.activityType\n activityInstance.uiType = uiType || activity.uiType\n activityInstance.uiSource = uiSource || activity.uiSource\n activityInstance.viewType = viewType || activity.viewType\n activityInstance.viewSource = viewSource || activity.viewSource\n activityInstance.supervisoryRole = supervisoryRole || activity.supervisoryRole\n activityInstance.priority = priority ?? activity.priority\n\n activityInstance.adhocType = 'standard'\n activityInstance.refBy = activityId\n\n /*\n * 낸 쪽이 직접 주지 않았으면 액티비티의 선언을 따른다.\n *\n * 위의 `if (!assignees || !approvalLine)` 안에 두지 않는다 — 둘 다 준 건에서는 그 블록에 안 들어가고,\n * 그러면 이 축만 조용히 빠진다.\n */\n if (activityInstance.rejectionIsFinal === undefined || activityInstance.rejectionIsFinal === null) {\n activityInstance.rejectionIsFinal = activity.rejectionIsFinal ?? false\n }\n\n if (!assignees || !approvalLine) {\n if (!assignees) {\n assignees = activityInstance.assignees = activity.assignees\n }\n\n if (!approvalLine) {\n approvalLine = activityInstance.approvalLine = activity.approvalLine\n }\n\n if (!dueAt && activity.standardTime) {\n activityInstance.dueAt = new Date(issuedAt.getTime() + activity.standardTime * 1000)\n }\n }\n }\n\n /*\n * The pool - handed in, else the activity's for a new case (a draft keeps the one it was written with). Every\n * role is read in the case's domain, each once, or the case is refused by name: a role nobody here holds only\n * looks like a pool. § assignee-pool.ts\n */\n if (assigneeRoles) {\n activityInstance.assigneeRoles = await resolvePoolRoles(assigneeRoles, context)\n } else if (!origin) {\n activityInstance.assigneeRoles = await resolvePoolRoles(activity.assigneeRoles, context)\n }\n\n /*\n * A role is not an assignee - it became the role's first user. Seen after the activity's list is taken\n * over, so a list saved on the activity before this is refused too. § assignee-input.ts\n */\n if (roleAssigneeRefusal(assignees)) {\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 }\n\n /*\n * **결재를 받겠다고 낸 건은 결재선이 있어야 한다.**\n *\n * 액티비티의 결재선을 물려받은 뒤에 본다 — 낸 쪽이 직접 주지 않아도 액티비티가 들고 있으면 그것이\n * 이 건의 결재선이다. 물려받기 전에 보면 멀쩡한 건을 막는다.\n *\n * 초안을 다시 내는 경우 결재선은 원본이 들고 있으므로 그것까지 함께 본다.\n *\n * 판단은 `approval-expectation.ts` 가 든다 — 여기서 조건을 적으면 시험할 수 없다.\n */\n const expectation = judgeApprovalExpectation({\n requireApproval: activityInstance.requireApproval,\n approvalLine: activityInstance.approvalLine ?? origin?.approvalLine,\n activityName: activity.name\n })\n\n if (expectationBroken(expectation)) {\n throw new Error(\n context.t('error.approval line is empty but approval was required', {\n activity: expectation.activityName,\n defaultValue:\n `\"${expectation.activityName}\" 에 결재선이 없습니다. 이 건은 결재를 받기로 하고 낸 것이라 올리지 않습니다 — ` +\n '그대로 두면 결재 없이 확정됩니다.'\n })\n )\n }\n\n /*\n * **결재 자리마다 설 사람이 있어야 올릴 수 있다.** 아무도 못 서는 자리가 있으면 그 건은 거기서 영영\n * 선다. 올리는 이 자리에서 막아야 결재선을 고칠 수 있는 사람이 무엇을 고쳐야 하는지 읽는다.\n * 상신자도 결재 자리에 설 수 있다(2026-10-23, ADR-0052 ② 를 거둠).\n *\n * 판단은 `seat-standing.ts` 가 들고, 자리를 푸는 것은 `resolve-judgeable-seats.ts` 가 한다 — 여기에\n * 조건을 적으면 위의 결재선 검사와 같은 이유로 시험할 수 없다.\n */\n const standing = judgeSeatsStand({\n seats: await resolveJudgeableSeats(activityInstance.approvalLine ?? origin?.approvalLine, context)\n })\n\n if (standingBroken(standing)) {\n /*\n * 사유마다 한 문장씩 — **자리가 같다고 사유를 합치지 않는다.** 관리자가 할 일이 다르다: 하나는\n * 「그 자리에 다른 결재자를」이고 하나는 「그 역할에 사람을」이다. (ADR-0047 ② 의 낱말)\n */\n throw new Error(\n standing.refusals\n .map(refusal => {\n /* 이름이 안 풀린 자리는 결재선에 적힌 값이라도 보인다 — 관리자가 고칠 실마리가 그것뿐이다. */\n const seats = refusal.seats\n .map(seat => `${seat.order}차${seat.name ? ` (${seat.name})` : seat.pointsAt ? ` (${seat.pointsAt})` : ''}`)\n .join(', ')\n\n const said = {\n 'approval-role-empty': `${seats} 결재 자리가 지목한 역할에 사람이 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 역할에 사람을 넣어 주십시오.`,\n 'approval-person-missing': `${seats} 결재 자리가 지목한 사람을 찾을 수 없습니다. 그대로 올리면 아무도 결재할 수 없습니다 — 그 자리에 지금 있는 사람을 다시 지정해 주십시오.`\n }[refusal.because]\n\n return context.t(STANDING_REFUSAL_KEYS[refusal.because], { seats, defaultValue: said })\n })\n .join(' ')\n )\n }\n\n const activitySearchKeys = fillActivitySearchKeys(activity?.searchKeys, input)\n\n if (activity.startingType == 'post') {\n /* \n startingType이 'post'이면, \n activityInstance 이슈와 동시에 issuer에게 할당된 activityThread가 생성되고 submit까지 모두 완료되게 된다.\n 만일, 결재선이 있다면, 상신되게 된다.\n */\n const posted = await tx.getRepository(ActivityInstance).save({\n version: 1,\n creator: user,\n ...origin,\n ...activityInstance,\n transaction: 'post',\n activity,\n ...activitySearchKeys,\n state: ActivityInstanceStatus.Started,\n domain,\n issuer: user,\n updater: user,\n issuedAt,\n startedAt: issuedAt\n })\n\n const thread = await createActivityThreadForUser('post', posted, user, context)\n\n /* post 방식은 thread가 하나이므로, instance의 output을 그대로 thread의 output이라고 판단할 수 있다. 따라서, 아래 로직은 제거한다. */\n // const data = { ...activityInstance.input, ...activityInstance.output }\n // const output = (activity.model || [])\n // .filter(item => item.inout === 'inout' || item.inout === 'out')\n // .reduce((inout, item) => {\n // inout[item.tag] = data[item.tag]\n // return inout\n // }, {})\n\n await submit({ id: thread.id, output: activityInstance.output }, context)\n\n return await tx.getRepository(ActivityInstance).findOneBy({ id: posted.id })\n } else {\n const issued = await tx.getRepository(ActivityInstance).save({\n version: 1,\n creator: user,\n ...origin,\n ...activityInstance,\n transaction: 'issue',\n activity,\n ...activitySearchKeys,\n state: ActivityInstanceStatus.Issued,\n domain,\n issuer: user,\n updater: user,\n issuedAt\n })\n\n /*\n 1. 하나의 thread가 필요한 경우 (대부분)\n 조건 : activityInstance의 threadsMin이 1 이어야 한다.\n 로직 1 : getSystemUserFromOrgMemberItem 의 결과가 한명이라면 그대로 activityThread.assignee로 직접 할당한다.\n 로직 2 : getSystemUserFromOrgMemberItem 의 결과가 한명이 아니라면, assigneeRoles 가 있는 경우에만 처리가 가능하다.\n 이 경우에는 assignee를 비운다. - createActivityThreadWithUnassigned\n 2. 할당되지 않은 복수개의 thread가 필요한 경우\n 조건 : threadsMin이 1 이상이어야 한다.\n 로직 1 : getSystemUserFromOrgMemberItem 의 결과와 threadsMin 값이 같다면, 그대로 activityThread.assignee로 직접 할당한다. createActivityThreadsForAllRoleUsers\n 로직 2 : createActivityThreadWithUnassigned\n 3. 모든 assignee가 처리를 해야하는 경우\n 조건 : threadsMin이 0 이어야 한다.\n 로직 : getSystemUserFromOrgMemberItem 의 결과로 createActivityThreadsForUsers\n */\n\n // assignees가 복수인 것은 아무 의미가 없다.\n const assignedUsers = await Promise.all(\n (assignees || []).map(assignee => getSystemUserFromOrgMemberItem(assignee, context))\n )\n\n if (assignedUsers.length == 0) {\n if (poolIdsOf(issued).length) {\n if (issued.threadsMin === 0) {\n /* 풀의 역할들 중 하나라도 가진 사람 모두에게 — 한 사람에 한 번 */\n await createActivityThreadsForAllRoleUsers('issue', issued, context)\n } else {\n /* minimum threads 설정에 따른 pending assignment 상태로 activityThread를 만드는 경우 */\n await createActivityThreadWithUnassigned('issue', issued, context)\n }\n }\n } else {\n await createActivityThreadsForUsers('issue', issued, assignedUsers, context)\n }\n\n return await tx.getRepository(ActivityInstance).findOneBy({ id: issued.id })\n }\n}\n"]}
@@ -17,7 +17,14 @@ async function abort({ id, reason }, context) {
17
17
  activityThread: id
18
18
  }));
19
19
  }
20
+ // Stopping is for the holder, never a way to claim and destroy an unassigned pool item.
21
+ if (!activityThread.assigneeId || activityThread.assigneeId !== user.id) {
22
+ throw new Error(context.t('error.not authorized to handle this task'));
23
+ }
20
24
  await (0, check_authority_js_1.checkAuthority)(activityThread, context);
25
+ if (['ended', 'aborted'].includes(activityThread.activityInstance?.state)) {
26
+ throw new Error(context.t('error.activity-instance is already terminated', { id: activityThread.activityInstanceId }));
27
+ }
21
28
  /*
22
29
  Prerequisites for a activity thread to Be Aborted.
23
30
  - The previous state of the activity thread must not be End or Aborted.
@@ -1 +1 @@
1
- {"version":3,"file":"abort.js","sourceRoot":"","sources":["../../../server/controllers/activity-thread/abort.ts"],"names":[],"mappings":";;AAKA,sBA6CC;AAlDD,yFAAuG;AACvG,4CAA0D;AAC1D,2CAAoC;AACpC,6DAAqD;AAE9C,KAAK,UAAU,KAAK,CACzB,EAAE,EAAE,EAAE,MAAM,EAAkC,EAC9C,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,IAAI,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAA;IAEjD,IAAI,cAAc,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;QAC5C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACxC,SAAS,EAAE,CAAC,QAAQ,EAAE,kBAAkB,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC;KAC5E,CAAC,CAAA;IAEF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,iCAAiC,EAAE;YAC3C,cAAc,EAAE,EAAE;SACnB,CAAC,CACH,CAAA;IACH,CAAC;IAED,MAAM,IAAA,mCAAc,EAAC,cAAc,EAAE,OAAO,CAAC,CAAA;IAE7C;;;MAGE;IACF,IAAI,cAAc,CAAC,KAAK,IAAI,yCAAoB,CAAC,OAAO,IAAI,cAAc,CAAC,KAAK,IAAI,yCAAoB,CAAC,KAAK,EAAE,CAAC;QAC/G,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,6CAA6C,EAAE;YACvD,EAAE;YACF,KAAK,EAAE,cAAc,CAAC,KAAK;SAC5B,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;QAC9B,cAAc,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;IACvC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAM,EAAC,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,CAAA;IAEhE,MAAM,IAAA,uCAA2B,EAAC,cAAc,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAErG,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread.js'\nimport { updateActivityInstanceState } from '../common.js'\nimport { _abort } from './_abort.js'\nimport { checkAuthority } from './check-authority.js'\n\nexport async function abort(\n { id, reason }: { id: string; reason: string },\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n var repository = tx.getRepository(ActivityThread)\n\n var activityThread = await repository.findOne({\n where: { domain: { id: domain.id }, id },\n relations: ['domain', 'activityInstance', 'assignee', 'creator', 'updater']\n })\n\n if (!activityThread) {\n throw new Error(\n context.t('error.activity-thread not found', {\n activityThread: id\n })\n )\n }\n\n await checkAuthority(activityThread, context)\n\n /* \n Prerequisites for a activity thread to Be Aborted.\n - The previous state of the activity thread must not be End or Aborted.\n */\n if (activityThread.state == ActivityThreadStatus.Aborted || activityThread.state == ActivityThreadStatus.Ended) {\n throw new Error(\n context.t(`error.activity-thread is already terminated`, {\n id,\n state: activityThread.state\n })\n )\n }\n\n if (!activityThread.startedAt) {\n activityThread.startedAt = new Date()\n }\n\n const result = await _abort({ activityThread, reason }, context)\n\n await updateActivityInstanceState(activityThread.activityInstanceId, { causedBy: [result] }, context)\n\n return result\n}\n"]}
1
+ {"version":3,"file":"abort.js","sourceRoot":"","sources":["../../../server/controllers/activity-thread/abort.ts"],"names":[],"mappings":";;AAKA,sBAoDC;AAzDD,yFAAuG;AACvG,4CAA0D;AAC1D,2CAAoC;AACpC,6DAAqD;AAE9C,KAAK,UAAU,KAAK,CACzB,EAAE,EAAE,EAAE,MAAM,EAAkC,EAC9C,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,IAAI,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAA;IAEjD,IAAI,cAAc,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;QAC5C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACxC,SAAS,EAAE,CAAC,QAAQ,EAAE,kBAAkB,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC;KAC5E,CAAC,CAAA;IAEF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,iCAAiC,EAAE;YAC3C,cAAc,EAAE,EAAE;SACnB,CAAC,CACH,CAAA;IACH,CAAC;IAED,wFAAwF;IACxF,IAAI,CAAC,cAAc,CAAC,UAAU,IAAI,cAAc,CAAC,UAAU,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAA;IACxE,CAAC;IACD,MAAM,IAAA,mCAAc,EAAC,cAAc,EAAE,OAAO,CAAC,CAAA;IAC7C,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,+CAA+C,EAAE,EAAE,EAAE,EAAE,cAAc,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAA;IACxH,CAAC;IAED;;;MAGE;IACF,IAAI,cAAc,CAAC,KAAK,IAAI,yCAAoB,CAAC,OAAO,IAAI,cAAc,CAAC,KAAK,IAAI,yCAAoB,CAAC,KAAK,EAAE,CAAC;QAC/G,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,6CAA6C,EAAE;YACvD,EAAE;YACF,KAAK,EAAE,cAAc,CAAC,KAAK;SAC5B,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;QAC9B,cAAc,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;IACvC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAM,EAAC,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,CAAA;IAEhE,MAAM,IAAA,uCAA2B,EAAC,cAAc,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAErG,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread.js'\nimport { updateActivityInstanceState } from '../common.js'\nimport { _abort } from './_abort.js'\nimport { checkAuthority } from './check-authority.js'\n\nexport async function abort(\n { id, reason }: { id: string; reason: string },\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n var repository = tx.getRepository(ActivityThread)\n\n var activityThread = await repository.findOne({\n where: { domain: { id: domain.id }, id },\n relations: ['domain', 'activityInstance', 'assignee', 'creator', 'updater']\n })\n\n if (!activityThread) {\n throw new Error(\n context.t('error.activity-thread not found', {\n activityThread: id\n })\n )\n }\n\n // Stopping is for the holder, never a way to claim and destroy an unassigned pool item.\n if (!activityThread.assigneeId || activityThread.assigneeId !== user.id) {\n throw new Error(context.t('error.not authorized to handle this task'))\n }\n await checkAuthority(activityThread, context)\n if (['ended', 'aborted'].includes(activityThread.activityInstance?.state)) {\n throw new Error(context.t('error.activity-instance is already terminated', { id: activityThread.activityInstanceId }))\n }\n\n /* \n Prerequisites for a activity thread to Be Aborted.\n - The previous state of the activity thread must not be End or Aborted.\n */\n if (activityThread.state == ActivityThreadStatus.Aborted || activityThread.state == ActivityThreadStatus.Ended) {\n throw new Error(\n context.t(`error.activity-thread is already terminated`, {\n id,\n state: activityThread.state\n })\n )\n }\n\n if (!activityThread.startedAt) {\n activityThread.startedAt = new Date()\n }\n\n const result = await _abort({ activityThread, reason }, context)\n\n await updateActivityInstanceState(activityThread.activityInstanceId, { causedBy: [result] }, context)\n\n return result\n}\n"]}
@@ -9,7 +9,7 @@ async function restart(id, output, reason, context) {
9
9
  const repository = tx.getRepository(activity_thread_js_1.ActivityThread);
10
10
  const activityThread = await repository.findOne({
11
11
  where: { domain: { id: domain.id }, id },
12
- relations: ['activityInstance']
12
+ relations: ['activityInstance', 'activityInstance.activity']
13
13
  });
14
14
  if (!activityThread) {
15
15
  throw new Error(context.t('error.activity-thread not found', {
@@ -37,7 +37,9 @@ async function restart(id, output, reason, context) {
37
37
  *
38
38
  * 다시 하려면 새로 낸다.
39
39
  */
40
- if (activityThread.activityInstance?.rejectionIsFinal) {
40
+ if (activityThread.activityInstance?.rejectionIsFinal ||
41
+ activityThread.activityInstance?.activity?.rejectionIsFinal ||
42
+ ['ended', 'aborted'].includes(activityThread.activityInstance?.state)) {
41
43
  throw new Error(context.t('error.activity-thread rejection is final', {
42
44
  id,
43
45
  activityInstance: activityThread.activityInstanceId
@@ -1 +1 @@
1
- {"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../server/controllers/activity-thread/restart.ts"],"names":[],"mappings":";;AAIA,0BAyEC;AA7ED,yFAAuG;AACvG,4CAA0D;AAC1D,6DAAqD;AAE9C,KAAK,UAAU,OAAO,CAC3B,EAAU,EACV,MAAc,EACd,MAAc,EACd,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAA;IACnD,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;QAC9C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACxC,SAAS,EAAE,CAAC,kBAAkB,CAAC;KAChC,CAAC,CAAA;IAEF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,iCAAiC,EAAE;YAC3C,cAAc,EAAE,EAAE;SACnB,CAAC,CACH,CAAA;IACH,CAAC;IAED,MAAM,IAAA,mCAAc,EAAC,cAAc,EAAE,OAAO,CAAC,CAAA;IAE7C;;;MAGE;IACF,IAAI,cAAc,CAAC,KAAK,KAAK,yCAAoB,CAAC,QAAQ,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,2CAA2C,EAAE;YACrD,EAAE;YACF,KAAK,EAAE,yCAAoB,CAAC,QAAQ;YACpC,MAAM,EAAE,cAAc,CAAC,KAAK;SAC7B,CAAC,CACH,CAAA;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,cAAc,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,0CAA0C,EAAE;YACpD,EAAE;YACF,gBAAgB,EAAE,cAAc,CAAC,kBAAkB;SACpD,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,cAAc,CAAC,MAAM,GAAG,MAAM,CAAA;IAChC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAC,IAAI,CAAC;QACzD,GAAG,cAAc;QACjB,MAAM;QACN,KAAK,EAAE,yCAAoB,CAAC,OAAO;QACnC,WAAW,EAAE,SAAS;QACtB,KAAK,EAAE,cAAc,CAAC,KAAK,GAAG,CAAC;QAC/B,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI,IAAI,EAAE;KACtB,CAAC,CAAA;IAEF,MAAM,IAAA,uCAA2B,EAAC,cAAc,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAErG,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread.js'\nimport { updateActivityInstanceState } from '../common.js'\nimport { checkAuthority } from './check-authority.js'\n\nexport async function restart(\n id: string,\n output: object,\n reason: string,\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n const repository = tx.getRepository(ActivityThread)\n const activityThread = await repository.findOne({\n where: { domain: { id: domain.id }, id },\n relations: ['activityInstance']\n })\n\n if (!activityThread) {\n throw new Error(\n context.t('error.activity-thread not found', {\n activityThread: id\n })\n )\n }\n\n await checkAuthority(activityThread, context)\n\n /* \n Prerequisites for a activity thread to Be Delegated.\n - The previous state of the activity thread should be Rejected.\n */\n if (activityThread.state !== ActivityThreadStatus.Rejected) {\n throw new Error(\n context.t(`error.activity-thread should be the state`, {\n id,\n state: ActivityThreadStatus.Rejected,\n actual: activityThread.state\n })\n )\n }\n\n /*\n * **되돌릴 수 없는 판정은 되살리지 않는다.**\n *\n * 반려되는 순간 대상이 닫히는 업무가 있다 — 부적합 처분, 트윈 조치. 그런 건을 되살리면 다음 차수의\n * 결재가 새로 서는데, 대상은 이미 닫혀 있어 **승인해도 아무 일이 일어나지 않는다.** 사람은 승인할\n * 것이 있다고 보고, 오류도 안 난다.\n *\n * 다시 하려면 새로 낸다.\n */\n if (activityThread.activityInstance?.rejectionIsFinal) {\n throw new Error(\n context.t('error.activity-thread rejection is final', {\n id,\n activityInstance: activityThread.activityInstanceId\n })\n )\n }\n\n if (output) {\n activityThread.output = output\n }\n\n const result = await tx.getRepository(ActivityThread).save({\n ...activityThread,\n reason,\n state: ActivityThreadStatus.Started,\n transaction: 'restart',\n round: activityThread.round + 1,\n updater: user,\n startedAt: new Date()\n })\n\n await updateActivityInstanceState(activityThread.activityInstanceId, { causedBy: [result] }, context)\n\n return result\n}\n"]}
1
+ {"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../server/controllers/activity-thread/restart.ts"],"names":[],"mappings":";;AAIA,0BA6EC;AAjFD,yFAAuG;AACvG,4CAA0D;AAC1D,6DAAqD;AAE9C,KAAK,UAAU,OAAO,CAC3B,EAAU,EACV,MAAc,EACd,MAAc,EACd,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAA;IACnD,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;QAC9C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;QACxC,SAAS,EAAE,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;KAC7D,CAAC,CAAA;IAEF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,iCAAiC,EAAE;YAC3C,cAAc,EAAE,EAAE;SACnB,CAAC,CACH,CAAA;IACH,CAAC;IAED,MAAM,IAAA,mCAAc,EAAC,cAAc,EAAE,OAAO,CAAC,CAAA;IAE7C;;;MAGE;IACF,IAAI,cAAc,CAAC,KAAK,KAAK,yCAAoB,CAAC,QAAQ,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,2CAA2C,EAAE;YACrD,EAAE;YACF,KAAK,EAAE,yCAAoB,CAAC,QAAQ;YACpC,MAAM,EAAE,cAAc,CAAC,KAAK;SAC7B,CAAC,CACH,CAAA;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,IACE,cAAc,CAAC,gBAAgB,EAAE,gBAAgB;QACjD,cAAc,CAAC,gBAAgB,EAAE,QAAQ,EAAE,gBAAgB;QAC3D,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,gBAAgB,EAAE,KAAK,CAAC,EACrE,CAAC;QACD,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,CAAC,CAAC,0CAA0C,EAAE;YACpD,EAAE;YACF,gBAAgB,EAAE,cAAc,CAAC,kBAAkB;SACpD,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,cAAc,CAAC,MAAM,GAAG,MAAM,CAAA;IAChC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAC,IAAI,CAAC;QACzD,GAAG,cAAc;QACjB,MAAM;QACN,KAAK,EAAE,yCAAoB,CAAC,OAAO;QACnC,WAAW,EAAE,SAAS;QACtB,KAAK,EAAE,cAAc,CAAC,KAAK,GAAG,CAAC;QAC/B,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI,IAAI,EAAE;KACtB,CAAC,CAAA;IAEF,MAAM,IAAA,uCAA2B,EAAC,cAAc,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAErG,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread.js'\nimport { updateActivityInstanceState } from '../common.js'\nimport { checkAuthority } from './check-authority.js'\n\nexport async function restart(\n id: string,\n output: object,\n reason: string,\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n const repository = tx.getRepository(ActivityThread)\n const activityThread = await repository.findOne({\n where: { domain: { id: domain.id }, id },\n relations: ['activityInstance', 'activityInstance.activity']\n })\n\n if (!activityThread) {\n throw new Error(\n context.t('error.activity-thread not found', {\n activityThread: id\n })\n )\n }\n\n await checkAuthority(activityThread, context)\n\n /* \n Prerequisites for a activity thread to Be Delegated.\n - The previous state of the activity thread should be Rejected.\n */\n if (activityThread.state !== ActivityThreadStatus.Rejected) {\n throw new Error(\n context.t(`error.activity-thread should be the state`, {\n id,\n state: ActivityThreadStatus.Rejected,\n actual: activityThread.state\n })\n )\n }\n\n /*\n * **되돌릴 수 없는 판정은 되살리지 않는다.**\n *\n * 반려되는 순간 대상이 닫히는 업무가 있다 — 부적합 처분, 트윈 조치. 그런 건을 되살리면 다음 차수의\n * 결재가 새로 서는데, 대상은 이미 닫혀 있어 **승인해도 아무 일이 일어나지 않는다.** 사람은 승인할\n * 것이 있다고 보고, 오류도 안 난다.\n *\n * 다시 하려면 새로 낸다.\n */\n if (\n activityThread.activityInstance?.rejectionIsFinal ||\n activityThread.activityInstance?.activity?.rejectionIsFinal ||\n ['ended', 'aborted'].includes(activityThread.activityInstance?.state)\n ) {\n throw new Error(\n context.t('error.activity-thread rejection is final', {\n id,\n activityInstance: activityThread.activityInstanceId\n })\n )\n }\n\n if (output) {\n activityThread.output = output\n }\n\n const result = await tx.getRepository(ActivityThread).save({\n ...activityThread,\n reason,\n state: ActivityThreadStatus.Started,\n transaction: 'restart',\n round: activityThread.round + 1,\n updater: user,\n startedAt: new Date()\n })\n\n await updateActivityInstanceState(activityThread.activityInstanceId, { causedBy: [result] }, context)\n\n return result\n}\n"]}
@@ -13,7 +13,7 @@ async function submit({ id, output, reason }, context) {
13
13
  const repository = tx.getRepository(activity_thread_js_1.ActivityThread);
14
14
  var activityThread = await repository.findOne({
15
15
  where: { domain: { id: domain.id }, id },
16
- relations: ['activityInstance']
16
+ relations: ['activityInstance', 'activityInstance.activity']
17
17
  });
18
18
  if (!activityThread) {
19
19
  throw new Error(context.t('error.activity-thread not found', {
@@ -21,6 +21,10 @@ async function submit({ id, output, reason }, context) {
21
21
  }));
22
22
  }
23
23
  await (0, check_authority_js_1.checkAuthority)(activityThread, context);
24
+ // Also reject old source requests that had already restarted before the policy was installed.
25
+ if (activityThread.round > 1 && (activityThread.activityInstance?.rejectionIsFinal || activityThread.activityInstance?.activity?.rejectionIsFinal)) {
26
+ throw new Error(context.t('error.activity-thread rejection is final'));
27
+ }
24
28
  /*
25
29
  Prerequisites for a activity thread to Be Started.
26
30
  - The previous state of the activity thread must not be terminated.
@@ -1 +1 @@
1
- {"version":3,"file":"submit.js","sourceRoot":"","sources":["../../../server/controllers/activity-thread/submit.ts"],"names":[],"mappings":"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","sourcesContent":["import { ApprovalLineItem } from '@things-factory/organization'\nimport { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread.js'\nimport { updateActivityInstanceState } from '../common.js'\nimport { checkAuthority } from './check-authority.js'\nimport { firstApprovalOrder, lineItemFor, referencesToNotify } from '../activity-approval/approval-line.js'\nimport { createApproval, createReferences } from '../activity-approval/create-approval.js'\n\nexport async function submit(\n { id, output, reason }: { id: string; output?: object; reason?: string },\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n // TODO - output값 체크해서 필수필드, validation 을 만족하지 못하면, Error를 던진다.\n // 필수 필드가 빈 값인 경우나, validation 이 있는 경우에 체크하여 false가 되는 경우.\n\n const repository = tx.getRepository(ActivityThread)\n\n var activityThread = await repository.findOne({\n where: { domain: { id: domain.id }, id },\n relations: ['activityInstance']\n })\n\n if (!activityThread) {\n throw new Error(\n context.t('error.activity-thread not found', {\n activityThread: id\n })\n )\n }\n\n await checkAuthority(activityThread, context)\n\n /* \n Prerequisites for a activity thread to Be Started.\n - The previous state of the activity thread must not be terminated.\n */\n if (activityThread.state !== ActivityThreadStatus.Assigned && activityThread.state !== ActivityThreadStatus.Started) {\n throw new Error(\n context.t(`error.activity-thread should not be submitted`, {\n id,\n actual: activityThread.state\n })\n )\n }\n\n // TODO 만약 activityInstance의 threadsMin 갯수를 아직 채우지 못했다면, 새로운 activityThread를 만들어서 처리하도록 한다.\n // (다른 사용자들이 threadsMin 개수만큼의 activityThread를 채울 수 있는 기회를 제공하기 위해서)\n\n if (!activityThread.startedAt) {\n activityThread.startedAt = new Date()\n }\n\n if (!activityThread.activityInstance) {\n /* 없는 채로 아래를 읽으면 `TypeError` 가 나고, 그 오류로는 무엇이 없는지 알 수 없다. */\n throw new Error(context.t('error.activity-instance not found', { activityThread: activityThread.id }))\n }\n\n const approvalLine: ApprovalLineItem[] = activityThread.activityInstance.approvalLine\n\n /*\n * 첫 **결재자**가 어느 줄인지는 한 자리가 정한다(§`approval-line.ts`). 앞에 참조가 있으면 건너뛴다 —\n * 참조는 결재 차례를 소비하지 않는다.\n */\n const firstOrder = firstApprovalOrder(approvalLine)\n const first = firstOrder === undefined ? undefined : lineItemFor(approvalLine, firstOrder)\n\n if (first) {\n await createApproval(\n { item: first, order: firstOrder!, participation: 'approval', activityThread, transaction: 'submit' },\n context\n )\n\n /*\n * **상신 즉시 알릴 참조들.** `notifyAfter` 를 안 적은 참조가 여기 온다 — 가장 일찍 알리는 것이\n * 안 정한 사람에게 안전하다(의견을 낼 기회가 가장 많다).\n *\n * 못 만든 참조가 있어도 상신을 물리지 않는다 — 참조는 막지 않는 자격이다.\n */\n const refs = await createReferences(\n { references: referencesToNotify(approvalLine, 0), activityThread },\n context\n )\n for (const f of refs.failed) {\n console.warn(`[worklist] 참조자를 세우지 못했다 (결재선 ${f.order}번째) — ${f.reason}`)\n }\n\n activityThread = await repository.save({\n ...activityThread,\n reason,\n output,\n transaction: 'submit',\n state: ActivityThreadStatus.Submitted,\n updater: user\n })\n } else {\n activityThread = await repository.save({\n ...activityThread,\n reason,\n output,\n transaction: 'end',\n state: ActivityThreadStatus.Ended,\n updater: user,\n terminator: user,\n terminatedAt: new Date()\n })\n }\n\n await updateActivityInstanceState(activityThread.activityInstanceId, { causedBy: [activityThread] }, context)\n\n return activityThread\n}\n"]}
1
+ {"version":3,"file":"submit.js","sourceRoot":"","sources":["../../../server/controllers/activity-thread/submit.ts"],"names":[],"mappings":"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","sourcesContent":["import { ApprovalLineItem } from '@things-factory/organization'\nimport { ActivityThread, ActivityThreadStatus } from '../../service/activity-thread/activity-thread.js'\nimport { updateActivityInstanceState } from '../common.js'\nimport { checkAuthority } from './check-authority.js'\nimport { firstApprovalOrder, lineItemFor, referencesToNotify } from '../activity-approval/approval-line.js'\nimport { createApproval, createReferences } from '../activity-approval/create-approval.js'\n\nexport async function submit(\n { id, output, reason }: { id: string; output?: object; reason?: string },\n context: ResolverContext\n): Promise<ActivityThread> {\n const { domain, user, tx } = context.state\n\n // TODO - output값 체크해서 필수필드, validation 을 만족하지 못하면, Error를 던진다.\n // 필수 필드가 빈 값인 경우나, validation 이 있는 경우에 체크하여 false가 되는 경우.\n\n const repository = tx.getRepository(ActivityThread)\n\n var activityThread = await repository.findOne({\n where: { domain: { id: domain.id }, id },\n relations: ['activityInstance', 'activityInstance.activity']\n })\n\n if (!activityThread) {\n throw new Error(\n context.t('error.activity-thread not found', {\n activityThread: id\n })\n )\n }\n\n await checkAuthority(activityThread, context)\n\n // Also reject old source requests that had already restarted before the policy was installed.\n if (activityThread.round > 1 && (activityThread.activityInstance?.rejectionIsFinal || activityThread.activityInstance?.activity?.rejectionIsFinal)) {\n throw new Error(context.t('error.activity-thread rejection is final'))\n }\n\n /* \n Prerequisites for a activity thread to Be Started.\n - The previous state of the activity thread must not be terminated.\n */\n if (activityThread.state !== ActivityThreadStatus.Assigned && activityThread.state !== ActivityThreadStatus.Started) {\n throw new Error(\n context.t(`error.activity-thread should not be submitted`, {\n id,\n actual: activityThread.state\n })\n )\n }\n\n // TODO 만약 activityInstance의 threadsMin 갯수를 아직 채우지 못했다면, 새로운 activityThread를 만들어서 처리하도록 한다.\n // (다른 사용자들이 threadsMin 개수만큼의 activityThread를 채울 수 있는 기회를 제공하기 위해서)\n\n if (!activityThread.startedAt) {\n activityThread.startedAt = new Date()\n }\n\n if (!activityThread.activityInstance) {\n /* 없는 채로 아래를 읽으면 `TypeError` 가 나고, 그 오류로는 무엇이 없는지 알 수 없다. */\n throw new Error(context.t('error.activity-instance not found', { activityThread: activityThread.id }))\n }\n\n const approvalLine: ApprovalLineItem[] = activityThread.activityInstance.approvalLine\n\n /*\n * 첫 **결재자**가 어느 줄인지는 한 자리가 정한다(§`approval-line.ts`). 앞에 참조가 있으면 건너뛴다 —\n * 참조는 결재 차례를 소비하지 않는다.\n */\n const firstOrder = firstApprovalOrder(approvalLine)\n const first = firstOrder === undefined ? undefined : lineItemFor(approvalLine, firstOrder)\n\n if (first) {\n await createApproval(\n { item: first, order: firstOrder!, participation: 'approval', activityThread, transaction: 'submit' },\n context\n )\n\n /*\n * **상신 즉시 알릴 참조들.** `notifyAfter` 를 안 적은 참조가 여기 온다 — 가장 일찍 알리는 것이\n * 안 정한 사람에게 안전하다(의견을 낼 기회가 가장 많다).\n *\n * 못 만든 참조가 있어도 상신을 물리지 않는다 — 참조는 막지 않는 자격이다.\n */\n const refs = await createReferences(\n { references: referencesToNotify(approvalLine, 0), activityThread },\n context\n )\n for (const f of refs.failed) {\n console.warn(`[worklist] 참조자를 세우지 못했다 (결재선 ${f.order}번째) — ${f.reason}`)\n }\n\n activityThread = await repository.save({\n ...activityThread,\n reason,\n output,\n transaction: 'submit',\n state: ActivityThreadStatus.Submitted,\n updater: user\n })\n } else {\n activityThread = await repository.save({\n ...activityThread,\n reason,\n output,\n transaction: 'end',\n state: ActivityThreadStatus.Ended,\n updater: user,\n terminator: user,\n terminatedAt: new Date()\n })\n }\n\n await updateActivityInstanceState(activityThread.activityInstanceId, { causedBy: [activityThread] }, context)\n\n return activityThread\n}\n"]}
@@ -138,7 +138,7 @@ async function evalActivityInstanceState(id, context) {
138
138
  reason: '',
139
139
  output: [activity_js_1.MultipleInstanceType.Parallel, activity_js_1.MultipleInstanceType.Sequential].includes(activityInstance.activity.multiple)
140
140
  ? activityThreads
141
- .filter(thread => (thread.state = activity_thread_js_1.ActivityThreadStatus.Ended))
141
+ .filter(thread => thread.state === activity_thread_js_1.ActivityThreadStatus.Ended)
142
142
  .reduce((sum, thread) => {
143
143
  sum[thread.assigneeId] = thread.output;
144
144
  return sum;
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../server/controllers/common.ts"],"names":[],"mappings":";;AAkBA,kEA0CC;AAuCD,8DAsEC;AAED,gFAUC;AAcD,0EAYC;AA2BD,kEA6BC;AAED,sEAoCC;AAED,oFAkBC;AAED,oFA6BC;AAED,sEAoBC;AAED,wEA2CC;AAED,wDAYC;AAjbD,qCAA4B;AAE5B,yDAAsD;AAEtD,+DAA0G;AAE1G,iEAAoF;AACpF,4FAA4G;AAC5G,sFAAoG;AACpG,4FAA8G;AAC9G,qHAAmG;AACnG,oFAAsF;AACtF,6EAA+E;AAMxE,KAAK,UAAU,2BAA2B,CAC/C,EAAU,EACV,EAAE,QAAQ,EAAuC,EACjD,OAAwB;IAExB,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE5B,IAAI,gBAAgB,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uCAAgB,CAAC,CAAC,OAAO,CAAC;QACtE,KAAK,EAAE,EAAE,EAAE,EAAE;QACb,SAAS,EAAE;YACT,QAAQ;YACR,UAAU;YACV,iBAAiB;YACjB,eAAe;YACf,iBAAiB;YACjB,SAAS;YACT,SAAS;YACT,SAAS;YACT,YAAY;SACb;KACF,CAAC,CAAA;IAEF,gBAAgB,CAAC,WAAW,GAAG,QAAQ,CAAA,CAAC,qCAAqC;IAC7E,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,yBAAyB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;IAE7E;;;;;;;;OAQG;IACH,IAAI,gBAAgB,CAAC,KAAK,KAAK,6CAAsB,CAAC,KAAK,EAAE,CAAC;QAC5D,MAAM,sBAAsB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAC3C,CAAC;IAED,6EAA6E;IAC7E,MAAM,2DAAqB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;IAEzG,MAAM,EAAE,CAAC,aAAa,CAAC,uCAAgB,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;AACjE,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,sBAAsB,CAAC,UAAkB,EAAE,OAAwB;IAChF,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE5B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAC,IAAI,CAAC;QAC1D,KAAK,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE;KAChD,CAAC,CAAA;IACF,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAM;IAE3B,MAAM,IAAI,GAAG,EAAE,CAAC,aAAa,CAAC,uCAAgB,CAAC,CAAA;IAC/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC;QAC3B,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvB,cAAc,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE;YAC5B,aAAa,EAAE,WAAW;YAC1B,QAAQ,EAAE,+CAAwB,CAAC,OAAO;SAC3C,CAAC,CAAC;KACJ,CAAC,CAAA;IACF,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAM;IAExB,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAA;IACrB,MAAM,IAAI,CAAC,IAAI,CACb,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACf,GAAG,GAAG;QACN,QAAQ,EAAE,+CAAwB,CAAC,MAAM;QACzC,WAAW,EAAE,OAAO;QACpB,YAAY,EAAE,EAAE;KACjB,CAAC,CAAQ,CACX,CAAA;AACH,CAAC;AAEM,KAAK,UAAU,yBAAyB,CAC7C,EAAU,EACV,OAAwB;IAExB,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAElC,MAAM,gBAAgB,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uCAAgB,CAAC,CAAC,OAAO,CAAC;QACxE,KAAK,EAAE,EAAE,EAAE,EAAE;QACb,SAAS,EAAE,CAAC,iBAAiB,EAAE,UAAU,CAAC;KAC3C,CAAC,CAAA;IACF,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAA;IAEtE,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;IACvE,MAAM,qBAAqB,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAA;IACzF,MAAM,mBAAmB,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAA;IAErF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK,KAAK,6CAAsB,CAAC,KAAK,CAAC;QAC5C,KAAK,KAAK,KAAK,6CAAsB,CAAC,KAAK,CAAC;QAC5C,KAAK,KAAK,KAAK,6CAAsB,CAAC,OAAO;YAC3C,OAAO,EAAE,CAAA;QACX,KAAK,YAAY,CAAC,MAAM,KAAK,CAAC;YAC5B,OAAO;gBACL,KAAK,EAAE,6CAAsB,CAAC,MAAM;aACrC,CAAA;QACH,KAAK,UAAU,GAAG,YAAY,CAAC,MAAM;YACnC,OAAO;gBACL,KAAK,EAAE,6CAAsB,CAAC,UAAU;aACzC,CAAA;QACH,KAAK,qBAAqB,CAAC,MAAM,GAAG,CAAC;YACnC,OAAO;gBACL,KAAK,EAAE,6CAAsB,CAAC,QAAQ;gBACtC,UAAU,EAAE,IAAI,IAAI,EAAE;aACvB,CAAA;QACH,KAAK,mBAAmB,CAAC,MAAM,GAAG,CAAC;YACjC,IAAI,OAAO,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACpD,IAAI,OAAO,GACT,CAAC,OAAO,IAAI,KAAK,KAAK,6CAAsB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,KAAK,6CAAsB,CAAC,OAAO,CAAC,CAAA;YAEjH,OAAO,CAAC,OAAO;gBACb,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,OAAO;oBACP,CAAC,CAAC;wBACE,KAAK,EAAE,6CAAsB,CAAC,OAAO;wBACrC,SAAS,EAAE,IAAI,IAAI,EAAE;wBACrB,OAAO,EAAE,IAAI;qBACd;oBACH,CAAC,CAAC;wBACE,KAAK,EAAE,6CAAsB,CAAC,OAAO;qBACtC,CAAA;QACT;YACE,OAAO;gBACL,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,IAAI,yCAAoB,CAAC,OAAO,CAAC;oBACjF,CAAC,CAAC,6CAAsB,CAAC,OAAO;oBAChC,CAAC,CAAC,6CAAsB,CAAC,KAAK;gBAChC,MAAM,EAAE,EAAE;gBACV,MAAM,EAAE,CAAC,kCAAoB,CAAC,QAAQ,EAAE,kCAAoB,CAAC,UAAU,CAAC,CAAC,QAAQ,CAC/E,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CACnC;oBACC,CAAC,CAAC,eAAe;yBACZ,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,yCAAoB,CAAC,KAAK,CAAC,CAAC;yBAC7D,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;wBACtB,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,CAAA;wBACtC,OAAO,GAAG,CAAA;oBACZ,CAAC,EAAE,EAAS,CAAC;oBACjB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM;gBAC7B,YAAY,EAAE,IAAI,IAAI,EAAE;gBACxB,UAAU,EAAE,IAAI;aACjB,CAAA;IACL,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,kCAAkC,CACtD,WAAmB,EACnB,gBAAkC,EAClC,OAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAA;IAE9E,MAAM,2BAA2B,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAEvF,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,+BAA+B,CACnD,WAAmB,EACnB,gBAAkC,EAClC,OAAyB,EACzB,OAAwB;IAExB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAA;IAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,yCAAoB,CAAC,UAAU,CAAC,CAAA;IAExF,IAAI,IAAI,GAAG,gBAAgB,CAAC,UAAU,IAAI,CAAC,OAAO,EAAE,CAAC;QACnD,MAAM,iBAAiB,CAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAA;IACjE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,WAAmB,EACnB,gBAAkC,EAClC,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAA;IACnD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IAEtB,OAAO,MAAM,UAAU,CAAC,IAAI,CAAC;QAC3B,OAAO,EAAE,CAAC;QACV,MAAM;QACN,KAAK,EAAE,yCAAoB,CAAC,UAAU;QACtC,gBAAgB;QAChB,WAAW;QACX,MAAM,EAAE,gBAAgB,CAAC,MAAM;QAC/B,KAAK,EAAE,gBAAgB,CAAC,KAAK;QAC7B,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,GAAG;KACf,CAAC,CAAA;AACJ,CAAC;AAEM,KAAK,UAAU,2BAA2B,CAC/C,WAAmB,EACnB,gBAAkC,EAClC,QAAc,EACd,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAA;IACnD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IAEtB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC;QACnC,OAAO,EAAE,CAAC;QACV,MAAM;QACN,QAAQ;QACR,KAAK,EAAE,yCAAoB,CAAC,QAAQ;QACpC,gBAAgB;QAChB,WAAW;QACX,MAAM,EAAE,gBAAgB,CAAC,MAAM;QAC/B,KAAK,EAAE,gBAAgB,CAAC,KAAK;QAC7B,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,GAAG;KACf,CAAC,CAAA;IAEF,MAAM,2BAA2B,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IAEvF,OAAO,MAAM,CAAA;AACf,CAAC;AAEM,KAAK,UAAU,6BAA6B,CACjD,WAAmB,EACnB,gBAAkC,EAClC,SAAiB,EACjB,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,mCAAc,CAAC,CAAA;IACnD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IAEtB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE;QAClD,OAAO,QAAQ,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;IAEF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAClC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QACtB,OAAO;YACL,OAAO,EAAE,CAAC;YACV,QAAQ;YACR,KAAK,EAAE,yCAAoB,CAAC,QAAQ;YACpC,gBAAgB;YAChB,MAAM;YACN,WAAW;YACX,MAAM,EAAE,gBAAgB,CAAC,MAAM;YAC/B,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,gBAAgB,CAAC,KAAK;YAC7B,UAAU,EAAE,GAAG;SACT,CAAA;IACV,CAAC,CAAC,CACH,CAAA;IAED,MAAM,2BAA2B,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,CAAA;IAErF,OAAO,MAAM,CAAA;AACf,CAAC;AAEM,KAAK,UAAU,oCAAoC,CACxD,WAAmB,EACnB,gBAAkC,EAClC,OAAwB;IAExB,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE5B,4FAA4F;IAC5F,MAAM,OAAO,GAAG,IAAA,4BAAS,EAAC,gBAAgB,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,gBAAI,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3H,MAAM,SAAS,GAAG,IAAA,8BAAW,EAAC,KAAK,CAAC,CAAA;IAEpC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IAED,4DAA4D;IAC5D,OAAO,MAAM,6BAA6B,CAAC,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;AAC/F,CAAC;AAEM,KAAK,UAAU,oCAAoC,CAAC,OAAwB;IACjF,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAQ,CAAC,CAAC,SAAS,CAAC;QAC1D,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;QACzB,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;KACtB,CAAC,CAAA;IAEF,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QACxC,OAAM;IACR,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,yBAAU,CAAC,CAAC,OAAO,CAAC;QAC5D,KAAK,EAAE;YACL,EAAE,EAAE,QAAQ,CAAC,YAAY;SAC1B;KACF,CAAC,CAAA;IAEF,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,SAAS;QAAE,OAAM;IAEhD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAQ,CAAC,CAAC,OAAO,CAAC;QACvD,KAAK,EAAE;YACL,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;YACzB,EAAE,EAAE,UAAU,CAAC,SAAS;SACzB;QACD,SAAS,EAAE,CAAC,MAAM,CAAC;KACpB,CAAC,CAAA;IAEF,OAAO,OAAO,EAAE,IAAI,CAAA;AACtB,CAAC;AAEM,KAAK,UAAU,6BAA6B,CAAC,OAAwB;IAC1E,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAQ,CAAC,CAAC,SAAS,CAAC;QAC1D,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;QACzB,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;KACtB,CAAC,CAAA;IAEF,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QACxC,OAAM;IACR,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAQ,CAAC,CAAC,OAAO,CAAC;QAC1D,KAAK,EAAE;YACL,EAAE,EAAE,QAAQ,CAAC,YAAY;SAC1B;QACD,SAAS,EAAE,CAAC,MAAM,CAAC;KACpB,CAAC,CAAA;IAEF,OAAO,UAAU,EAAE,IAAI,CAAA;AACzB,CAAC;AAEM,KAAK,UAAU,8BAA8B,CAClD,IAAqC,EACrC,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAE1C,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAuC,CAAA;IACnF,MAAM,EAAE,GAAG,QAAQ,EAAE,EAAE,IAAI,QAAQ,EAAE,EAAE,IAAI,KAAK,CAAA;IAEhD,IAAI,IAAI,IAAI,kCAAmB,CAAC,QAAQ,EAAE,CAAC;QACzC,gGAAgG;QAChG,MAAM,QAAQ,GACZ,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QAErH,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChC,OAAM;QACR,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAA;IACtB,CAAC;SAAM,IAAI,IAAI,IAAI,kCAAmB,CAAC,UAAU,EAAE,CAAC;QAClD,MAAM,UAAU,GACd,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,yBAAU,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAA;QAE1H,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACvC,OAAM;QACR,CAAC;QACD,OAAO,MAAM,EAAE,CAAC,aAAa,CAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAClF,CAAC;SAAM,IAAI,IAAI,IAAI,kCAAmB,CAAC,IAAI,EAAE,CAAC;QAC5C;;;;;WAKG;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,mDAAmD,CAAC,CAAC,EAAE;YAC7F,IAAI,EAAE,2CAAuB;SAC9B,CAAC,CAAA;IACJ,CAAC;SAAM,IAAI,IAAI,IAAI,kCAAmB,CAAC,MAAM,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAA;IACb,CAAC;SAAM,IAAI,IAAI,IAAI,kCAAmB,CAAC,YAAY,EAAE,CAAC;QACpD,OAAO,MAAM,oCAAoC,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;SAAM,IAAI,IAAI,IAAI,kCAAmB,CAAC,YAAY,EAAE,CAAC;QACpD,OAAO,MAAM,6BAA6B,CAAC,OAAO,CAAC,CAAA;IACrD,CAAC;AACH,CAAC;AAED,SAAgB,sBAAsB,CAAC,UAAmC,EAAE,KAA6B;IACvG,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAM;IACR,CAAC;IAED,OAAO,UAAU,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACjC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QACrE,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC,EAAE,EAAE,CAAC,CAAA;AACR,CAAC","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(\"there's no users having given role\")\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'\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(\"there's no users having given role\")\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,6 +4,6 @@ import { ActivityMutation } from "./activity-mutation.js";
4
4
  import { ActivityQuery } from "./activity-query.js";
5
5
  import { ActivityHistoryEntitySubscriber } from "./event-subscriber.js";
6
6
  import { ActivityDeclarationGuardSubscriber } from "./declaration-guard-subscriber.js";
7
- export declare const entities: (typeof ActivityHistory | typeof Activity)[];
8
- export declare const resolvers: (typeof ActivityQuery | typeof ActivityMutation)[];
7
+ export declare const entities: (typeof Activity | typeof ActivityHistory)[];
8
+ export declare const resolvers: (typeof ActivityMutation | typeof ActivityQuery)[];
9
9
  export declare const subscribers: (typeof ActivityHistoryEntitySubscriber | typeof ActivityDeclarationGuardSubscriber)[];
@@ -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 ActivityApprovalSubscription | typeof ActivityApprovalMutation | typeof ActivityApprovalQuery)[];
7
+ export declare const resolvers: (typeof ActivityApprovalQuery | typeof ActivityApprovalMutation | typeof ActivityApprovalSubscription)[];
8
8
  export declare const subscribers: (typeof ActivityApprovalSubscriber)[];
@@ -12,14 +12,14 @@ import { Brackets } from 'typeorm';
12
12
  * everyone holding that role, forever.
13
13
  * - **끝난 것의 정의는 한 자리에 있다** (TERMINATED_JUDGMENTS). Counted again here, a new judgment
14
14
  * value would land in one reader and not the other.
15
- * - **내가 올린 것은 내 결재가 아니다** (ADR-0052 ②). 누르는 자리(`checkAuthority`)가 거절하는 것을
16
- * 여기서도 빼야 한다 — 갈리면 목록에 떴는데 누르면 거절된다. 두 표현은 `own-request.ts` 에 나란히 있다.
15
+ * - **내가 올린 것도 내 결재다.** 상신자를 빼던 규칙(ADR-0052 ②)은 2026-10-23 사용자가 거두었다 —
16
+ * 결재 자리에 서는 사람이면 자기가 올린 건도 결재함에 뜨고 누를 수 있다.
17
17
  *
18
18
  * ── What a caller has to bring ───────────────────────────────────────────────
19
19
  * `ap` (ActivityApproval) as the alias, and **`at` and `ai` joined** — the thread and its instance.
20
- * The clause reads only `ap` today. It is about to read the instance as well, to answer whether the
21
- * person judging is the one who raised it (ADR-0052 ②), and a caller that has not joined does not
22
- * return a wrong number — it throws at query time.
20
+ * The clause reads only `ap`. It read the instance too while the one who raised a case was left out of
21
+ * its own inbox (ADR-0052 ②, withdrawn 2026-10-23); the joins stay so that a clause reading the
22
+ * instance again works for every reader at once — a caller that has not joined throws at query time.
23
23
  *
24
24
  * Two of the three readers already joined, for their own reasons: the inbox list for sorting, the
25
25
  * calendar to read the thread it draws. The badge joined nothing, because counting rows needs no
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.myPendingApprovalsWhere = myPendingApprovalsWhere;
4
4
  const typeorm_1 = require("typeorm");
5
5
  const approval_line_js_1 = require("../../controllers/activity-approval/approval-line.js");
6
- const own_request_js_1 = require("../../controllers/activity-approval/own-request.js");
7
6
  /**
8
7
  * The approvals waiting on me — one definition, three readers.
9
8
  *
@@ -17,14 +16,14 @@ const own_request_js_1 = require("../../controllers/activity-approval/own-reques
17
16
  * everyone holding that role, forever.
18
17
  * - **끝난 것의 정의는 한 자리에 있다** (TERMINATED_JUDGMENTS). Counted again here, a new judgment
19
18
  * value would land in one reader and not the other.
20
- * - **내가 올린 것은 내 결재가 아니다** (ADR-0052 ②). 누르는 자리(`checkAuthority`)가 거절하는 것을
21
- * 여기서도 빼야 한다 — 갈리면 목록에 떴는데 누르면 거절된다. 두 표현은 `own-request.ts` 에 나란히 있다.
19
+ * - **내가 올린 것도 내 결재다.** 상신자를 빼던 규칙(ADR-0052 ②)은 2026-10-23 사용자가 거두었다 —
20
+ * 결재 자리에 서는 사람이면 자기가 올린 건도 결재함에 뜨고 누를 수 있다.
22
21
  *
23
22
  * ── What a caller has to bring ───────────────────────────────────────────────
24
23
  * `ap` (ActivityApproval) as the alias, and **`at` and `ai` joined** — the thread and its instance.
25
- * The clause reads only `ap` today. It is about to read the instance as well, to answer whether the
26
- * person judging is the one who raised it (ADR-0052 ②), and a caller that has not joined does not
27
- * return a wrong number — it throws at query time.
24
+ * The clause reads only `ap`. It read the instance too while the one who raised a case was left out of
25
+ * its own inbox (ADR-0052 ②, withdrawn 2026-10-23); the joins stay so that a clause reading the
26
+ * instance again works for every reader at once — a caller that has not joined throws at query time.
28
27
  *
29
28
  * Two of the three readers already joined, for their own reasons: the inbox list for sorting, the
30
29
  * calendar to read the thread it draws. The badge joined nothing, because counting rows needs no
@@ -37,8 +36,6 @@ function myPendingApprovalsWhere({ userId, roles }) {
37
36
  return new typeorm_1.Brackets(outer => {
38
37
  outer
39
38
  .where(`(ap.participation IS NULL OR ap.participation != 'reference')`)
40
- /* 값을 쓰는 자리에서 묶는다 — 옆 bracket 이 같은 이름을 묶어 준 덕에 도는 것은 우연이다. */
41
- .andWhere(own_request_js_1.NOT_RAISED_BY_ME_SQL, { userId })
42
39
  .andWhere(new typeorm_1.Brackets(qb => {
43
40
  qb.where('ap.judgment NOT IN (:...judgment)', { judgment }).andWhere('ap.approver = :userId', { userId });
44
41
  if (roles.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"my-pending-approvals.js","sourceRoot":"","sources":["../../../server/service/activity-approval/my-pending-approvals.ts"],"names":[],"mappings":";;AAiCA,0DAyBC;AA1DD,qCAAkC;AAElC,2FAA2F;AAC3F,uFAAyF;AAEzF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,SAAgB,uBAAuB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAuC;IAC5F,MAAM,QAAQ,GAAG,CAAC,GAAG,uCAAoB,CAAC,CAAA;IAE1C,OAAO,IAAI,kBAAQ,CAAC,KAAK,CAAC,EAAE;QAC1B,KAAK;aACF,KAAK,CAAC,+DAA+D,CAAC;YACvE,6DAA6D;aAC5D,QAAQ,CAAC,qCAAoB,EAAE,EAAE,MAAM,EAAE,CAAC;aAC1C,QAAQ,CACP,IAAI,kBAAQ,CAAC,EAAE,CAAC,EAAE;YAChB,EAAE,CAAC,KAAK,CAAC,mCAAmC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;YAEzG,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,EAAE,CAAC,OAAO,CACR,IAAI,kBAAQ,CAAC,MAAM,CAAC,EAAE;oBACpB,MAAM;yBACH,KAAK,CAAC,mCAAmC,EAAE,EAAE,QAAQ,EAAE,CAAC;yBACxD,QAAQ,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC;yBACrD,QAAQ,CAAC,qBAAqB,CAAC,CAAA;gBACpC,CAAC,CAAC,CACH,CAAA;YACH,CAAC;QACH,CAAC,CAAC,CACH,CAAA;IACL,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { Brackets } from 'typeorm'\n\nimport { TERMINATED_JUDGMENTS } from '../../controllers/activity-approval/approval-line.js'\nimport { NOT_RAISED_BY_ME_SQL } from '../../controllers/activity-approval/own-request.js'\n\n/**\n * The approvals waiting on me — one definition, three readers.\n *\n * 내 결재함 asks this, the calendar asks it, and so does the badge on the collapsed menu. All three\n * have to agree on three things that are easy to get wrong separately:\n *\n * - **참조는 승인 대기가 아니다.** Asking a reference to approve destroys what a reference is. An\n * empty column is an approval: rows created before the column existed have nothing there.\n * - **역할로 걸린 결재도 내 것이다** — but only while unclaimed. A role-held row keeps `approver`\n * empty until someone presses, so without a judgment test finished work stays in the list of\n * everyone holding that role, forever.\n * - **끝난 것의 정의는 한 자리에 있다** (TERMINATED_JUDGMENTS). Counted again here, a new judgment\n * value would land in one reader and not the other.\n * - **내가 올린 것은 내 결재가 아니다** (ADR-0052 ②). 누르는 자리(`checkAuthority`)가 거절하는 것을\n * 여기서도 빼야 한다 — 갈리면 목록에 떴는데 누르면 거절된다. 두 표현은 `own-request.ts` 에 나란히 있다.\n *\n * ── What a caller has to bring ───────────────────────────────────────────────\n * `ap` (ActivityApproval) as the alias, and **`at` and `ai` joined** — the thread and its instance.\n * The clause reads only `ap` today. It is about to read the instance as well, to answer whether the\n * person judging is the one who raised it (ADR-0052 ②), and a caller that has not joined does not\n * return a wrong number — it throws at query time.\n *\n * Two of the three readers already joined, for their own reasons: the inbox list for sorting, the\n * calendar to read the thread it draws. The badge joined nothing, because counting rows needs no\n * columns. So the clause would have started working for two readers and started failing for the\n * third, and the third is the one nobody opens a screen to check. The badge joins too, and\n * `joined-for-the-shared-clause.test.ts` counts that every reader does.\n */\nexport function myPendingApprovalsWhere({ userId, roles }: { userId: string; roles: string[] }): Brackets {\n const judgment = [...TERMINATED_JUDGMENTS]\n\n return new Brackets(outer => {\n outer\n .where(`(ap.participation IS NULL OR ap.participation != 'reference')`)\n /* 값을 쓰는 자리에서 묶는다 — 옆 bracket 이 같은 이름을 묶어 준 덕에 도는 것은 우연이다. */\n .andWhere(NOT_RAISED_BY_ME_SQL, { userId })\n .andWhere(\n new Brackets(qb => {\n qb.where('ap.judgment NOT IN (:...judgment)', { judgment }).andWhere('ap.approver = :userId', { userId })\n\n if (roles.length > 0) {\n qb.orWhere(\n new Brackets(roleQb => {\n roleQb\n .where('ap.judgment NOT IN (:...judgment)', { judgment })\n .andWhere('ap.approverRole IN (:...roles)', { roles })\n .andWhere(`ap.approver IS NULL`)\n })\n )\n }\n })\n )\n })\n}\n"]}
1
+ {"version":3,"file":"my-pending-approvals.js","sourceRoot":"","sources":["../../../server/service/activity-approval/my-pending-approvals.ts"],"names":[],"mappings":";;AAgCA,0DAuBC;AAvDD,qCAAkC;AAElC,2FAA2F;AAE3F;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,SAAgB,uBAAuB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAuC;IAC5F,MAAM,QAAQ,GAAG,CAAC,GAAG,uCAAoB,CAAC,CAAA;IAE1C,OAAO,IAAI,kBAAQ,CAAC,KAAK,CAAC,EAAE;QAC1B,KAAK;aACF,KAAK,CAAC,+DAA+D,CAAC;aACtE,QAAQ,CACP,IAAI,kBAAQ,CAAC,EAAE,CAAC,EAAE;YAChB,EAAE,CAAC,KAAK,CAAC,mCAAmC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;YAEzG,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,EAAE,CAAC,OAAO,CACR,IAAI,kBAAQ,CAAC,MAAM,CAAC,EAAE;oBACpB,MAAM;yBACH,KAAK,CAAC,mCAAmC,EAAE,EAAE,QAAQ,EAAE,CAAC;yBACxD,QAAQ,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC;yBACrD,QAAQ,CAAC,qBAAqB,CAAC,CAAA;gBACpC,CAAC,CAAC,CACH,CAAA;YACH,CAAC;QACH,CAAC,CAAC,CACH,CAAA;IACL,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { Brackets } from 'typeorm'\n\nimport { TERMINATED_JUDGMENTS } from '../../controllers/activity-approval/approval-line.js'\n\n/**\n * The approvals waiting on me — one definition, three readers.\n *\n * 내 결재함 asks this, the calendar asks it, and so does the badge on the collapsed menu. All three\n * have to agree on three things that are easy to get wrong separately:\n *\n * - **참조는 승인 대기가 아니다.** Asking a reference to approve destroys what a reference is. An\n * empty column is an approval: rows created before the column existed have nothing there.\n * - **역할로 걸린 결재도 내 것이다** — but only while unclaimed. A role-held row keeps `approver`\n * empty until someone presses, so without a judgment test finished work stays in the list of\n * everyone holding that role, forever.\n * - **끝난 것의 정의는 한 자리에 있다** (TERMINATED_JUDGMENTS). Counted again here, a new judgment\n * value would land in one reader and not the other.\n * - **내가 올린 것도 내 결재다.** 상신자를 빼던 규칙(ADR-0052 ②)은 2026-10-23 사용자가 거두었다 —\n * 결재 자리에 서는 사람이면 자기가 올린 건도 결재함에 뜨고 누를 수 있다.\n *\n * ── What a caller has to bring ───────────────────────────────────────────────\n * `ap` (ActivityApproval) as the alias, and **`at` and `ai` joined** — the thread and its instance.\n * The clause reads only `ap`. It read the instance too while the one who raised a case was left out of\n * its own inbox (ADR-0052 ②, withdrawn 2026-10-23); the joins stay so that a clause reading the\n * instance again works for every reader at once — a caller that has not joined throws at query time.\n *\n * Two of the three readers already joined, for their own reasons: the inbox list for sorting, the\n * calendar to read the thread it draws. The badge joined nothing, because counting rows needs no\n * columns. So the clause would have started working for two readers and started failing for the\n * third, and the third is the one nobody opens a screen to check. The badge joins too, and\n * `joined-for-the-shared-clause.test.ts` counts that every reader does.\n */\nexport function myPendingApprovalsWhere({ userId, roles }: { userId: string; roles: string[] }): Brackets {\n const judgment = [...TERMINATED_JUDGMENTS]\n\n return new Brackets(outer => {\n outer\n .where(`(ap.participation IS NULL OR ap.participation != 'reference')`)\n .andWhere(\n new Brackets(qb => {\n qb.where('ap.judgment NOT IN (:...judgment)', { judgment }).andWhere('ap.approver = :userId', { userId })\n\n if (roles.length > 0) {\n qb.orWhere(\n new Brackets(roleQb => {\n roleQb\n .where('ap.judgment NOT IN (:...judgment)', { judgment })\n .andWhere('ap.approverRole IN (:...roles)', { roles })\n .andWhere(`ap.approver IS NULL`)\n })\n )\n }\n })\n )\n })\n}\n"]}
@@ -11,7 +11,7 @@ export declare class ActivityInstanceQuery {
11
11
  activityInstancesIssuedByMe(params: ListParam, context: ResolverContext): Promise<ActivityInstanceList>;
12
12
  activityInstancesByActivity(activityId: string, params: ListParam, context: ResolverContext): Promise<ActivityInstanceList>;
13
13
  pickableActivityList(params: ListParam, context: ResolverContext): Promise<ActivityInstanceList>;
14
- draftList(params: ListParam, context: ResolverContext): Promise<ActivityInstanceList>;
14
+ draftList(params: ListParam, group: string, context: ResolverContext): Promise<ActivityInstanceList>;
15
15
  activity(activityInstance: ActivityInstance): Promise<Activity>;
16
16
  activityThreads(activityInstance: ActivityInstance, context: ResolverContext): Promise<ActivityThread[]>;
17
17
  assigneeRoles(activityInstance: ActivityInstance): Promise<Role[]>;