@things-factory/compliance 10.1.261 → 10.1.262
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/service/common/legal-todo.d.ts +7 -1
- package/dist-server/service/common/legal-todo.js +8 -6
- package/dist-server/service/common/legal-todo.js.map +1 -1
- package/dist-server/service/training/training-service.js +1 -0
- package/dist-server/service/training/training-service.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -18
|
@@ -12,8 +12,14 @@ export interface LegalTodo {
|
|
|
12
12
|
subjectKind: string;
|
|
13
13
|
subjectId: string;
|
|
14
14
|
dueAt?: Date | null;
|
|
15
|
+
/** Who set it off - the manager opening the training year; the one asked when nobody did (an employee's change). */
|
|
16
|
+
by?: User;
|
|
15
17
|
}
|
|
16
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Hands out one to-do; answers its instance id, or nothing where the domain has not installed the to-do. worklist's
|
|
20
|
+
* handOut: the one asked has it in 할 일 and nobody in 상신함 - issued as its own assignee, it went to the person's
|
|
21
|
+
* 상신함 (2026-11-08).
|
|
22
|
+
*/
|
|
17
23
|
export declare function issueLegalTodo(tx: EntityManager, domain: any, todo: LegalTodo): Promise<string | null>;
|
|
18
24
|
/** Closes the to-do once what it asked is recorded - left alone when it is closed already. */
|
|
19
25
|
export declare function closeLegalTodo(tx: EntityManager, domain: any, instanceId: string | null | undefined, by: User, reason?: string): Promise<void>;
|
|
@@ -7,23 +7,25 @@ const env_1 = require("@things-factory/env");
|
|
|
7
7
|
const translator_1 = require("@things-factory/i18n-base/translator");
|
|
8
8
|
const worklist_1 = require("@things-factory/worklist");
|
|
9
9
|
const legal_todo_activity_names_1 = require("../../activities/legal-todo-activity-names");
|
|
10
|
-
/** The to-do
|
|
10
|
+
/** The context worklist works the to-do under - its user is who acts; worklist speaks its refusals through `t`. */
|
|
11
11
|
function contextOf(tx, domain, user) {
|
|
12
12
|
const t = (0, translator_1.translatorFor)(user.locale || 'ko');
|
|
13
13
|
return { state: { domain, user, tx }, t: (key, options) => t(key, options) };
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Hands out one to-do; answers its instance id, or nothing where the domain has not installed the to-do. worklist's
|
|
17
|
+
* handOut: the one asked has it in 할 일 and nobody in 상신함 - issued as its own assignee, it went to the person's
|
|
18
|
+
* 상신함 (2026-11-08).
|
|
19
|
+
*/
|
|
16
20
|
async function issueLegalTodo(tx, domain, todo) {
|
|
17
21
|
const activity = await tx.getRepository(worklist_1.Activity).findOne({ where: { domain: { id: domain.id }, name: legal_todo_activity_names_1.LEGAL_TODO_ACTIVITY } });
|
|
18
22
|
if (!activity) {
|
|
19
23
|
env_1.logger.warn(`[Compliance] ${domain.subdomain}: the activity "${legal_todo_activity_names_1.LEGAL_TODO_ACTIVITY}" is not installed - "${todo.name}" not handed out`);
|
|
20
24
|
return null;
|
|
21
25
|
}
|
|
22
|
-
const context = contextOf(tx, domain, todo.assignee);
|
|
23
|
-
const dueAt = todo.dueAt ?? undefined;
|
|
26
|
+
const context = contextOf(tx, domain, todo.by ?? todo.assignee);
|
|
24
27
|
const input = { subjectKind: todo.subjectKind, subjectId: todo.subjectId, headline: todo.headline, address: todo.address };
|
|
25
|
-
const instance = await (0, worklist_1.
|
|
26
|
-
await (0, worklist_1.assign)({ id: instance.id, assignees: [todo.assignee.email], dueAt, reason: todo.name }, context);
|
|
28
|
+
const instance = await (0, worklist_1.handOut)({ activityId: activity.id, name: todo.name, description: todo.headline, input, assignee: todo.assignee, dueAt: todo.dueAt ?? undefined }, context);
|
|
27
29
|
return instance.id;
|
|
28
30
|
}
|
|
29
31
|
/** Closes the to-do once what it asked is recorded - left alone when it is closed already. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legal-todo.js","sourceRoot":"","sources":["../../../server/service/common/legal-todo.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"legal-todo.js","sourceRoot":"","sources":["../../../server/service/common/legal-todo.ts"],"names":[],"mappings":";;AAyCA,wCAUC;AAGD,wCAIC;AA1DD,qCAA2C;AAG3C,6CAA4C;AAC5C,qEAAoE;AACpE,uDAAmF;AAEnF,0FAAgF;AAuBhF,mHAAmH;AACnH,SAAS,SAAS,CAAC,EAAiB,EAAE,MAAW,EAAE,IAAU;IAC3D,MAAM,CAAC,GAAG,IAAA,0BAAa,EAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,CAAA;IAC5C,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAW,EAAE,OAAa,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,EAAS,CAAA;AACnG,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,cAAc,CAAC,EAAiB,EAAE,MAAW,EAAE,IAAe;IAClF,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,mBAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,+CAAmB,EAAS,EAAE,CAAC,CAAA;IACrI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,YAAM,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,SAAS,mBAAmB,+CAAmB,yBAAyB,IAAI,CAAC,IAAI,kBAAkB,CAAC,CAAA;QACvI,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC/D,MAAM,KAAK,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAA;IAC1H,MAAM,QAAQ,GAAG,MAAM,IAAA,kBAAO,EAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,EAAE,OAAO,CAAC,CAAA;IACjL,OAAO,QAAQ,CAAC,EAAE,CAAA;AACpB,CAAC;AAED,8FAA8F;AACvF,KAAK,UAAU,cAAc,CAAC,EAAiB,EAAE,MAAW,EAAE,UAAqC,EAAE,EAAQ,EAAE,MAAM,GAAG,KAAK;IAClI,IAAI,CAAC,UAAU;QAAE,OAAM;IACvB,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,yBAAc,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,IAAA,YAAE,EAAC,CAAC,UAAU,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,EAAS,EAAE,CAAC,CAAA;IACvK,IAAI,IAAI;QAAE,MAAM,IAAA,gBAAK,EAAC,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAS,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAA;AACrF,CAAC","sourcesContent":["import { EntityManager, In } from 'typeorm'\n\nimport { User } from '@things-factory/auth-base'\nimport { logger } from '@things-factory/env'\nimport { translatorFor } from '@things-factory/i18n-base/translator'\nimport { abort, Activity, ActivityThread, handOut } from '@things-factory/worklist'\n\nimport { LEGAL_TODO_ACTIVITY } from '../../activities/legal-todo-activity-names'\n\n/*\n * Handing out a legal to-do and closing it (ADR-0187 decisions 18, 23 · ADR-0147 decision 9). The record it is about\n * keeps the instance id; recording what was asked closes it. Reminding one past its day is worklist's (ADR-0186).\n */\n\nexport interface LegalTodo {\n /** The one asked. */\n assignee: User\n /** 「성희롱 예방교육 이수 — 2026」. */\n name: string\n /** 「2026-12-31 까지」 - what the to-do shows. */\n headline: string\n /** The screen that records it - `regulations?tab=trainings`. */\n address: string\n subjectKind: string\n subjectId: string\n dueAt?: Date | null\n /** Who set it off - the manager opening the training year; the one asked when nobody did (an employee's change). */\n by?: User\n}\n\n/** The context worklist works the to-do under - its user is who acts; worklist speaks its refusals through `t`. */\nfunction contextOf(tx: EntityManager, domain: any, user: User) {\n const t = translatorFor(user.locale || 'ko')\n return { state: { domain, user, tx }, t: (key: string, options?: any) => t(key, options) } as any\n}\n\n/**\n * Hands out one to-do; answers its instance id, or nothing where the domain has not installed the to-do. worklist's\n * handOut: the one asked has it in 할 일 and nobody in 상신함 - issued as its own assignee, it went to the person's\n * 상신함 (2026-11-08).\n */\nexport async function issueLegalTodo(tx: EntityManager, domain: any, todo: LegalTodo): Promise<string | null> {\n const activity = await tx.getRepository(Activity).findOne({ where: { domain: { id: domain.id }, name: LEGAL_TODO_ACTIVITY } as any })\n if (!activity) {\n logger.warn(`[Compliance] ${domain.subdomain}: the activity \"${LEGAL_TODO_ACTIVITY}\" is not installed - \"${todo.name}\" not handed out`)\n return null\n }\n const context = contextOf(tx, domain, todo.by ?? todo.assignee)\n const input = { subjectKind: todo.subjectKind, subjectId: todo.subjectId, headline: todo.headline, address: todo.address }\n const instance = await handOut({ activityId: activity.id, name: todo.name, description: todo.headline, input, assignee: todo.assignee, dueAt: todo.dueAt ?? undefined }, context)\n return instance.id\n}\n\n/** Closes the to-do once what it asked is recorded - left alone when it is closed already. */\nexport async function closeLegalTodo(tx: EntityManager, domain: any, instanceId: string | null | undefined, by: User, reason = '기록함'): Promise<void> {\n if (!instanceId) return\n const open = await tx.getRepository(ActivityThread).count({ where: { activityInstance: { id: instanceId }, state: In(['assigned', 'started', 'unassigned']) } as any })\n if (open) await abort({ id: instanceId, reason } as any, contextOf(tx, domain, by))\n}\n"]}
|
|
@@ -389,6 +389,7 @@ async function openTrainingYear(kindCode, year, context) {
|
|
|
389
389
|
const t = (0, translator_1.translatorFor)(person.user.locale || 'ko');
|
|
390
390
|
const id = await (0, legal_todo_1.issueLegalTodo)(tx, domain, {
|
|
391
391
|
assignee: person.user,
|
|
392
|
+
by: user,
|
|
392
393
|
name: t('text.training-todo-name', { kind: kindWord(t, kindCode), year }),
|
|
393
394
|
headline: t('text.training-todo-headline', { dueOn }),
|
|
394
395
|
address: exports.MY_TRAININGS_ADDRESS,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"training-service.js","sourceRoot":"","sources":["../../../server/service/training/training-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager, In } from 'typeorm'\n\nimport { announce } from '@things-factory/announcement'\nimport { createAttachment } from '@things-factory/attachment-base'\nimport { requestHolds, User } from '@things-factory/auth-base'\nimport { translatorFor } from '@things-factory/i18n-base/translator'\nimport { audienceTargetRefusal, audienceUserIds, Department, departmentTreeOf, domainRolesOf, Employee, withDescendants } from '@things-factory/organization'\nimport { isActiveEmployee } from '@things-factory/organization/dist-server/service/employee-profile/employee-profile-rules.js'\nimport { CourseVersion, enroll, Enrollment, EnrollmentStatus } from '@things-factory/learning'\nimport { getRepository, Refusal } from '@things-factory/shell'\n\nimport { todayIn, workingEmployeeOf } from '../common/employee-reader'\nimport { closeLegalTodo, issueLegalTodo } from '../common/legal-todo'\nimport { TrainingAssignment, TrainingCompletion, TrainingCompletionStatus, TrainingMethod, TrainingSession, TrainingSetting } from './training'\nimport {\n onlineDueOnOf,\n TrainingTarget,\n trainingCertificateRefusal,\n trainingDecisionRefusal,\n trainingDeletionRefusal,\n trainingDueOnOf,\n trainingDueAt,\n TrainingKindSet,\n trainingKindsInDomain,\n trainingSessionRefusal,\n trainingSettingRefusal,\n trainingStateOf,\n TrainingState\n} from './training-rules'\nimport { NewTrainingSession, TrainingCertificateInput, TrainingSessionPatch, TrainingSettingPatch } from './training-type'\n\n/*\n * The mandatory trainings of a domain (ADR-0187 decisions 15-19): a kind's setting, a session opened and told, the\n * attendance and certificates that complete it, the to-dos of a year, and who reads where each person stands. Nothing\n * here deletes a training record.\n */\n\nexport const TRAINING_SESSION_REF_TYPE = 'TrainingSession'\nexport const TRAINING_COMPLETION_REF_TYPE = 'TrainingCompletion'\nexport const TRAINING_SCHEDULED_TRIGGER = 'compliance.training-scheduled'\n/** The employee's screen of their trainings - where a to-do and an announcement lead. */\nexport const MY_TRAININGS_ADDRESS = 'regulations?tab=trainings'\n/** The source an online session's enrolments are asked under (ADR-0194 decision 15) - `<source>:<session id>`. */\nexport const TRAINING_SESSION_SOURCE = 'compliance.training-session'\n\nconst text = (value: unknown) => (typeof value === 'string' && value.trim() ? value.trim() : null)\nconst kindWord = (t: (key: string, options?: any) => string, code: string) => t(`text.training-kind.${code}`)\n\n/* ---------------------------------------------------------------- kinds and people */\n\n/** The request's transaction, or the data source's manager for a query that runs without one. */\nexport function trainingManagerOf(context: any): EntityManager {\n return context?.state?.tx ?? getRepository(TrainingSetting).manager\n}\n\n/** The kinds as the domain has them. */\nexport async function trainingKindsOf(tx: EntityManager, domain: { id: string }): Promise<TrainingKindSet[]> {\n return trainingKindsInDomain(await tx.getRepository(TrainingSetting).find({ where: { domain: { id: domain.id } } as any }))\n}\n\n/** Whom a kind or a session is for - the whole domain when nobody is named. */\nexport function trainingAudiencesOf(kind: TrainingKindSet, domain: { id: string; name?: string }, own?: TrainingTarget[] | null): TrainingTarget[] {\n if (own?.length) return own\n if (kind.audiences.length) return kind.audiences\n return [{ scope: 'DOMAIN', targetId: domain.id, targetName: domain.name }]\n}\n\n/**\n * The people who must take a kind: the employees still working here whose account the kind's audience reaches. One\n * with no account is reached by no audience, as an announcement reaches nobody without one.\n */\nexport async function trainingPeopleOf(tx: EntityManager, domain: any, audiences: TrainingTarget[], today: string): Promise<Employee[]> {\n const userIds = await audienceUserIds(domain, audiences as any, tx)\n if (!userIds.length) return []\n const rows = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, user: { id: In(userIds) } } as any, relations: ['user', 'department'], order: { name: 'ASC' } as any })\n return rows.filter(one => isActiveEmployee(one as any, today))\n}\n\n/** Why the targets of an audience may not be given, or nothing - each names one of this domain's own. */\nasync function audiencesRefusal(tx: EntityManager, domain: any, audiences: TrainingTarget[] | null | undefined): Promise<Refusal | null> {\n if (!audiences?.length) return null\n const departmentIds = [...(await departmentTreeOf(domain, tx)).keys()]\n const roleIds = (await domainRolesOf(domain, undefined, tx)).map(one => one.id)\n for (const target of audiences) {\n const why = audienceTargetRefusal(target, { domainId: domain.id, departmentIds, roleIds })\n if (why) return new Refusal('training-audience-invalid', { target: target.targetName ?? target.targetId }, `${target.targetName ?? target.targetId} is not of this domain (${why})`)\n }\n return null\n}\n\nconst audienceRows = (audiences?: TrainingTarget[] | null) =>\n (audiences ?? []).map(one => ({ scope: one.scope, targetId: one.targetId, ...(one.targetName ? { targetName: String(one.targetName).slice(0, 100) } : {}) }))\n\n/* ---------------------------------------------------------------- who reads */\n\nexport interface TrainingReader {\n /** Holds `training` query - reads every completion and its certificates. */\n all: boolean\n employee: Employee | null\n /** The departments the reader heads, with those under them - read for whether their people are done, nothing more. */\n headed: string[]\n}\n\n/** Who the request is to the trainings. A department head is the employee a department names as its manager. */\nexport async function trainingReaderOf(context: any): Promise<TrainingReader> {\n const { domain } = context.state\n const tx = trainingManagerOf(context)\n const all = await requestHolds(context, 'training', 'query')\n const employee = await workingEmployeeOf(context)\n let headed: string[] = []\n if (employee) {\n const managed = await (tx as EntityManager).getRepository(Department).find({ where: { domain: { id: domain.id }, manager: { id: employee.id } } as any })\n if (managed.length) headed = withDescendants(managed.map(one => one.id), await departmentTreeOf(domain, tx))\n }\n return { all, employee, headed }\n}\n\n/** The reader may read the trainings at all - a holder or an employee; a partner is refused. */\nfunction requireReader(reader: TrainingReader): void {\n if (!reader.all && !reader.employee) throw new Refusal('compliance-employees-only', {}, 'only an employee of this company can do this')\n}\n\n/* ---------------------------------------------------------------- settings */\n\n\n/** A kind's own word - written over the declaration, one row per kind. */\nexport async function saveTrainingSettings(patches: TrainingSettingPatch[], context: any): Promise<TrainingSetting[]> {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingSetting)\n const kinds = await trainingKindsOf(tx, domain)\n const saved: TrainingSetting[] = []\n for (const patch of patches) {\n const refusal = trainingSettingRefusal(patch) ?? (await audiencesRefusal(tx, domain, patch.audiences))\n if (refusal) throw refusal\n const kind = kinds.find(one => one.code === patch.kind)!\n const row: TrainingSetting = (await repository.findOne({ where: { domain: { id: domain.id }, kind: patch.kind } as any })) ?? (repository.create({ domain, kind: patch.kind, enabled: kind.enabled, creator: user } as any) as unknown as TrainingSetting)\n if (patch.enabled !== undefined && patch.enabled !== null) row.enabled = !!patch.enabled\n if (patch.dueDay !== undefined) row.dueDay = text(patch.dueDay)\n if (patch.audiences !== undefined) row.audiences = audienceRows(patch.audiences)\n if (patch.memo !== undefined) row.memo = text(patch.memo)\n row.updater = user\n saved.push(await repository.save(row))\n }\n return saved\n}\n\n/* ---------------------------------------------------------------- sessions */\n\n\n/** Opens a session with its material, and tells its audience - in the same write. */\nexport async function openTrainingSession(input: NewTrainingSession, attach: any[] | undefined, context: any): Promise<TrainingSession> {\n const { domain, user, tx } = context.state\n const kind = (await trainingKindsOf(tx, domain)).find(one => one.code === input.kind)\n const refusal = trainingSessionRefusal(input, kind) ?? (await audiencesRefusal(tx, domain, input.audiences))\n if (refusal) throw refusal\n\n const saved = await (tx as EntityManager).getRepository(TrainingSession).save({\n domain,\n kind: input.kind,\n year: input.year,\n name: input.name.trim(),\n method: input.method as TrainingMethod,\n startsOn: input.startsOn,\n endsOn: text(input.endsOn),\n instructor: text(input.instructor),\n organisation: text(input.organisation),\n audiences: audienceRows(input.audiences),\n course: input.method === TrainingMethod.ONLINE && input.courseId ? { id: input.courseId } : null,\n notes: text(input.notes),\n creator: user,\n updater: user\n } as any)\n for (const file of attach ?? []) await createAttachment(null, { attachment: { file, refType: TRAINING_SESSION_REF_TYPE, refBy: saved.id } } as any, context)\n if (saved.method === TrainingMethod.ONLINE) await enrollOnlineSession(saved, kind!, context)\n\n const t = context.t ?? ((key: string) => key)\n const when = saved.endsOn && saved.endsOn !== saved.startsOn ? `${saved.startsOn} ~ ${saved.endsOn}` : saved.startsOn\n await announce(context, {\n trigger: TRAINING_SCHEDULED_TRIGGER,\n sourceKind: TRAINING_SESSION_REF_TYPE,\n sourceId: saved.id,\n title: `${kindWord(t, saved.kind)} · ${saved.name}`,\n body: [\n `${t('field.training-session-when')}: ${when}`,\n `${t('field.training-method')}: ${t(`text.training-method.${saved.method}`)}`,\n ...(saved.instructor ? [`${t('field.training-instructor')}: ${saved.instructor}`] : []),\n ...(saved.organisation ? [`${t('field.training-organisation')}: ${saved.organisation}`] : [])\n ].join('\\n'),\n links: [{ label: t('title.training-my-trainings'), url: MY_TRAININGS_ADDRESS }],\n audiences: trainingAudiencesOf(kind!, domain, saved.audiences) as any\n })\n return saved\n}\n\n\n/**\n * Opens an online session to its audience (ADR-0194 decision 15): each person still working here is enrolled in the\n * session's course, due by its last day (the kind's due day when it has none). The session's to-do is the enrolment's -\n * so the year's to-do a person was handed for the kind is closed, to leave one.\n */\nasync function enrollOnlineSession(session: TrainingSession, kind: TrainingKindSet, context: any): Promise<void> {\n const { domain, user, tx } = context.state\n const people = (await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind, domain, session.audiences), todayIn(domain))).filter(one => one.user)\n const courseId = (session as any).course?.id ?? session.courseId\n await enroll({ kind: TRAINING_SESSION_SOURCE, id: session.id }, people.map(one => one.user!.id), courseId, onlineDueOnOf(session, kind.dueDay), context)\n const repository = (tx as EntityManager).getRepository(TrainingAssignment)\n for (const person of people) {\n const assignment = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: person.id }, kind: session.kind, year: session.year } as any })\n if (!assignment?.todoInstanceId || assignment.closedAt) continue\n await closeLegalTodo(tx, domain, assignment.todoInstanceId, user, '온라인 회차 수강')\n assignment.todoInstanceId = null\n assignment.updater = user\n await repository.save(assignment)\n }\n}\n\n/** The people of a kind and year who hold an open enrolment of an online session - their to-do is that enrolment's. */\nasync function onlineLearnersOf(tx: EntityManager, domain: { id: string }, kind: string, year: number): Promise<Set<string>> {\n const sessions = await tx.getRepository(TrainingSession).find({ where: { domain: { id: domain.id }, kind, year, method: TrainingMethod.ONLINE } as any })\n if (!sessions.length) return new Set()\n const open = await tx.getRepository(Enrollment).find({\n where: { domain: { id: domain.id }, sourceKind: TRAINING_SESSION_SOURCE, sourceId: In(sessions.map(one => one.id)), status: In([EnrollmentStatus.ASSIGNED, EnrollmentStatus.IN_PROGRESS]) } as any\n })\n return new Set(open.map(one => one.userId!))\n}\n\n/** What a session says may be corrected - its kind and year stay, the completions of it count for them. */\nexport async function updateTrainingSessions(patches: TrainingSessionPatch[], context: any): Promise<TrainingSession[]> {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingSession)\n const kinds = await trainingKindsOf(tx, domain)\n const saved: TrainingSession[] = []\n for (const patch of patches) {\n const row = await repository.findOne({ where: { id: patch.id, domain: { id: domain.id } } as any })\n if (!row) throw new Refusal('training-not-found', {}, 'the record was not found. reload and try again.')\n /* An online session's people are enrolled in its course - it stays online (ADR-0194 decision 15). */\n if (patch.method !== undefined && patch.method !== row.method && (row.method === TrainingMethod.ONLINE || patch.method === TrainingMethod.ONLINE))\n throw new Refusal('training-online-method-fixed', {}, 'an online session stays online, and another stays as it is - open a new session instead')\n for (const field of ['name', 'method', 'startsOn', 'endsOn', 'instructor', 'organisation', 'notes'] as const)\n if (patch[field] !== undefined) (row as any)[field] = field === 'name' || field === 'method' || field === 'startsOn' ? (patch[field] ?? '').trim() : text(patch[field])\n /* An earlier session of a kind turned off since is still corrected - only what it says is asked. */\n const refusal = trainingSessionRefusal({ ...row, courseId: row.courseId }, { ...kinds.find(one => one.code === row.kind)!, enabled: true })\n if (refusal) throw refusal\n row.updater = user\n saved.push(await repository.save(row))\n }\n return saved\n}\n\n/* ---------------------------------------------------------------- completions */\n\nasync function completionsOf(tx: EntityManager, domain: { id: string }, employeeId: string, kind: string, year: number) {\n return await tx.getRepository(TrainingCompletion).find({ where: { domain: { id: domain.id }, employee: { id: employeeId }, kind, year } as any })\n}\n\n/** A confirmed completion closes the person's to-do of the kind and year, once. */\nasync function closeTodoOf(tx: EntityManager, domain: any, employeeId: string, kind: string, year: number, by: User): Promise<void> {\n const repository = tx.getRepository(TrainingAssignment)\n const assignment = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: employeeId }, kind, year } as any })\n if (!assignment?.todoInstanceId || assignment.closedAt) return\n await closeLegalTodo(tx, domain, assignment.todoInstanceId, by, '이수 확인')\n assignment.closedAt = new Date()\n assignment.updater = by\n await repository.save(assignment)\n}\n\n/**\n * The attendance of a session, recorded by the manager - confirmed at once. Someone already done for the kind and year\n * is left as they are.\n */\nexport async function recordTrainingAttendance(sessionId: string, employeeIds: string[], completedOn: string | null | undefined, context: any): Promise<TrainingCompletion[]> {\n const { domain, user, tx } = context.state\n const session = await (tx as EntityManager).getRepository(TrainingSession).findOne({ where: { id: sessionId, domain: { id: domain.id } } as any })\n if (!session) throw new Refusal('training-not-found', {}, 'the record was not found. reload and try again.')\n const day = text(completedOn) ?? session.endsOn ?? session.startsOn\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(day) || day < session.startsOn) throw new Refusal('training-attendance-day-invalid', { startsOn: session.startsOn }, `the day attended is on or after ${session.startsOn}, YYYY-MM-DD`)\n if (!employeeIds.length) throw new Refusal('training-attendees-required', {}, 'pick the people who attended')\n\n const today = todayIn(domain)\n const employees = await (tx as EntityManager).getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(employeeIds) } as any })\n const repository = (tx as EntityManager).getRepository(TrainingCompletion)\n const written: TrainingCompletion[] = []\n for (const id of new Set(employeeIds)) {\n const employee = employees.find(one => one.id === id)\n if (!employee || !isActiveEmployee(employee as any, today)) throw new Refusal('training-employee-unknown', {}, 'an attendee must be an employee working in this domain')\n if (trainingStateOf(await completionsOf(tx, domain, id, session.kind, session.year)) === 'DONE') continue\n written.push(\n await repository.save({\n domain,\n employee,\n kind: session.kind,\n year: session.year,\n session,\n completedOn: day,\n method: session.method,\n organisation: session.organisation,\n status: TrainingCompletionStatus.CONFIRMED,\n decidedAt: new Date(),\n decidedBy: user,\n creator: user,\n updater: user\n } as any)\n )\n await closeTodoOf(tx, domain, id, session.kind, session.year, user)\n }\n return written\n}\n\n\n/** A certificate the person sends for themself - waiting until the manager confirms it. */\nexport async function submitTrainingCertificate(input: TrainingCertificateInput, attach: any[] | undefined, context: any): Promise<TrainingCompletion> {\n const { domain, user, tx } = context.state\n const employee = await workingEmployeeOf(context)\n if (!employee) throw new Refusal('compliance-employees-only', {}, 'only an employee of this company can do this')\n const kind = (await trainingKindsOf(tx, domain)).find(one => one.code === input.kind)\n const refusal = trainingCertificateRefusal(input, kind, todayIn(domain), attach?.length ?? 0, await completionsOf(tx, domain, employee.id, input.kind, input.year))\n if (refusal) throw refusal\n const session = input.sessionId ? await (tx as EntityManager).getRepository(TrainingSession).findOne({ where: { id: input.sessionId, domain: { id: domain.id }, kind: input.kind, year: input.year } as any }) : null\n if (input.sessionId && !session) throw new Refusal('training-session-unknown', {}, 'the session must be one of this kind and year')\n\n const saved = await (tx as EntityManager).getRepository(TrainingCompletion).save({\n domain,\n employee,\n kind: input.kind,\n year: input.year,\n session,\n completedOn: input.completedOn,\n method: input.method as TrainingMethod,\n organisation: text(input.organisation),\n status: TrainingCompletionStatus.SUBMITTED,\n creator: user,\n updater: user\n } as any)\n for (const file of attach ?? []) await createAttachment(null, { attachment: { file, refType: TRAINING_COMPLETION_REF_TYPE, refBy: saved.id } } as any, context)\n return saved\n}\n\n/** The manager confirms certificates sent - each closes the person's to-do. */\nexport async function confirmTrainingCompletions(ids: string[], context: any): Promise<TrainingCompletion[]> {\n return await decide(ids, TrainingCompletionStatus.CONFIRMED, null, context)\n}\n\n/** The manager returns a certificate, saying why - the person sends another. */\nexport async function returnTrainingCompletion(id: string, reason: string, context: any): Promise<TrainingCompletion> {\n return (await decide([id], TrainingCompletionStatus.RETURNED, reason, context))[0]\n}\n\nasync function decide(ids: string[], decision: TrainingCompletionStatus.CONFIRMED | TrainingCompletionStatus.RETURNED, reason: string | null, context: any) {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingCompletion)\n const saved: TrainingCompletion[] = []\n for (const id of ids) {\n const row = await repository.findOne({ where: { id, domain: { id: domain.id } } as any })\n if (!row) throw new Refusal('training-not-found', {}, 'the record was not found. reload and try again.')\n const refusal = trainingDecisionRefusal(row.status, decision, reason)\n if (refusal) throw refusal\n row.status = decision\n row.returnReason = decision === TrainingCompletionStatus.RETURNED ? reason!.trim() : null\n row.decidedAt = new Date()\n row.decidedBy = user\n row.updater = user\n saved.push(await repository.save(row))\n if (decision === TrainingCompletionStatus.CONFIRMED) await closeTodoOf(tx, domain, row.employeeId!, row.kind, row.year, user)\n }\n return saved\n}\n\n/** Training records are kept (decision 17) - every delete is refused with what to do instead. */\nexport async function deleteTrainingRecords(): Promise<never> {\n throw trainingDeletionRefusal()\n}\n\n/* ---------------------------------------------------------------- the year's to-dos */\n\nexport interface TrainingYearOpening {\n people: number\n done: number\n handedOut: number\n}\n\n/**\n * Opens a kind's year: a worklist to-do 「<교육> 이수」 with the due day for everyone of its audience not done - at most\n * one per person, kind and year, so opening it again hands out only to those it missed (a person who joined since, a\n * to-do the domain could not hand out before).\n */\nexport async function openTrainingYear(kindCode: string, year: number, context: any): Promise<TrainingYearOpening> {\n const { domain, user, tx } = context.state\n const kind = (await trainingKindsOf(tx, domain)).find(one => one.code === kindCode)\n const refusal = trainingSessionRefusal({ kind: kindCode, year, name: '-', method: 'POSTED', startsOn: `${year}-01-01` }, kind)\n if (refusal) throw refusal\n\n const today = todayIn(domain)\n const dueOn = trainingDueOnOf(year, kind!.dueDay)\n const people = await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind!, domain), today)\n const repository = (tx as EntityManager).getRepository(TrainingAssignment)\n const done = new Set(\n (await (tx as EntityManager).getRepository(TrainingCompletion).find({ where: { domain: { id: domain.id }, kind: kindCode, year, status: TrainingCompletionStatus.CONFIRMED } as any })).map(one => one.employeeId)\n )\n /* Someone enrolled in an online session of the kind has that enrolment's to-do - none twice. */\n const online = await onlineLearnersOf(tx, domain, kindCode, year)\n let handedOut = 0\n for (const person of people) {\n if (done.has(person.id) || !person.user || online.has(person.user.id)) continue\n const assignment =\n (await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: person.id }, kind: kindCode, year } as any })) ??\n (await repository.save({ domain, employee: person, kind: kindCode, year, dueOn, creator: user, updater: user } as any))\n if (assignment.todoInstanceId) continue\n const t = translatorFor(person.user.locale || 'ko')\n const id = await issueLegalTodo(tx, domain, {\n assignee: person.user,\n name: t('text.training-todo-name', { kind: kindWord(t, kindCode), year }),\n headline: t('text.training-todo-headline', { dueOn }),\n address: MY_TRAININGS_ADDRESS,\n subjectKind: 'TrainingAssignment',\n subjectId: assignment.id,\n dueAt: trainingDueAt(dueOn, domain.timezone)\n })\n if (!id) continue\n assignment.todoInstanceId = id\n assignment.updater = user\n await repository.save(assignment)\n handedOut++\n }\n return { people: people.length, done: people.filter(one => done.has(one.id)).length, handedOut }\n}\n\n/* ---------------------------------------------------------------- online completions (ADR-0194 decision 16) */\n\nconst dayIn = (at: Date | string, timezone?: string | null) =>\n new Intl.DateTimeFormat('en-CA', { timeZone: timezone || 'UTC', year: 'numeric', month: '2-digit', day: '2-digit' }).format(new Date(at))\n\n/**\n * An enrolment of an online session completed: a confirmed completion of the session's kind and year, with the\n * learning module's evidence - no manager's confirmation needed. Runs in the completion's transaction: what fails here\n * takes the completion back. Someone done already for the kind and year is left as they are.\n */\nexport async function recordOnlineCompletion(enrollment: Enrollment, context: any): Promise<TrainingCompletion | null> {\n const { domain, tx } = context.state\n const session = await (tx as EntityManager).getRepository(TrainingSession).findOne({ where: { id: enrollment.sourceId, domain: { id: domain.id } } as any })\n if (!session) throw new Refusal('training-not-found', {}, 'the session of this enrolment was not found')\n const employee = await (tx as EntityManager).getRepository(Employee).findOne({ where: { domain: { id: domain.id }, user: { id: enrollment.userId } } as any })\n if (!employee) throw new Refusal('training-employee-unknown', {}, 'the learner must be an employee working in this domain')\n if (trainingStateOf(await completionsOf(tx, domain, employee.id, session.kind, session.year)) === 'DONE') return null\n const version = enrollment.versionId ? await (tx as EntityManager).getRepository(CourseVersion).findOne({ where: { id: enrollment.versionId } as any, withDeleted: true }) : null\n const saved = await (tx as EntityManager).getRepository(TrainingCompletion).save({\n domain,\n employee,\n kind: session.kind,\n year: session.year,\n session,\n completedOn: dayIn(enrollment.completedAt ?? new Date(), domain.timezone),\n method: TrainingMethod.ONLINE,\n status: TrainingCompletionStatus.CONFIRMED,\n decidedAt: new Date(),\n learningEnrollmentId: enrollment.id,\n learningEvidence: {\n minutes: Math.floor((enrollment.learnedSeconds ?? 0) / 60),\n score: enrollment.score ?? null,\n attempts: enrollment.attempts ?? 0,\n acknowledgedAt: enrollment.acknowledgedAt ?? null,\n version: version?.number ?? null,\n certificateNo: enrollment.certificateNo ?? null\n },\n creator: context.state.user,\n updater: context.state.user\n } as any)\n await closeTodoOf(tx, domain, employee.id, session.kind, session.year, context.state.user)\n return saved\n}\n\n/** A completed enrolment a manager cancelled: the completion made from it is returned with the reason - kept, not deleted. */\nexport async function returnOnlineCompletion(enrollment: Enrollment, reason: string, context: any): Promise<void> {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingCompletion)\n const row = await repository.findOne({ where: { domain: { id: domain.id }, learningEnrollmentId: enrollment.id } as any })\n if (!row || row.status !== TrainingCompletionStatus.CONFIRMED) return\n row.status = TrainingCompletionStatus.RETURNED\n row.returnReason = reason\n row.decidedAt = new Date()\n row.decidedBy = user\n row.updater = user\n await repository.save(row)\n}\n\n/* ---------------------------------------------------------------- where each person stands */\n\nexport interface TrainingStandingRow {\n id: string\n kind: string\n year: number\n dueOn: string\n state: TrainingState\n completedOn?: string | null\n employee: Employee\n departmentName?: string | null\n}\n\n/** Where everyone of every kind on stands in a year - the people of each kind's audience, by name. */\nexport async function standingsOf(tx: EntityManager, domain: any, year: number, today: string): Promise<TrainingStandingRow[]> {\n const kinds = (await trainingKindsOf(tx, domain)).filter(one => one.enabled)\n const completions = await tx.getRepository(TrainingCompletion).find({ where: { domain: { id: domain.id }, year } as any })\n const rows: TrainingStandingRow[] = []\n for (const kind of kinds) {\n const dueOn = trainingDueOnOf(year, kind.dueDay)\n for (const employee of await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind, domain), today)) {\n const mine = completions.filter(one => one.kind === kind.code && one.employeeId === employee.id)\n const state = trainingStateOf(mine)\n rows.push({\n id: `${kind.code}:${year}:${employee.id}`,\n kind: kind.code,\n year,\n dueOn,\n state,\n completedOn: state === 'DONE' ? mine.filter(one => one.status === 'CONFIRMED').map(one => one.completedOn).sort()[0] : null,\n employee,\n departmentName: employee.department?.name ?? null\n })\n }\n }\n return rows\n}\n\n/**\n * The standings the reader may read: a holder all of them; an employee their own; a department head also whether each\n * of their people is done - no day, no waiting certificate, nothing of its content.\n */\nexport async function readableStandings(year: number, context: any): Promise<TrainingStandingRow[]> {\n const { domain } = context.state\n const tx = trainingManagerOf(context)\n const reader = await trainingReaderOf(context)\n requireReader(reader)\n const rows = await standingsOf(tx, domain, year, todayIn(domain))\n if (reader.all) return rows\n return rows\n .filter(row => row.employee.id === reader.employee!.id || (row.employee.departmentId && reader.headed.includes(row.employee.departmentId)))\n .map(row => (row.employee.id === reader.employee!.id ? row : { ...row, state: row.state === 'DONE' ? 'DONE' : 'NOT_DONE', completedOn: null }))\n}\n\nexport interface MyTrainingRow {\n kind: string\n year: number\n dueOn: string\n state: TrainingState\n completion?: TrainingCompletion | null\n sessions: TrainingSession[]\n}\n\n/** The request's employee's trainings of a year: each kind on whose audience they are in, with its sessions. */\nexport async function myTrainings(year: number, context: any): Promise<MyTrainingRow[]> {\n const { domain } = context.state\n const tx = trainingManagerOf(context)\n const employee = await workingEmployeeOf(context)\n if (!employee) throw new Refusal('compliance-employees-only', {}, 'only an employee of this company can do this')\n const today = todayIn(domain)\n const kinds = (await trainingKindsOf(tx, domain)).filter(one => one.enabled)\n const sessions = await (tx as EntityManager).getRepository(TrainingSession).find({ where: { domain: { id: domain.id }, year } as any, order: { startsOn: 'ASC' } as any })\n const out: MyTrainingRow[] = []\n for (const kind of kinds) {\n if (!(await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind, domain), today)).some(one => one.id === employee.id)) continue\n const mine = (await completionsOf(tx, domain, employee.id, kind.code, year)).sort((a, b) => +new Date(b.createdAt!) - +new Date(a.createdAt!))\n const state = trainingStateOf(mine)\n out.push({\n kind: kind.code,\n year,\n dueOn: trainingDueOnOf(year, kind.dueDay),\n state,\n completion: (state === 'DONE' ? mine.find(one => one.status === 'CONFIRMED') : mine[0]) ?? null,\n sessions: sessions.filter(one => one.kind === kind.code)\n })\n }\n return out\n}\n\n/** Whether the request may read a completion - a holder, or the one it is of. A department head may not. */\nexport async function mayReadCompletion(row: { employeeId?: string | null } | null, context: any): Promise<boolean> {\n if (!row) return false\n if (await requestHolds(context, 'training', 'query')) return true\n const employee = await workingEmployeeOf(context)\n return !!employee && employee.id === row.employeeId\n}\n\n/** Whether the request may read a session's material - a holder, or an employee it is for. */\nexport async function mayReadSession(row: TrainingSession | null, context: any): Promise<boolean> {\n if (!row) return false\n if (await requestHolds(context, 'training', 'query')) return true\n const { domain } = context.state\n const employee = await workingEmployeeOf(context)\n if (!employee) return false\n const manager = trainingManagerOf(context)\n const kind = (await trainingKindsOf(manager, domain)).find(one => one.code === row.kind)\n if (!kind) return false\n return (await trainingPeopleOf(manager, domain, trainingAudiencesOf(kind, domain, row.audiences), todayIn(domain))).some(one => one.id === employee.id)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"training-service.js","sourceRoot":"","sources":["../../../server/service/training/training-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager, In } from 'typeorm'\n\nimport { announce } from '@things-factory/announcement'\nimport { createAttachment } from '@things-factory/attachment-base'\nimport { requestHolds, User } from '@things-factory/auth-base'\nimport { translatorFor } from '@things-factory/i18n-base/translator'\nimport { audienceTargetRefusal, audienceUserIds, Department, departmentTreeOf, domainRolesOf, Employee, withDescendants } from '@things-factory/organization'\nimport { isActiveEmployee } from '@things-factory/organization/dist-server/service/employee-profile/employee-profile-rules.js'\nimport { CourseVersion, enroll, Enrollment, EnrollmentStatus } from '@things-factory/learning'\nimport { getRepository, Refusal } from '@things-factory/shell'\n\nimport { todayIn, workingEmployeeOf } from '../common/employee-reader'\nimport { closeLegalTodo, issueLegalTodo } from '../common/legal-todo'\nimport { TrainingAssignment, TrainingCompletion, TrainingCompletionStatus, TrainingMethod, TrainingSession, TrainingSetting } from './training'\nimport {\n onlineDueOnOf,\n TrainingTarget,\n trainingCertificateRefusal,\n trainingDecisionRefusal,\n trainingDeletionRefusal,\n trainingDueOnOf,\n trainingDueAt,\n TrainingKindSet,\n trainingKindsInDomain,\n trainingSessionRefusal,\n trainingSettingRefusal,\n trainingStateOf,\n TrainingState\n} from './training-rules'\nimport { NewTrainingSession, TrainingCertificateInput, TrainingSessionPatch, TrainingSettingPatch } from './training-type'\n\n/*\n * The mandatory trainings of a domain (ADR-0187 decisions 15-19): a kind's setting, a session opened and told, the\n * attendance and certificates that complete it, the to-dos of a year, and who reads where each person stands. Nothing\n * here deletes a training record.\n */\n\nexport const TRAINING_SESSION_REF_TYPE = 'TrainingSession'\nexport const TRAINING_COMPLETION_REF_TYPE = 'TrainingCompletion'\nexport const TRAINING_SCHEDULED_TRIGGER = 'compliance.training-scheduled'\n/** The employee's screen of their trainings - where a to-do and an announcement lead. */\nexport const MY_TRAININGS_ADDRESS = 'regulations?tab=trainings'\n/** The source an online session's enrolments are asked under (ADR-0194 decision 15) - `<source>:<session id>`. */\nexport const TRAINING_SESSION_SOURCE = 'compliance.training-session'\n\nconst text = (value: unknown) => (typeof value === 'string' && value.trim() ? value.trim() : null)\nconst kindWord = (t: (key: string, options?: any) => string, code: string) => t(`text.training-kind.${code}`)\n\n/* ---------------------------------------------------------------- kinds and people */\n\n/** The request's transaction, or the data source's manager for a query that runs without one. */\nexport function trainingManagerOf(context: any): EntityManager {\n return context?.state?.tx ?? getRepository(TrainingSetting).manager\n}\n\n/** The kinds as the domain has them. */\nexport async function trainingKindsOf(tx: EntityManager, domain: { id: string }): Promise<TrainingKindSet[]> {\n return trainingKindsInDomain(await tx.getRepository(TrainingSetting).find({ where: { domain: { id: domain.id } } as any }))\n}\n\n/** Whom a kind or a session is for - the whole domain when nobody is named. */\nexport function trainingAudiencesOf(kind: TrainingKindSet, domain: { id: string; name?: string }, own?: TrainingTarget[] | null): TrainingTarget[] {\n if (own?.length) return own\n if (kind.audiences.length) return kind.audiences\n return [{ scope: 'DOMAIN', targetId: domain.id, targetName: domain.name }]\n}\n\n/**\n * The people who must take a kind: the employees still working here whose account the kind's audience reaches. One\n * with no account is reached by no audience, as an announcement reaches nobody without one.\n */\nexport async function trainingPeopleOf(tx: EntityManager, domain: any, audiences: TrainingTarget[], today: string): Promise<Employee[]> {\n const userIds = await audienceUserIds(domain, audiences as any, tx)\n if (!userIds.length) return []\n const rows = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, user: { id: In(userIds) } } as any, relations: ['user', 'department'], order: { name: 'ASC' } as any })\n return rows.filter(one => isActiveEmployee(one as any, today))\n}\n\n/** Why the targets of an audience may not be given, or nothing - each names one of this domain's own. */\nasync function audiencesRefusal(tx: EntityManager, domain: any, audiences: TrainingTarget[] | null | undefined): Promise<Refusal | null> {\n if (!audiences?.length) return null\n const departmentIds = [...(await departmentTreeOf(domain, tx)).keys()]\n const roleIds = (await domainRolesOf(domain, undefined, tx)).map(one => one.id)\n for (const target of audiences) {\n const why = audienceTargetRefusal(target, { domainId: domain.id, departmentIds, roleIds })\n if (why) return new Refusal('training-audience-invalid', { target: target.targetName ?? target.targetId }, `${target.targetName ?? target.targetId} is not of this domain (${why})`)\n }\n return null\n}\n\nconst audienceRows = (audiences?: TrainingTarget[] | null) =>\n (audiences ?? []).map(one => ({ scope: one.scope, targetId: one.targetId, ...(one.targetName ? { targetName: String(one.targetName).slice(0, 100) } : {}) }))\n\n/* ---------------------------------------------------------------- who reads */\n\nexport interface TrainingReader {\n /** Holds `training` query - reads every completion and its certificates. */\n all: boolean\n employee: Employee | null\n /** The departments the reader heads, with those under them - read for whether their people are done, nothing more. */\n headed: string[]\n}\n\n/** Who the request is to the trainings. A department head is the employee a department names as its manager. */\nexport async function trainingReaderOf(context: any): Promise<TrainingReader> {\n const { domain } = context.state\n const tx = trainingManagerOf(context)\n const all = await requestHolds(context, 'training', 'query')\n const employee = await workingEmployeeOf(context)\n let headed: string[] = []\n if (employee) {\n const managed = await (tx as EntityManager).getRepository(Department).find({ where: { domain: { id: domain.id }, manager: { id: employee.id } } as any })\n if (managed.length) headed = withDescendants(managed.map(one => one.id), await departmentTreeOf(domain, tx))\n }\n return { all, employee, headed }\n}\n\n/** The reader may read the trainings at all - a holder or an employee; a partner is refused. */\nfunction requireReader(reader: TrainingReader): void {\n if (!reader.all && !reader.employee) throw new Refusal('compliance-employees-only', {}, 'only an employee of this company can do this')\n}\n\n/* ---------------------------------------------------------------- settings */\n\n\n/** A kind's own word - written over the declaration, one row per kind. */\nexport async function saveTrainingSettings(patches: TrainingSettingPatch[], context: any): Promise<TrainingSetting[]> {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingSetting)\n const kinds = await trainingKindsOf(tx, domain)\n const saved: TrainingSetting[] = []\n for (const patch of patches) {\n const refusal = trainingSettingRefusal(patch) ?? (await audiencesRefusal(tx, domain, patch.audiences))\n if (refusal) throw refusal\n const kind = kinds.find(one => one.code === patch.kind)!\n const row: TrainingSetting = (await repository.findOne({ where: { domain: { id: domain.id }, kind: patch.kind } as any })) ?? (repository.create({ domain, kind: patch.kind, enabled: kind.enabled, creator: user } as any) as unknown as TrainingSetting)\n if (patch.enabled !== undefined && patch.enabled !== null) row.enabled = !!patch.enabled\n if (patch.dueDay !== undefined) row.dueDay = text(patch.dueDay)\n if (patch.audiences !== undefined) row.audiences = audienceRows(patch.audiences)\n if (patch.memo !== undefined) row.memo = text(patch.memo)\n row.updater = user\n saved.push(await repository.save(row))\n }\n return saved\n}\n\n/* ---------------------------------------------------------------- sessions */\n\n\n/** Opens a session with its material, and tells its audience - in the same write. */\nexport async function openTrainingSession(input: NewTrainingSession, attach: any[] | undefined, context: any): Promise<TrainingSession> {\n const { domain, user, tx } = context.state\n const kind = (await trainingKindsOf(tx, domain)).find(one => one.code === input.kind)\n const refusal = trainingSessionRefusal(input, kind) ?? (await audiencesRefusal(tx, domain, input.audiences))\n if (refusal) throw refusal\n\n const saved = await (tx as EntityManager).getRepository(TrainingSession).save({\n domain,\n kind: input.kind,\n year: input.year,\n name: input.name.trim(),\n method: input.method as TrainingMethod,\n startsOn: input.startsOn,\n endsOn: text(input.endsOn),\n instructor: text(input.instructor),\n organisation: text(input.organisation),\n audiences: audienceRows(input.audiences),\n course: input.method === TrainingMethod.ONLINE && input.courseId ? { id: input.courseId } : null,\n notes: text(input.notes),\n creator: user,\n updater: user\n } as any)\n for (const file of attach ?? []) await createAttachment(null, { attachment: { file, refType: TRAINING_SESSION_REF_TYPE, refBy: saved.id } } as any, context)\n if (saved.method === TrainingMethod.ONLINE) await enrollOnlineSession(saved, kind!, context)\n\n const t = context.t ?? ((key: string) => key)\n const when = saved.endsOn && saved.endsOn !== saved.startsOn ? `${saved.startsOn} ~ ${saved.endsOn}` : saved.startsOn\n await announce(context, {\n trigger: TRAINING_SCHEDULED_TRIGGER,\n sourceKind: TRAINING_SESSION_REF_TYPE,\n sourceId: saved.id,\n title: `${kindWord(t, saved.kind)} · ${saved.name}`,\n body: [\n `${t('field.training-session-when')}: ${when}`,\n `${t('field.training-method')}: ${t(`text.training-method.${saved.method}`)}`,\n ...(saved.instructor ? [`${t('field.training-instructor')}: ${saved.instructor}`] : []),\n ...(saved.organisation ? [`${t('field.training-organisation')}: ${saved.organisation}`] : [])\n ].join('\\n'),\n links: [{ label: t('title.training-my-trainings'), url: MY_TRAININGS_ADDRESS }],\n audiences: trainingAudiencesOf(kind!, domain, saved.audiences) as any\n })\n return saved\n}\n\n\n/**\n * Opens an online session to its audience (ADR-0194 decision 15): each person still working here is enrolled in the\n * session's course, due by its last day (the kind's due day when it has none). The session's to-do is the enrolment's -\n * so the year's to-do a person was handed for the kind is closed, to leave one.\n */\nasync function enrollOnlineSession(session: TrainingSession, kind: TrainingKindSet, context: any): Promise<void> {\n const { domain, user, tx } = context.state\n const people = (await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind, domain, session.audiences), todayIn(domain))).filter(one => one.user)\n const courseId = (session as any).course?.id ?? session.courseId\n await enroll({ kind: TRAINING_SESSION_SOURCE, id: session.id }, people.map(one => one.user!.id), courseId, onlineDueOnOf(session, kind.dueDay), context)\n const repository = (tx as EntityManager).getRepository(TrainingAssignment)\n for (const person of people) {\n const assignment = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: person.id }, kind: session.kind, year: session.year } as any })\n if (!assignment?.todoInstanceId || assignment.closedAt) continue\n await closeLegalTodo(tx, domain, assignment.todoInstanceId, user, '온라인 회차 수강')\n assignment.todoInstanceId = null\n assignment.updater = user\n await repository.save(assignment)\n }\n}\n\n/** The people of a kind and year who hold an open enrolment of an online session - their to-do is that enrolment's. */\nasync function onlineLearnersOf(tx: EntityManager, domain: { id: string }, kind: string, year: number): Promise<Set<string>> {\n const sessions = await tx.getRepository(TrainingSession).find({ where: { domain: { id: domain.id }, kind, year, method: TrainingMethod.ONLINE } as any })\n if (!sessions.length) return new Set()\n const open = await tx.getRepository(Enrollment).find({\n where: { domain: { id: domain.id }, sourceKind: TRAINING_SESSION_SOURCE, sourceId: In(sessions.map(one => one.id)), status: In([EnrollmentStatus.ASSIGNED, EnrollmentStatus.IN_PROGRESS]) } as any\n })\n return new Set(open.map(one => one.userId!))\n}\n\n/** What a session says may be corrected - its kind and year stay, the completions of it count for them. */\nexport async function updateTrainingSessions(patches: TrainingSessionPatch[], context: any): Promise<TrainingSession[]> {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingSession)\n const kinds = await trainingKindsOf(tx, domain)\n const saved: TrainingSession[] = []\n for (const patch of patches) {\n const row = await repository.findOne({ where: { id: patch.id, domain: { id: domain.id } } as any })\n if (!row) throw new Refusal('training-not-found', {}, 'the record was not found. reload and try again.')\n /* An online session's people are enrolled in its course - it stays online (ADR-0194 decision 15). */\n if (patch.method !== undefined && patch.method !== row.method && (row.method === TrainingMethod.ONLINE || patch.method === TrainingMethod.ONLINE))\n throw new Refusal('training-online-method-fixed', {}, 'an online session stays online, and another stays as it is - open a new session instead')\n for (const field of ['name', 'method', 'startsOn', 'endsOn', 'instructor', 'organisation', 'notes'] as const)\n if (patch[field] !== undefined) (row as any)[field] = field === 'name' || field === 'method' || field === 'startsOn' ? (patch[field] ?? '').trim() : text(patch[field])\n /* An earlier session of a kind turned off since is still corrected - only what it says is asked. */\n const refusal = trainingSessionRefusal({ ...row, courseId: row.courseId }, { ...kinds.find(one => one.code === row.kind)!, enabled: true })\n if (refusal) throw refusal\n row.updater = user\n saved.push(await repository.save(row))\n }\n return saved\n}\n\n/* ---------------------------------------------------------------- completions */\n\nasync function completionsOf(tx: EntityManager, domain: { id: string }, employeeId: string, kind: string, year: number) {\n return await tx.getRepository(TrainingCompletion).find({ where: { domain: { id: domain.id }, employee: { id: employeeId }, kind, year } as any })\n}\n\n/** A confirmed completion closes the person's to-do of the kind and year, once. */\nasync function closeTodoOf(tx: EntityManager, domain: any, employeeId: string, kind: string, year: number, by: User): Promise<void> {\n const repository = tx.getRepository(TrainingAssignment)\n const assignment = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: employeeId }, kind, year } as any })\n if (!assignment?.todoInstanceId || assignment.closedAt) return\n await closeLegalTodo(tx, domain, assignment.todoInstanceId, by, '이수 확인')\n assignment.closedAt = new Date()\n assignment.updater = by\n await repository.save(assignment)\n}\n\n/**\n * The attendance of a session, recorded by the manager - confirmed at once. Someone already done for the kind and year\n * is left as they are.\n */\nexport async function recordTrainingAttendance(sessionId: string, employeeIds: string[], completedOn: string | null | undefined, context: any): Promise<TrainingCompletion[]> {\n const { domain, user, tx } = context.state\n const session = await (tx as EntityManager).getRepository(TrainingSession).findOne({ where: { id: sessionId, domain: { id: domain.id } } as any })\n if (!session) throw new Refusal('training-not-found', {}, 'the record was not found. reload and try again.')\n const day = text(completedOn) ?? session.endsOn ?? session.startsOn\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(day) || day < session.startsOn) throw new Refusal('training-attendance-day-invalid', { startsOn: session.startsOn }, `the day attended is on or after ${session.startsOn}, YYYY-MM-DD`)\n if (!employeeIds.length) throw new Refusal('training-attendees-required', {}, 'pick the people who attended')\n\n const today = todayIn(domain)\n const employees = await (tx as EntityManager).getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(employeeIds) } as any })\n const repository = (tx as EntityManager).getRepository(TrainingCompletion)\n const written: TrainingCompletion[] = []\n for (const id of new Set(employeeIds)) {\n const employee = employees.find(one => one.id === id)\n if (!employee || !isActiveEmployee(employee as any, today)) throw new Refusal('training-employee-unknown', {}, 'an attendee must be an employee working in this domain')\n if (trainingStateOf(await completionsOf(tx, domain, id, session.kind, session.year)) === 'DONE') continue\n written.push(\n await repository.save({\n domain,\n employee,\n kind: session.kind,\n year: session.year,\n session,\n completedOn: day,\n method: session.method,\n organisation: session.organisation,\n status: TrainingCompletionStatus.CONFIRMED,\n decidedAt: new Date(),\n decidedBy: user,\n creator: user,\n updater: user\n } as any)\n )\n await closeTodoOf(tx, domain, id, session.kind, session.year, user)\n }\n return written\n}\n\n\n/** A certificate the person sends for themself - waiting until the manager confirms it. */\nexport async function submitTrainingCertificate(input: TrainingCertificateInput, attach: any[] | undefined, context: any): Promise<TrainingCompletion> {\n const { domain, user, tx } = context.state\n const employee = await workingEmployeeOf(context)\n if (!employee) throw new Refusal('compliance-employees-only', {}, 'only an employee of this company can do this')\n const kind = (await trainingKindsOf(tx, domain)).find(one => one.code === input.kind)\n const refusal = trainingCertificateRefusal(input, kind, todayIn(domain), attach?.length ?? 0, await completionsOf(tx, domain, employee.id, input.kind, input.year))\n if (refusal) throw refusal\n const session = input.sessionId ? await (tx as EntityManager).getRepository(TrainingSession).findOne({ where: { id: input.sessionId, domain: { id: domain.id }, kind: input.kind, year: input.year } as any }) : null\n if (input.sessionId && !session) throw new Refusal('training-session-unknown', {}, 'the session must be one of this kind and year')\n\n const saved = await (tx as EntityManager).getRepository(TrainingCompletion).save({\n domain,\n employee,\n kind: input.kind,\n year: input.year,\n session,\n completedOn: input.completedOn,\n method: input.method as TrainingMethod,\n organisation: text(input.organisation),\n status: TrainingCompletionStatus.SUBMITTED,\n creator: user,\n updater: user\n } as any)\n for (const file of attach ?? []) await createAttachment(null, { attachment: { file, refType: TRAINING_COMPLETION_REF_TYPE, refBy: saved.id } } as any, context)\n return saved\n}\n\n/** The manager confirms certificates sent - each closes the person's to-do. */\nexport async function confirmTrainingCompletions(ids: string[], context: any): Promise<TrainingCompletion[]> {\n return await decide(ids, TrainingCompletionStatus.CONFIRMED, null, context)\n}\n\n/** The manager returns a certificate, saying why - the person sends another. */\nexport async function returnTrainingCompletion(id: string, reason: string, context: any): Promise<TrainingCompletion> {\n return (await decide([id], TrainingCompletionStatus.RETURNED, reason, context))[0]\n}\n\nasync function decide(ids: string[], decision: TrainingCompletionStatus.CONFIRMED | TrainingCompletionStatus.RETURNED, reason: string | null, context: any) {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingCompletion)\n const saved: TrainingCompletion[] = []\n for (const id of ids) {\n const row = await repository.findOne({ where: { id, domain: { id: domain.id } } as any })\n if (!row) throw new Refusal('training-not-found', {}, 'the record was not found. reload and try again.')\n const refusal = trainingDecisionRefusal(row.status, decision, reason)\n if (refusal) throw refusal\n row.status = decision\n row.returnReason = decision === TrainingCompletionStatus.RETURNED ? reason!.trim() : null\n row.decidedAt = new Date()\n row.decidedBy = user\n row.updater = user\n saved.push(await repository.save(row))\n if (decision === TrainingCompletionStatus.CONFIRMED) await closeTodoOf(tx, domain, row.employeeId!, row.kind, row.year, user)\n }\n return saved\n}\n\n/** Training records are kept (decision 17) - every delete is refused with what to do instead. */\nexport async function deleteTrainingRecords(): Promise<never> {\n throw trainingDeletionRefusal()\n}\n\n/* ---------------------------------------------------------------- the year's to-dos */\n\nexport interface TrainingYearOpening {\n people: number\n done: number\n handedOut: number\n}\n\n/**\n * Opens a kind's year: a worklist to-do 「<교육> 이수」 with the due day for everyone of its audience not done - at most\n * one per person, kind and year, so opening it again hands out only to those it missed (a person who joined since, a\n * to-do the domain could not hand out before).\n */\nexport async function openTrainingYear(kindCode: string, year: number, context: any): Promise<TrainingYearOpening> {\n const { domain, user, tx } = context.state\n const kind = (await trainingKindsOf(tx, domain)).find(one => one.code === kindCode)\n const refusal = trainingSessionRefusal({ kind: kindCode, year, name: '-', method: 'POSTED', startsOn: `${year}-01-01` }, kind)\n if (refusal) throw refusal\n\n const today = todayIn(domain)\n const dueOn = trainingDueOnOf(year, kind!.dueDay)\n const people = await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind!, domain), today)\n const repository = (tx as EntityManager).getRepository(TrainingAssignment)\n const done = new Set(\n (await (tx as EntityManager).getRepository(TrainingCompletion).find({ where: { domain: { id: domain.id }, kind: kindCode, year, status: TrainingCompletionStatus.CONFIRMED } as any })).map(one => one.employeeId)\n )\n /* Someone enrolled in an online session of the kind has that enrolment's to-do - none twice. */\n const online = await onlineLearnersOf(tx, domain, kindCode, year)\n let handedOut = 0\n for (const person of people) {\n if (done.has(person.id) || !person.user || online.has(person.user.id)) continue\n const assignment =\n (await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: person.id }, kind: kindCode, year } as any })) ??\n (await repository.save({ domain, employee: person, kind: kindCode, year, dueOn, creator: user, updater: user } as any))\n if (assignment.todoInstanceId) continue\n const t = translatorFor(person.user.locale || 'ko')\n const id = await issueLegalTodo(tx, domain, {\n assignee: person.user,\n by: user,\n name: t('text.training-todo-name', { kind: kindWord(t, kindCode), year }),\n headline: t('text.training-todo-headline', { dueOn }),\n address: MY_TRAININGS_ADDRESS,\n subjectKind: 'TrainingAssignment',\n subjectId: assignment.id,\n dueAt: trainingDueAt(dueOn, domain.timezone)\n })\n if (!id) continue\n assignment.todoInstanceId = id\n assignment.updater = user\n await repository.save(assignment)\n handedOut++\n }\n return { people: people.length, done: people.filter(one => done.has(one.id)).length, handedOut }\n}\n\n/* ---------------------------------------------------------------- online completions (ADR-0194 decision 16) */\n\nconst dayIn = (at: Date | string, timezone?: string | null) =>\n new Intl.DateTimeFormat('en-CA', { timeZone: timezone || 'UTC', year: 'numeric', month: '2-digit', day: '2-digit' }).format(new Date(at))\n\n/**\n * An enrolment of an online session completed: a confirmed completion of the session's kind and year, with the\n * learning module's evidence - no manager's confirmation needed. Runs in the completion's transaction: what fails here\n * takes the completion back. Someone done already for the kind and year is left as they are.\n */\nexport async function recordOnlineCompletion(enrollment: Enrollment, context: any): Promise<TrainingCompletion | null> {\n const { domain, tx } = context.state\n const session = await (tx as EntityManager).getRepository(TrainingSession).findOne({ where: { id: enrollment.sourceId, domain: { id: domain.id } } as any })\n if (!session) throw new Refusal('training-not-found', {}, 'the session of this enrolment was not found')\n const employee = await (tx as EntityManager).getRepository(Employee).findOne({ where: { domain: { id: domain.id }, user: { id: enrollment.userId } } as any })\n if (!employee) throw new Refusal('training-employee-unknown', {}, 'the learner must be an employee working in this domain')\n if (trainingStateOf(await completionsOf(tx, domain, employee.id, session.kind, session.year)) === 'DONE') return null\n const version = enrollment.versionId ? await (tx as EntityManager).getRepository(CourseVersion).findOne({ where: { id: enrollment.versionId } as any, withDeleted: true }) : null\n const saved = await (tx as EntityManager).getRepository(TrainingCompletion).save({\n domain,\n employee,\n kind: session.kind,\n year: session.year,\n session,\n completedOn: dayIn(enrollment.completedAt ?? new Date(), domain.timezone),\n method: TrainingMethod.ONLINE,\n status: TrainingCompletionStatus.CONFIRMED,\n decidedAt: new Date(),\n learningEnrollmentId: enrollment.id,\n learningEvidence: {\n minutes: Math.floor((enrollment.learnedSeconds ?? 0) / 60),\n score: enrollment.score ?? null,\n attempts: enrollment.attempts ?? 0,\n acknowledgedAt: enrollment.acknowledgedAt ?? null,\n version: version?.number ?? null,\n certificateNo: enrollment.certificateNo ?? null\n },\n creator: context.state.user,\n updater: context.state.user\n } as any)\n await closeTodoOf(tx, domain, employee.id, session.kind, session.year, context.state.user)\n return saved\n}\n\n/** A completed enrolment a manager cancelled: the completion made from it is returned with the reason - kept, not deleted. */\nexport async function returnOnlineCompletion(enrollment: Enrollment, reason: string, context: any): Promise<void> {\n const { domain, user, tx } = context.state\n const repository = (tx as EntityManager).getRepository(TrainingCompletion)\n const row = await repository.findOne({ where: { domain: { id: domain.id }, learningEnrollmentId: enrollment.id } as any })\n if (!row || row.status !== TrainingCompletionStatus.CONFIRMED) return\n row.status = TrainingCompletionStatus.RETURNED\n row.returnReason = reason\n row.decidedAt = new Date()\n row.decidedBy = user\n row.updater = user\n await repository.save(row)\n}\n\n/* ---------------------------------------------------------------- where each person stands */\n\nexport interface TrainingStandingRow {\n id: string\n kind: string\n year: number\n dueOn: string\n state: TrainingState\n completedOn?: string | null\n employee: Employee\n departmentName?: string | null\n}\n\n/** Where everyone of every kind on stands in a year - the people of each kind's audience, by name. */\nexport async function standingsOf(tx: EntityManager, domain: any, year: number, today: string): Promise<TrainingStandingRow[]> {\n const kinds = (await trainingKindsOf(tx, domain)).filter(one => one.enabled)\n const completions = await tx.getRepository(TrainingCompletion).find({ where: { domain: { id: domain.id }, year } as any })\n const rows: TrainingStandingRow[] = []\n for (const kind of kinds) {\n const dueOn = trainingDueOnOf(year, kind.dueDay)\n for (const employee of await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind, domain), today)) {\n const mine = completions.filter(one => one.kind === kind.code && one.employeeId === employee.id)\n const state = trainingStateOf(mine)\n rows.push({\n id: `${kind.code}:${year}:${employee.id}`,\n kind: kind.code,\n year,\n dueOn,\n state,\n completedOn: state === 'DONE' ? mine.filter(one => one.status === 'CONFIRMED').map(one => one.completedOn).sort()[0] : null,\n employee,\n departmentName: employee.department?.name ?? null\n })\n }\n }\n return rows\n}\n\n/**\n * The standings the reader may read: a holder all of them; an employee their own; a department head also whether each\n * of their people is done - no day, no waiting certificate, nothing of its content.\n */\nexport async function readableStandings(year: number, context: any): Promise<TrainingStandingRow[]> {\n const { domain } = context.state\n const tx = trainingManagerOf(context)\n const reader = await trainingReaderOf(context)\n requireReader(reader)\n const rows = await standingsOf(tx, domain, year, todayIn(domain))\n if (reader.all) return rows\n return rows\n .filter(row => row.employee.id === reader.employee!.id || (row.employee.departmentId && reader.headed.includes(row.employee.departmentId)))\n .map(row => (row.employee.id === reader.employee!.id ? row : { ...row, state: row.state === 'DONE' ? 'DONE' : 'NOT_DONE', completedOn: null }))\n}\n\nexport interface MyTrainingRow {\n kind: string\n year: number\n dueOn: string\n state: TrainingState\n completion?: TrainingCompletion | null\n sessions: TrainingSession[]\n}\n\n/** The request's employee's trainings of a year: each kind on whose audience they are in, with its sessions. */\nexport async function myTrainings(year: number, context: any): Promise<MyTrainingRow[]> {\n const { domain } = context.state\n const tx = trainingManagerOf(context)\n const employee = await workingEmployeeOf(context)\n if (!employee) throw new Refusal('compliance-employees-only', {}, 'only an employee of this company can do this')\n const today = todayIn(domain)\n const kinds = (await trainingKindsOf(tx, domain)).filter(one => one.enabled)\n const sessions = await (tx as EntityManager).getRepository(TrainingSession).find({ where: { domain: { id: domain.id }, year } as any, order: { startsOn: 'ASC' } as any })\n const out: MyTrainingRow[] = []\n for (const kind of kinds) {\n if (!(await trainingPeopleOf(tx, domain, trainingAudiencesOf(kind, domain), today)).some(one => one.id === employee.id)) continue\n const mine = (await completionsOf(tx, domain, employee.id, kind.code, year)).sort((a, b) => +new Date(b.createdAt!) - +new Date(a.createdAt!))\n const state = trainingStateOf(mine)\n out.push({\n kind: kind.code,\n year,\n dueOn: trainingDueOnOf(year, kind.dueDay),\n state,\n completion: (state === 'DONE' ? mine.find(one => one.status === 'CONFIRMED') : mine[0]) ?? null,\n sessions: sessions.filter(one => one.kind === kind.code)\n })\n }\n return out\n}\n\n/** Whether the request may read a completion - a holder, or the one it is of. A department head may not. */\nexport async function mayReadCompletion(row: { employeeId?: string | null } | null, context: any): Promise<boolean> {\n if (!row) return false\n if (await requestHolds(context, 'training', 'query')) return true\n const employee = await workingEmployeeOf(context)\n return !!employee && employee.id === row.employeeId\n}\n\n/** Whether the request may read a session's material - a holder, or an employee it is for. */\nexport async function mayReadSession(row: TrainingSession | null, context: any): Promise<boolean> {\n if (!row) return false\n if (await requestHolds(context, 'training', 'query')) return true\n const { domain } = context.state\n const employee = await workingEmployeeOf(context)\n if (!employee) return false\n const manager = trainingManagerOf(context)\n const kind = (await trainingKindsOf(manager, domain)).find(one => one.code === row.kind)\n if (!kind) return false\n return (await trainingPeopleOf(manager, domain, trainingAudiencesOf(kind, domain, row.audiences), todayIn(domain))).some(one => one.id === employee.id)\n}\n"]}
|