@things-factory/pdf 10.1.232 → 10.1.233
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/issue-document.d.ts +6 -0
- package/dist-client/issue-document.js +38 -1
- package/dist-client/issue-document.js.map +1 -1
- package/dist-client/pages/issued-document/issued-document-list.js +11 -1
- package/dist-client/pages/issued-document/issued-document-list.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controller/pdf-release-service.d.ts +5 -0
- package/dist-server/controller/pdf-release-service.js +40 -9
- package/dist-server/controller/pdf-release-service.js.map +1 -1
- package/dist-server/index.d.ts +1 -1
- package/dist-server/index.js +2 -1
- package/dist-server/index.js.map +1 -1
- package/dist-server/service/index.d.ts +1 -0
- package/dist-server/service/pdf-release/pdf-release-query.d.ts +2 -0
- package/dist-server/service/pdf-release/pdf-release-query.js +15 -0
- package/dist-server/service/pdf-release/pdf-release-query.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/translations/en.json +2 -0
- package/translations/es.json +2 -0
- package/translations/ja.json +4 -1
- package/translations/ko.json +2 -0
- package/translations/ms.json +4 -1
- package/translations/zh.json +4 -1
|
@@ -17,6 +17,11 @@ export interface IssueRequest {
|
|
|
17
17
|
/** A template the owning module picked for this subject (a product's own certificate) - before the domain's of the kind. */
|
|
18
18
|
template?: PDFTemplate | null;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* The document as it would be issued, before it is (ADR-0176) - unnumbered, kept nowhere, and marked as a preview across
|
|
22
|
+
* every page so it cannot pass for the issued one.
|
|
23
|
+
*/
|
|
24
|
+
export declare function previewPdf(context: ResolverContext, request: IssueRequest): Promise<Buffer>;
|
|
20
25
|
/**
|
|
21
26
|
* Issue a document - the one way a row reaches the ledger (ADR-0176 decision 2). The kind's module says whether the
|
|
22
27
|
* caller may issue it and what it prints; this numbers it per kind and year, fills the template with the kind's data,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.companyForPrint = companyForPrint;
|
|
4
4
|
exports.templateOfKind = templateOfKind;
|
|
5
|
+
exports.previewPdf = previewPdf;
|
|
5
6
|
exports.releasePdf = releasePdf;
|
|
6
7
|
exports.mayReadRelease = mayReadRelease;
|
|
7
8
|
exports.revokeRelease = revokeRelease;
|
|
@@ -27,6 +28,17 @@ async function companyForPrint(context) {
|
|
|
27
28
|
const { domain, tx } = context.state;
|
|
28
29
|
return (await (0, biz_base_1.printedCompanyOf)(domain, { seal: true, manager: tx }));
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* 「우리 회사」 as an issued document prints it - refused while its representative or seal is missing, for a certificate
|
|
33
|
+
* without them is no certificate (a 재직증명서 printed with an empty 대표이사 and no seal, 2026-10-30).
|
|
34
|
+
*/
|
|
35
|
+
async function issuingCompany(context) {
|
|
36
|
+
const company = await companyForPrint(context);
|
|
37
|
+
const missing = [!company.representative && 'representative', !company.seal && 'seal'].filter(Boolean);
|
|
38
|
+
if (missing.length)
|
|
39
|
+
throw new shell_1.Refusal('issued-document-company-incomplete', {}, `「우리 회사」 lacks its ${missing.join(' and ')} - fill it in before issuing`);
|
|
40
|
+
return company;
|
|
41
|
+
}
|
|
30
42
|
/** The template a kind prints from in this domain: its own `PDFTemplate` of the kind, else the kind's template in code. */
|
|
31
43
|
async function templateOfKind(context, kind) {
|
|
32
44
|
const { domain, tx } = context.state;
|
|
@@ -53,13 +65,11 @@ async function nextSequence(context, kind, year) {
|
|
|
53
65
|
return (last?.sequence ?? 0) + 1;
|
|
54
66
|
}
|
|
55
67
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* 「우리 회사」 and the issue (`{{issue.number}}`, `{{issue.issuedOn}}`, `{{issue.purpose}}`, `{{issue.submittedTo}}`),
|
|
59
|
-
* prints it, and keeps the row with its file. Runs in the request's transaction (`context.state`: domain, user, tx).
|
|
68
|
+
* What an issue prints, before it is numbered: the kind's rule asked, its data from the subject and what the person
|
|
69
|
+
* gave, the template and 「우리 회사」. Refuses what may not or cannot be issued - the issue and its preview alike.
|
|
60
70
|
*/
|
|
61
|
-
async function
|
|
62
|
-
const { domain
|
|
71
|
+
async function prepare(context, request) {
|
|
72
|
+
const { domain } = context.state;
|
|
63
73
|
const kind = (0, issued_document_kind_1.issuedDocumentKindOf)(request.kind);
|
|
64
74
|
if (!kind)
|
|
65
75
|
throw new shell_1.Refusal('issued-document-kind-unknown', { kind: request.kind }, `no module issues ${request.kind}`);
|
|
@@ -71,12 +81,33 @@ async function releasePdf(context, request) {
|
|
|
71
81
|
const issuedOn = (0, shell_1.calendarDay)(domain.timezone);
|
|
72
82
|
const { subjectName, data } = await kind.dataOf(context, refId, { ...input, asOf: input.asOf ?? issuedOn });
|
|
73
83
|
const template = request.template ?? (await templateOfKind(context, kind.kind));
|
|
74
|
-
const
|
|
84
|
+
const company = await issuingCompany(context);
|
|
85
|
+
const issueOf = (number) => ({ number, issuedOn, purpose: input.purpose ?? '', submittedTo: input.submittedTo ?? '', asOf: input.asOf ?? issuedOn });
|
|
86
|
+
return { kind, refId, input, issuedOn, subjectName, data, template, parts: (template ?? kind.template), company, issueOf };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The document as it would be issued, before it is (ADR-0176) - unnumbered, kept nowhere, and marked as a preview across
|
|
90
|
+
* every page so it cannot pass for the issued one.
|
|
91
|
+
*/
|
|
92
|
+
async function previewPdf(context, request) {
|
|
93
|
+
const { data, parts, company, issueOf } = await prepare(context, request);
|
|
94
|
+
const word = String(context.t?.('text.issued-document-preview-mark') ?? '');
|
|
95
|
+
const watermark = word && word !== 'text.issued-document-preview-mark' ? word : 'PREVIEW';
|
|
96
|
+
return await service.generatePdf({ ...parts, watermark }, { ...data, company, issue: issueOf('') });
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Issue a document - the one way a row reaches the ledger (ADR-0176 decision 2). The kind's module says whether the
|
|
100
|
+
* caller may issue it and what it prints; this numbers it per kind and year, fills the template with the kind's data,
|
|
101
|
+
* 「우리 회사」 and the issue (`{{issue.number}}`, `{{issue.issuedOn}}`, `{{issue.purpose}}`, `{{issue.submittedTo}}`),
|
|
102
|
+
* prints it, and keeps the row with its file. Runs in the request's transaction (`context.state`: domain, user, tx).
|
|
103
|
+
*/
|
|
104
|
+
async function releasePdf(context, request) {
|
|
105
|
+
const { domain, user, tx } = context.state;
|
|
106
|
+
const { kind, refId, input, issuedOn, subjectName, data, template, parts, company, issueOf } = await prepare(context, request);
|
|
75
107
|
const year = Number(issuedOn.slice(0, 4));
|
|
76
108
|
const sequence = await nextSequence(context, kind.kind, year);
|
|
77
109
|
const number = (0, issued_document_kind_1.issueNumberOf)(kind.prefix, year, sequence);
|
|
78
|
-
const
|
|
79
|
-
const contents = await service.generatePdf(parts, { ...data, company: await companyForPrint(context), issue });
|
|
110
|
+
const contents = await service.generatePdf(parts, { ...data, company, issue: issueOf(number) });
|
|
80
111
|
const release = await tx.getRepository(pdf_release_1.PDFRelease).save({
|
|
81
112
|
domain,
|
|
82
113
|
name: number,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-release-service.js","sourceRoot":"","sources":["../../server/controller/pdf-release-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Readable } from 'stream'\n\nimport { createAttachment } from '@things-factory/attachment-base'\nimport { printedCompanyOf } from '@things-factory/biz-base'\nimport { calendarDay, Refusal } from '@things-factory/shell'\n\nimport { PDFRelease, PDFReleaseStatus } from '../service/pdf-release/pdf-release'\nimport { PDFTemplate } from '../service/pdf-template/pdf-template'\nimport { IssueInput, issuedDocumentKindOf, issuedFileNameOf, issueInputOf, issueNumberOf } from './issued-document-kind'\nimport { PdfTemplateParts } from './pdf-document'\nimport { PdfService } from './pdf-service'\n\nconst service = new PdfService()\n\n/**\n * A generated PDF handed to the attachment store as an upload would be - its name spelled as the upload parser hands one\n * over (latin1), which the store decodes back to UTF-8.\n */\nconst upload = (filename: string, contents: Buffer) =>\n Promise.resolve({ filename: Buffer.from(filename, 'utf8').toString('latin1'), mimetype: 'application/pdf', encoding: '7bit', createReadStream: () => Readable.from([contents]) })\n\n/**\n * 「우리 회사」 as every template reads it - `{{company.name}}`, `{{company.seal}}` (ADR-0176 decision 4). The seal is a\n * `data:` URL made here, on the server, for the print alone.\n */\nexport async function companyForPrint(context: ResolverContext): Promise<Record<string, any>> {\n const { domain, tx } = context.state\n return (await printedCompanyOf(domain, { seal: true, manager: tx })) as any\n}\n\n/** The template a kind prints from in this domain: its own `PDFTemplate` of the kind, else the kind's template in code. */\nexport async function templateOfKind(context: ResolverContext, kind: string): Promise<PDFTemplate | null> {\n const { domain, tx } = context.state\n const rows = await tx.getRepository(PDFTemplate).find({ where: { domain: { id: domain.id }, kind }, order: { updatedAt: 'DESC' } })\n return rows.find(one => one.active !== false) ?? null\n}\n\n/**\n * The next sequence of a kind in a year - the last row of the kind and year locked in the request's transaction, so two\n * issues at once cannot take one number (the unique index `ix_pdf_release_1` holds where there is no row to lock yet).\n */\nasync function nextSequence(context: ResolverContext, kind: string, year: number): Promise<number> {\n const { domain, tx } = context.state\n const query = tx\n .getRepository(PDFRelease)\n .createQueryBuilder('release')\n .where('release.domain_id = :domain', { domain: domain.id })\n .andWhere('release.kind = :kind', { kind })\n .andWhere('release.year = :year', { year })\n .orderBy('release.sequence', 'DESC')\n .limit(1)\n if (tx.connection.options.type === 'postgres') query.setLock('pessimistic_write')\n const last = await query.getOne()\n return (last?.sequence ?? 0) + 1\n}\n\nexport interface IssueRequest {\n /** A registered kind (`registerIssuedDocumentKind`): its number, its subject and its rules. */\n kind: string\n /** What the document is about, as the kind's `refType` names it - none for a kind about the company itself (`Domain`). */\n refId?: string | null\n input?: IssueInput | null\n /** A template the owning module picked for this subject (a product's own certificate) - before the domain's of the kind. */\n template?: PDFTemplate | null\n}\n\n/**\n * Issue a document - the one way a row reaches the ledger (ADR-0176 decision 2). The kind's module says whether the\n * caller may issue it and what it prints; this numbers it per kind and year, fills the template with the kind's data,\n * 「우리 회사」 and the issue (`{{issue.number}}`, `{{issue.issuedOn}}`, `{{issue.purpose}}`, `{{issue.submittedTo}}`),\n * prints it, and keeps the row with its file. Runs in the request's transaction (`context.state`: domain, user, tx).\n */\nexport async function releasePdf(context: ResolverContext, request: IssueRequest): Promise<{ release: PDFRelease; contents: Buffer }> {\n const { domain, user, tx } = context.state\n const kind = issuedDocumentKindOf(request.kind)\n if (!kind) throw new Refusal('issued-document-kind-unknown', { kind: request.kind }, `no module issues ${request.kind}`)\n /* A document about the company itself is about the request's domain - whatever was named. */\n const refId = kind.refType === 'Domain' ? domain.id : request.refId\n if (!refId || !(await kind.mayIssue(context, refId))) throw new Refusal('issued-document-not-permitted', { kind: request.kind }, `you may not issue ${request.kind} for this`)\n\n const input = issueInputOf(request.input)\n const issuedOn = calendarDay(domain.timezone)\n const { subjectName, data } = await kind.dataOf(context, refId, { ...input, asOf: input.asOf ?? issuedOn })\n const template: PDFTemplate | null = request.template ?? (await templateOfKind(context, kind.kind))\n const parts: PdfTemplateParts = template ?? kind.template\n\n const year = Number(issuedOn.slice(0, 4))\n const sequence = await nextSequence(context, kind.kind, year)\n const number = issueNumberOf(kind.prefix, year, sequence)\n const issue = { number, issuedOn, purpose: input.purpose ?? '', submittedTo: input.submittedTo ?? '', asOf: input.asOf ?? issuedOn }\n const contents = await service.generatePdf(parts, { ...data, company: await companyForPrint(context), issue })\n\n const release = await tx.getRepository(PDFRelease).save({\n domain,\n name: number,\n kind: kind.kind,\n number,\n year,\n sequence,\n refType: kind.refType,\n refId,\n subjectName,\n purpose: input.purpose,\n submittedTo: input.submittedTo,\n template: template ?? null,\n state: PDFReleaseStatus.published,\n creator: user,\n updater: user\n } as any)\n const kindWord = String(context.t?.(`issued-document.${kind.kind}`) ?? '')\n const fileName = issuedFileNameOf(kindWord && kindWord !== `issued-document.${kind.kind}` ? kindWord : kind.prefix, subjectName, number)\n await createAttachment(null, { attachment: { file: upload(fileName, contents), refType: 'PDFRelease', refBy: release.id, category: 'document' } }, context)\n return { release, contents }\n}\n\n/** Whether the caller may read a ledger row: its kind's module says - a row of a kind no loaded module issues stays closed. */\nexport async function mayReadRelease(context: ResolverContext, row: PDFRelease): Promise<boolean> {\n const kind = issuedDocumentKindOf(row.kind)\n if (!kind) return false\n try {\n return (await kind.mayRead(context, row)) === true\n } catch {\n return false\n }\n}\n\n/**\n * Revoke an issued document (ADR-0176 decision 2): a reason is required; the row and its file stay. Whoever may issue\n * the kind for its subject may revoke it.\n */\nexport async function revokeRelease(context: ResolverContext, id: string, reason: string): Promise<PDFRelease> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(PDFRelease)\n const row = await repository.findOne({ where: { domain: { id: domain.id }, id } })\n if (!row) throw new Refusal('issued-document-not-found', {}, 'the issued document was not found')\n const kind = issuedDocumentKindOf(row.kind)\n if (!kind || !row.refId || !(await kind.mayIssue(context, row.refId))) throw new Refusal('issued-document-not-permitted', { kind: row.kind }, `you may not revoke ${row.kind}`)\n const why = String(reason ?? '').trim()\n if (!why) throw new Refusal('issued-document-revoke-reason-required', {}, 'say why it is revoked')\n if (row.state === PDFReleaseStatus.revoked) throw new Refusal('issued-document-already-revoked', {}, 'it is revoked already')\n return await repository.save({ ...row, state: PDFReleaseStatus.revoked, revokedAt: new Date(), revokeReason: why, updater: user })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pdf-release-service.js","sourceRoot":"","sources":["../../server/controller/pdf-release-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Readable } from 'stream'\n\nimport { createAttachment } from '@things-factory/attachment-base'\nimport { printedCompanyOf } from '@things-factory/biz-base'\nimport { calendarDay, Refusal } from '@things-factory/shell'\n\nimport { PDFRelease, PDFReleaseStatus } from '../service/pdf-release/pdf-release'\nimport { PDFTemplate } from '../service/pdf-template/pdf-template'\nimport { IssueInput, issuedDocumentKindOf, issuedFileNameOf, issueInputOf, issueNumberOf } from './issued-document-kind'\nimport { PdfTemplateParts } from './pdf-document'\nimport { PdfService } from './pdf-service'\n\nconst service = new PdfService()\n\n/**\n * A generated PDF handed to the attachment store as an upload would be - its name spelled as the upload parser hands one\n * over (latin1), which the store decodes back to UTF-8.\n */\nconst upload = (filename: string, contents: Buffer) =>\n Promise.resolve({ filename: Buffer.from(filename, 'utf8').toString('latin1'), mimetype: 'application/pdf', encoding: '7bit', createReadStream: () => Readable.from([contents]) })\n\n/**\n * 「우리 회사」 as every template reads it - `{{company.name}}`, `{{company.seal}}` (ADR-0176 decision 4). The seal is a\n * `data:` URL made here, on the server, for the print alone.\n */\nexport async function companyForPrint(context: ResolverContext): Promise<Record<string, any>> {\n const { domain, tx } = context.state\n return (await printedCompanyOf(domain, { seal: true, manager: tx })) as any\n}\n\n/**\n * 「우리 회사」 as an issued document prints it - refused while its representative or seal is missing, for a certificate\n * without them is no certificate (a 재직증명서 printed with an empty 대표이사 and no seal, 2026-10-30).\n */\nasync function issuingCompany(context: ResolverContext): Promise<Record<string, any>> {\n const company = await companyForPrint(context)\n const missing = [!company.representative && 'representative', !company.seal && 'seal'].filter(Boolean)\n if (missing.length) throw new Refusal('issued-document-company-incomplete', {}, `「우리 회사」 lacks its ${missing.join(' and ')} - fill it in before issuing`)\n return company\n}\n\n/** The template a kind prints from in this domain: its own `PDFTemplate` of the kind, else the kind's template in code. */\nexport async function templateOfKind(context: ResolverContext, kind: string): Promise<PDFTemplate | null> {\n const { domain, tx } = context.state\n const rows = await tx.getRepository(PDFTemplate).find({ where: { domain: { id: domain.id }, kind }, order: { updatedAt: 'DESC' } })\n return rows.find(one => one.active !== false) ?? null\n}\n\n/**\n * The next sequence of a kind in a year - the last row of the kind and year locked in the request's transaction, so two\n * issues at once cannot take one number (the unique index `ix_pdf_release_1` holds where there is no row to lock yet).\n */\nasync function nextSequence(context: ResolverContext, kind: string, year: number): Promise<number> {\n const { domain, tx } = context.state\n const query = tx\n .getRepository(PDFRelease)\n .createQueryBuilder('release')\n .where('release.domain_id = :domain', { domain: domain.id })\n .andWhere('release.kind = :kind', { kind })\n .andWhere('release.year = :year', { year })\n .orderBy('release.sequence', 'DESC')\n .limit(1)\n if (tx.connection.options.type === 'postgres') query.setLock('pessimistic_write')\n const last = await query.getOne()\n return (last?.sequence ?? 0) + 1\n}\n\nexport interface IssueRequest {\n /** A registered kind (`registerIssuedDocumentKind`): its number, its subject and its rules. */\n kind: string\n /** What the document is about, as the kind's `refType` names it - none for a kind about the company itself (`Domain`). */\n refId?: string | null\n input?: IssueInput | null\n /** A template the owning module picked for this subject (a product's own certificate) - before the domain's of the kind. */\n template?: PDFTemplate | null\n}\n\n/**\n * What an issue prints, before it is numbered: the kind's rule asked, its data from the subject and what the person\n * gave, the template and 「우리 회사」. Refuses what may not or cannot be issued - the issue and its preview alike.\n */\nasync function prepare(context: ResolverContext, request: IssueRequest) {\n const { domain } = context.state\n const kind = issuedDocumentKindOf(request.kind)\n if (!kind) throw new Refusal('issued-document-kind-unknown', { kind: request.kind }, `no module issues ${request.kind}`)\n /* A document about the company itself is about the request's domain - whatever was named. */\n const refId = kind.refType === 'Domain' ? domain.id : request.refId\n if (!refId || !(await kind.mayIssue(context, refId))) throw new Refusal('issued-document-not-permitted', { kind: request.kind }, `you may not issue ${request.kind} for this`)\n\n const input = issueInputOf(request.input)\n const issuedOn = calendarDay(domain.timezone)\n const { subjectName, data } = await kind.dataOf(context, refId, { ...input, asOf: input.asOf ?? issuedOn })\n const template: PDFTemplate | null = request.template ?? (await templateOfKind(context, kind.kind))\n const company = await issuingCompany(context)\n const issueOf = (number: string) => ({ number, issuedOn, purpose: input.purpose ?? '', submittedTo: input.submittedTo ?? '', asOf: input.asOf ?? issuedOn })\n return { kind, refId, input, issuedOn, subjectName, data, template, parts: (template ?? kind.template) as PdfTemplateParts, company, issueOf }\n}\n\n/**\n * The document as it would be issued, before it is (ADR-0176) - unnumbered, kept nowhere, and marked as a preview across\n * every page so it cannot pass for the issued one.\n */\nexport async function previewPdf(context: ResolverContext, request: IssueRequest): Promise<Buffer> {\n const { data, parts, company, issueOf } = await prepare(context, request)\n const word = String(context.t?.('text.issued-document-preview-mark') ?? '')\n const watermark = word && word !== 'text.issued-document-preview-mark' ? word : 'PREVIEW'\n return await service.generatePdf({ ...parts, watermark }, { ...data, company, issue: issueOf('') })\n}\n\n/**\n * Issue a document - the one way a row reaches the ledger (ADR-0176 decision 2). The kind's module says whether the\n * caller may issue it and what it prints; this numbers it per kind and year, fills the template with the kind's data,\n * 「우리 회사」 and the issue (`{{issue.number}}`, `{{issue.issuedOn}}`, `{{issue.purpose}}`, `{{issue.submittedTo}}`),\n * prints it, and keeps the row with its file. Runs in the request's transaction (`context.state`: domain, user, tx).\n */\nexport async function releasePdf(context: ResolverContext, request: IssueRequest): Promise<{ release: PDFRelease; contents: Buffer }> {\n const { domain, user, tx } = context.state\n const { kind, refId, input, issuedOn, subjectName, data, template, parts, company, issueOf } = await prepare(context, request)\n\n const year = Number(issuedOn.slice(0, 4))\n const sequence = await nextSequence(context, kind.kind, year)\n const number = issueNumberOf(kind.prefix, year, sequence)\n const contents = await service.generatePdf(parts, { ...data, company, issue: issueOf(number) })\n\n const release = await tx.getRepository(PDFRelease).save({\n domain,\n name: number,\n kind: kind.kind,\n number,\n year,\n sequence,\n refType: kind.refType,\n refId,\n subjectName,\n purpose: input.purpose,\n submittedTo: input.submittedTo,\n template: template ?? null,\n state: PDFReleaseStatus.published,\n creator: user,\n updater: user\n } as any)\n const kindWord = String(context.t?.(`issued-document.${kind.kind}`) ?? '')\n const fileName = issuedFileNameOf(kindWord && kindWord !== `issued-document.${kind.kind}` ? kindWord : kind.prefix, subjectName, number)\n await createAttachment(null, { attachment: { file: upload(fileName, contents), refType: 'PDFRelease', refBy: release.id, category: 'document' } }, context)\n return { release, contents }\n}\n\n/** Whether the caller may read a ledger row: its kind's module says - a row of a kind no loaded module issues stays closed. */\nexport async function mayReadRelease(context: ResolverContext, row: PDFRelease): Promise<boolean> {\n const kind = issuedDocumentKindOf(row.kind)\n if (!kind) return false\n try {\n return (await kind.mayRead(context, row)) === true\n } catch {\n return false\n }\n}\n\n/**\n * Revoke an issued document (ADR-0176 decision 2): a reason is required; the row and its file stay. Whoever may issue\n * the kind for its subject may revoke it.\n */\nexport async function revokeRelease(context: ResolverContext, id: string, reason: string): Promise<PDFRelease> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(PDFRelease)\n const row = await repository.findOne({ where: { domain: { id: domain.id }, id } })\n if (!row) throw new Refusal('issued-document-not-found', {}, 'the issued document was not found')\n const kind = issuedDocumentKindOf(row.kind)\n if (!kind || !row.refId || !(await kind.mayIssue(context, row.refId))) throw new Refusal('issued-document-not-permitted', { kind: row.kind }, `you may not revoke ${row.kind}`)\n const why = String(reason ?? '').trim()\n if (!why) throw new Refusal('issued-document-revoke-reason-required', {}, 'say why it is revoked')\n if (row.state === PDFReleaseStatus.revoked) throw new Refusal('issued-document-already-revoked', {}, 'it is revoked already')\n return await repository.save({ ...row, state: PDFReleaseStatus.revoked, revokedAt: new Date(), revokeReason: why, updater: user })\n}\n"]}
|
package/dist-server/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from './service';
|
|
|
2
2
|
export { composePdfDocument, PAGE_SIZES } from './controller/pdf-document';
|
|
3
3
|
export type { PdfTemplateParts } from './controller/pdf-document';
|
|
4
4
|
export { PdfService } from './controller/pdf-service';
|
|
5
|
-
export { companyForPrint, mayReadRelease, releasePdf, revokeRelease, templateOfKind } from './controller/pdf-release-service';
|
|
5
|
+
export { companyForPrint, mayReadRelease, previewPdf, releasePdf, revokeRelease, templateOfKind } from './controller/pdf-release-service';
|
|
6
6
|
export type { IssueRequest } from './controller/pdf-release-service';
|
|
7
7
|
export { issuedDocumentKindOf, issuedDocumentKinds, issuedFileNameOf, issueInputOf, issueNumberOf, registerIssuedDocumentKind } from './controller/issued-document-kind';
|
|
8
8
|
export type { IssuedDocumentData, IssuedDocumentKind, IssuedRow, IssueInput } from './controller/issued-document-kind';
|
package/dist-server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerIssuedDocumentKind = exports.issueNumberOf = exports.issueInputOf = exports.issuedFileNameOf = exports.issuedDocumentKinds = exports.issuedDocumentKindOf = exports.templateOfKind = exports.revokeRelease = exports.releasePdf = exports.mayReadRelease = exports.companyForPrint = exports.PdfService = exports.PAGE_SIZES = exports.composePdfDocument = void 0;
|
|
3
|
+
exports.registerIssuedDocumentKind = exports.issueNumberOf = exports.issueInputOf = exports.issuedFileNameOf = exports.issuedDocumentKinds = exports.issuedDocumentKindOf = exports.templateOfKind = exports.revokeRelease = exports.releasePdf = exports.previewPdf = exports.mayReadRelease = exports.companyForPrint = exports.PdfService = exports.PAGE_SIZES = exports.composePdfDocument = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
tslib_1.__exportStar(require("./service"), exports);
|
|
6
6
|
var pdf_document_1 = require("./controller/pdf-document");
|
|
@@ -11,6 +11,7 @@ Object.defineProperty(exports, "PdfService", { enumerable: true, get: function (
|
|
|
11
11
|
var pdf_release_service_1 = require("./controller/pdf-release-service");
|
|
12
12
|
Object.defineProperty(exports, "companyForPrint", { enumerable: true, get: function () { return pdf_release_service_1.companyForPrint; } });
|
|
13
13
|
Object.defineProperty(exports, "mayReadRelease", { enumerable: true, get: function () { return pdf_release_service_1.mayReadRelease; } });
|
|
14
|
+
Object.defineProperty(exports, "previewPdf", { enumerable: true, get: function () { return pdf_release_service_1.previewPdf; } });
|
|
14
15
|
Object.defineProperty(exports, "releasePdf", { enumerable: true, get: function () { return pdf_release_service_1.releasePdf; } });
|
|
15
16
|
Object.defineProperty(exports, "revokeRelease", { enumerable: true, get: function () { return pdf_release_service_1.revokeRelease; } });
|
|
16
17
|
Object.defineProperty(exports, "templateOfKind", { enumerable: true, get: function () { return pdf_release_service_1.templateOfKind; } });
|
package/dist-server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;;AAAA,oDAAyB;AACzB,0DAA0E;AAAjE,kHAAA,kBAAkB,OAAA;AAAE,0GAAA,UAAU,OAAA;AAEvC,wDAAqD;AAA5C,yGAAA,UAAU,OAAA;AACnB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;;AAAA,oDAAyB;AACzB,0DAA0E;AAAjE,kHAAA,kBAAkB,OAAA;AAAE,0GAAA,UAAU,OAAA;AAEvC,wDAAqD;AAA5C,yGAAA,UAAU,OAAA;AACnB,wEAAyI;AAAhI,sHAAA,eAAe,OAAA;AAAE,qHAAA,cAAc,OAAA;AAAE,iHAAA,UAAU,OAAA;AAAE,iHAAA,UAAU,OAAA;AAAE,oHAAA,aAAa,OAAA;AAAE,qHAAA,cAAc,OAAA;AAE/F,0EAAwK;AAA/J,4HAAA,oBAAoB,OAAA;AAAE,2HAAA,mBAAmB,OAAA;AAAE,wHAAA,gBAAgB,OAAA;AAAE,oHAAA,YAAY,OAAA;AAAE,qHAAA,aAAa,OAAA;AAAE,kIAAA,0BAA0B,OAAA;AAG7H,2CAAwC;AAExC,yDAA4D;AAC5D,6CAAyC;AAEzC,KAAK,MAAM,IAAI,IAAI,uBAAU;IAAE,IAAA,4BAAgB,EAAC,IAAI,CAAC,CAAA","sourcesContent":["export * from './service'\nexport { composePdfDocument, PAGE_SIZES } from './controller/pdf-document'\nexport type { PdfTemplateParts } from './controller/pdf-document'\nexport { PdfService } from './controller/pdf-service'\nexport { companyForPrint, mayReadRelease, previewPdf, releasePdf, revokeRelease, templateOfKind } from './controller/pdf-release-service'\nexport type { IssueRequest } from './controller/pdf-release-service'\nexport { issuedDocumentKindOf, issuedDocumentKinds, issuedFileNameOf, issueInputOf, issueNumberOf, registerIssuedDocumentKind } from './controller/issued-document-kind'\nexport type { IssuedDocumentData, IssuedDocumentKind, IssuedRow, IssueInput } from './controller/issued-document-kind'\n\nimport './controller/pdf-release-reader'\n\nimport { registerRoleTask } from '@things-factory/auth-base'\nimport { ROLE_TASKS } from './role-tasks'\n\nfor (const task of ROLE_TASKS) registerRoleTask(task)\n"]}
|
|
@@ -8,6 +8,7 @@ export declare const schema: {
|
|
|
8
8
|
'Query.readableIssuedDocuments': string;
|
|
9
9
|
'Query.issuedDocument': string;
|
|
10
10
|
'Query.issuedDocumentKinds': string;
|
|
11
|
+
'Query.previewIssuedDocument': string;
|
|
11
12
|
'Mutation.issueDocument': string;
|
|
12
13
|
'Mutation.revokeIssuedDocument': string;
|
|
13
14
|
};
|
|
@@ -21,6 +21,7 @@ export declare class PDFReleaseQuery {
|
|
|
21
21
|
readableIssuedDocuments(params: ListParam, mine: boolean, context: ResolverContext): Promise<PDFReleaseList>;
|
|
22
22
|
issuedDocument(id: string, context: ResolverContext): Promise<PDFRelease | null>;
|
|
23
23
|
issuedDocumentKinds(context: ResolverContext): Promise<IssuedDocumentKindInfo[]>;
|
|
24
|
+
previewIssuedDocument(kind: string, refId: string | null, input: IssueDocumentInput, context: ResolverContext): Promise<string>;
|
|
24
25
|
issueDocument(kind: string, refId: string | null, input: IssueDocumentInput, context: ResolverContext): Promise<PDFRelease>;
|
|
25
26
|
revokeIssuedDocument(id: string, reason: string, context: ResolverContext): Promise<PDFRelease>;
|
|
26
27
|
readable(pdfRelease: PDFRelease, context: ResolverContext): Promise<boolean>;
|
|
@@ -34,6 +35,7 @@ export declare const OPEN_FIELDS: {
|
|
|
34
35
|
'Query.readableIssuedDocuments': string;
|
|
35
36
|
'Query.issuedDocument': string;
|
|
36
37
|
'Query.issuedDocumentKinds': string;
|
|
38
|
+
'Query.previewIssuedDocument': string;
|
|
37
39
|
'Mutation.issueDocument': string;
|
|
38
40
|
'Mutation.revokeIssuedDocument': string;
|
|
39
41
|
};
|
|
@@ -144,6 +144,9 @@ let PDFReleaseQuery = class PDFReleaseQuery {
|
|
|
144
144
|
}
|
|
145
145
|
return infos;
|
|
146
146
|
}
|
|
147
|
+
async previewIssuedDocument(kind, refId, input, context) {
|
|
148
|
+
return (await (0, pdf_release_service_1.previewPdf)(context, { kind, refId, input })).toString('base64');
|
|
149
|
+
}
|
|
147
150
|
async issueDocument(kind, refId, input, context) {
|
|
148
151
|
return (await (0, pdf_release_service_1.releasePdf)(context, { kind, refId, input })).release;
|
|
149
152
|
}
|
|
@@ -202,6 +205,17 @@ tslib_1.__decorate([
|
|
|
202
205
|
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
203
206
|
tslib_1.__metadata("design:returntype", Promise)
|
|
204
207
|
], PDFReleaseQuery.prototype, "issuedDocumentKinds", null);
|
|
208
|
+
tslib_1.__decorate([
|
|
209
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
210
|
+
(0, type_graphql_1.Query)(returns => String, { description: 'A document of a kind as it would be issued, before it is - unnumbered, kept nowhere, marked as a preview; base64 PDF' }),
|
|
211
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('kind')),
|
|
212
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('refId', { nullable: true, description: 'What it is about - none for a document about the company itself' })),
|
|
213
|
+
tslib_1.__param(2, (0, type_graphql_1.Arg)('input', type => IssueDocumentInput, { nullable: true })),
|
|
214
|
+
tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
|
|
215
|
+
tslib_1.__metadata("design:type", Function),
|
|
216
|
+
tslib_1.__metadata("design:paramtypes", [String, String, IssueDocumentInput, Object]),
|
|
217
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
218
|
+
], PDFReleaseQuery.prototype, "previewIssuedDocument", null);
|
|
205
219
|
tslib_1.__decorate([
|
|
206
220
|
(0, type_graphql_1.Directive)('@transaction'),
|
|
207
221
|
(0, type_graphql_1.Mutation)(returns => pdf_release_1.PDFRelease, { description: 'To issue a document of a kind for its subject - numbered, printed and kept in the ledger; the kind\'s module says who may' }),
|
|
@@ -269,6 +283,7 @@ exports.OPEN_FIELDS = {
|
|
|
269
283
|
'Query.readableIssuedDocuments': "each row is read by its kind's module rule (mayRead)",
|
|
270
284
|
'Query.issuedDocument': "read by its kind's module rule (mayRead)",
|
|
271
285
|
'Query.issuedDocumentKinds': 'the names of the kinds the loaded modules issue - no data',
|
|
286
|
+
'Query.previewIssuedDocument': "previewed by whoever may issue it - its kind's module rule (mayIssue)",
|
|
272
287
|
'Mutation.issueDocument': "issued by its kind's module rule (mayIssue)",
|
|
273
288
|
'Mutation.revokeIssuedDocument': "revoked by whoever may issue the kind for its subject (mayIssue)"
|
|
274
289
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-release-query.js","sourceRoot":"","sources":["../../../server/service/pdf-release/pdf-release-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, Field, FieldResolver, InputType, Int, Mutation, ObjectType, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { Attachment } from '@things-factory/attachment-base'\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getRepository, ListParam, SpeakRefusals } from '@things-factory/shell'\n\nimport { issuedDocumentKindOf, issuedDocumentKinds } from '../../controller/issued-document-kind'\nimport { mayReadRelease, releasePdf, revokeRelease } from '../../controller/pdf-release-service'\nimport { PDFRelease } from './pdf-release'\nimport { PDFReleaseList } from './pdf-release-type'\n\n@InputType({ description: 'What a person gives when issuing a document' })\nexport class IssueDocumentInput {\n @Field({ nullable: true, description: 'What the document is for (용도)' }) purpose?: string\n @Field({ nullable: true, description: 'Where it is handed in (제출처)' }) submittedTo?: string\n @Field({ nullable: true, description: 'The day it speaks of (기준일), YYYY-MM-DD - today in the domain when none' }) asOf?: string\n}\n\n@ObjectType({ description: 'An issued document kind a module registered' })\nexport class IssuedDocumentKindInfo {\n @Field({ description: '<module>.<document>' }) kind: string\n @Field({ description: 'The head of its numbers' }) prefix: string\n @Field({ description: 'What its subject is' }) refType: string\n @Field({ description: 'Whether the issue form asks for the day it speaks of' }) asOf: boolean\n @Field({ description: 'Whether the caller may issue it here, in the ledger - a kind about the company itself, or about the caller' }) issuable: boolean\n @Field({ nullable: true, description: 'The subject it is issued for here - the caller\\'s own, for a kind about the caller' }) refId?: string\n}\n\n/** The ledger rows a person may read, newest first - each row asks its kind's module (`mayRead`). */\nasync function readableRows(context: ResolverContext, where: Record<string, any>): Promise<PDFRelease[]> {\n const { domain } = context.state\n const rows = await getRepository(PDFRelease).find({ where: { domain: { id: domain.id }, ...where }, order: { createdAt: 'DESC' } })\n const kept: PDFRelease[] = []\n for (const row of rows) if (await mayReadRelease(context, row)) kept.push(row)\n return kept\n}\n\nconst SEARCHED = ['number', 'subjectName', 'purpose', 'submittedTo']\n\n/** The ledger's filters - kind, refType, refId, state - and its search words, from a list's parameters. */\nfunction listOf(params: ListParam) {\n const where: Record<string, any> = {}\n let search = ''\n for (const filter of params?.filters ?? []) {\n if (['kind', 'refType', 'refId', 'state'].includes(filter.name)) where[filter.name] = filter.operator === 'in' ? In(filter.value) : filter.value\n else if (filter.name === 'q' || SEARCHED.includes(filter.name)) search = String(filter.value ?? '').replace(/%/g, '').toLowerCase()\n }\n return { where, search }\n}\n\n/** A page of rows, after the search words. */\nfunction pageOf(rows: PDFRelease[], search: string, params: ListParam): PDFReleaseList {\n const found = search ? rows.filter(row => SEARCHED.some(field => String((row as any)[field] ?? '').toLowerCase().includes(search))) : rows\n const { page = 1, limit = 0 } = params?.pagination ?? {}\n return { items: limit > 0 ? found.slice((page - 1) * limit, page * limit) : found, total: found.length }\n}\n\n/** Whether a row is about the caller - its kind's own subject for them (one's own employee record). */\nasync function aboutCaller(context: ResolverContext, row: PDFRelease, own: Map<string, string | null>): Promise<boolean> {\n const kind = issuedDocumentKindOf(row.kind)\n if (!kind?.ownSubject || !row.kind) return false\n if (!own.has(row.kind)) own.set(row.kind, await kind.ownSubject(context).catch(() => null))\n return !!row.refId && own.get(row.kind) === row.refId\n}\n\n/*\n * The issuance ledger (발급 대장, ADR-0176 decision 2), two ways:\n *\n * - The whole ledger - every row's number, kind, subject, purpose, recipient and issuer - is read under its own category\n * `issued-document` (`pdf.issuance-ledger`; management support keeps it, the user 2026-10-30). A row's file still\n * opens by its kind's rule.\n * - Everyone else reads rows by each kind's rule (`mayRead`), asked row by row: their own (내 정보 › 내 증명서,\n * `mine` - about them or issued by them), the registers on the register screen. Issuing and revoking ask the kind (`mayIssue`). These\n * doors carry no `@privilege` and are declared open by design on `schema.openFields`.\n */\n@Resolver(PDFRelease)\n@UseMiddleware(SpeakRefusals)\nexport class PDFReleaseQuery {\n @Directive('@privilege(category: \"issued-document\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => PDFReleaseList, { description: 'The whole issuance ledger, newest first - filter by kind, refType, refId, state; search number, subject, purpose or recipient' })\n async issuedDocuments(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<PDFReleaseList> {\n const { where, search } = listOf(params)\n const rows = await getRepository(PDFRelease).find({ where: { domain: { id: context.state.domain.id }, ...where }, order: { createdAt: 'DESC' } })\n return pageOf(rows, search, params)\n }\n\n @Query(returns => PDFReleaseList, { description: \"The issued documents the caller may read by their kinds' rules, newest first - with mine, those about the caller or issued by them\" })\n async readableIssuedDocuments(\n @Args(type => ListParam) params: ListParam,\n @Arg('mine', { nullable: true, description: 'Only the caller\\'s own: the documents about them and those they issued' }) mine: boolean,\n @Ctx() context: ResolverContext\n ): Promise<PDFReleaseList> {\n const { where, search } = listOf(params)\n let rows = await readableRows(context, where)\n if (mine) {\n const own = new Map<string, string | null>()\n const kept: PDFRelease[] = []\n for (const row of rows) if (row.creatorId === context.state.user?.id || (await aboutCaller(context, row, own))) kept.push(row)\n rows = kept\n }\n return pageOf(rows, search, params)\n }\n\n @Query(returns => PDFRelease, { nullable: true, description: 'One issued document, if the caller may read it' })\n async issuedDocument(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<PDFRelease | null> {\n return (await readableRows(context, { id }))[0] ?? null\n }\n\n @Query(returns => [IssuedDocumentKindInfo], { description: 'The kinds of document the loaded modules issue' })\n async issuedDocumentKinds(@Ctx() context: ResolverContext): Promise<IssuedDocumentKindInfo[]> {\n const domainId = context.state.domain?.id\n const infos: IssuedDocumentKindInfo[] = []\n for (const one of issuedDocumentKinds()) {\n /*\n * Issued here: a kind about the company itself, and a kind about the caller (one's own 재직증명서). Anyone else's\n * is issued from the screen of its subject.\n */\n const own = one.refType === 'Domain' ? null : ((await one.ownSubject?.(context).catch(() => null)) ?? null)\n const subject = one.refType === 'Domain' ? domainId : own\n const issuable = !!subject && (await one.mayIssue(context, subject).catch(() => false))\n infos.push({ kind: one.kind, prefix: one.prefix, refType: one.refType, asOf: !!one.asOf, issuable, refId: issuable && own ? own : undefined })\n }\n return infos\n }\n\n @Directive('@transaction')\n @Mutation(returns => PDFRelease, { description: 'To issue a document of a kind for its subject - numbered, printed and kept in the ledger; the kind\\'s module says who may' })\n async issueDocument(\n @Arg('kind') kind: string,\n @Arg('refId', { nullable: true, description: 'What it is about - none for a document about the company itself' }) refId: string | null,\n @Arg('input', type => IssueDocumentInput, { nullable: true }) input: IssueDocumentInput,\n @Ctx() context: ResolverContext\n ): Promise<PDFRelease> {\n return (await releasePdf(context, { kind, refId, input })).release\n }\n\n @Directive('@transaction')\n @Mutation(returns => PDFRelease, { description: 'To revoke an issued document, with the reason - the row and its file stay' })\n async revokeIssuedDocument(@Arg('id') id: string, @Arg('reason') reason: string, @Ctx() context: ResolverContext): Promise<PDFRelease> {\n return await revokeRelease(context, id, reason)\n }\n\n @FieldResolver(type => Boolean, { description: \"Whether the caller may open the file - its kind's rule\" })\n async readable(@Root() pdfRelease: PDFRelease, @Ctx() context: ResolverContext): Promise<boolean> {\n return await mayReadRelease(context, pdfRelease)\n }\n\n @FieldResolver(type => Attachment, { nullable: true, description: \"The PDF file of the release - for whoever may open it by its kind's rule\" })\n async file(@Root() pdfRelease: PDFRelease, @Ctx() context: ResolverContext): Promise<Attachment | null> {\n if (!(await mayReadRelease(context, pdfRelease))) return null\n return await getRepository(Attachment).findOne({ where: { refType: 'PDFRelease', refBy: pdfRelease.id }, order: { createdAt: 'DESC' } })\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() pdfRelease: PDFRelease): Promise<Domain> {\n return pdfRelease.domainId && (await getRepository(Domain).findOneBy({ id: pdfRelease.domainId }))\n }\n\n @FieldResolver(type => User)\n async updater(@Root() pdfRelease: PDFRelease): Promise<User> {\n return pdfRelease.updaterId && (await getRepository(User).findOneBy({ id: pdfRelease.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() pdfRelease: PDFRelease): Promise<User> {\n return pdfRelease.creatorId && (await getRepository(User).findOneBy({ id: pdfRelease.creatorId }))\n }\n}\n\n/** The ledger's doors, open by design (auth-base `openFields`). */\nexport const OPEN_FIELDS = {\n 'Query.readableIssuedDocuments': \"each row is read by its kind's module rule (mayRead)\",\n 'Query.issuedDocument': \"read by its kind's module rule (mayRead)\",\n 'Query.issuedDocumentKinds': 'the names of the kinds the loaded modules issue - no data',\n 'Mutation.issueDocument': \"issued by its kind's module rule (mayIssue)\",\n 'Mutation.revokeIssuedDocument': \"revoked by whoever may issue the kind for its subject (mayIssue)\"\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pdf-release-query.js","sourceRoot":"","sources":["../../../server/service/pdf-release/pdf-release-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, Field, FieldResolver, InputType, Int, Mutation, ObjectType, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { Attachment } from '@things-factory/attachment-base'\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getRepository, ListParam, SpeakRefusals } from '@things-factory/shell'\n\nimport { issuedDocumentKindOf, issuedDocumentKinds } from '../../controller/issued-document-kind'\nimport { mayReadRelease, previewPdf, releasePdf, revokeRelease } from '../../controller/pdf-release-service'\nimport { PDFRelease } from './pdf-release'\nimport { PDFReleaseList } from './pdf-release-type'\n\n@InputType({ description: 'What a person gives when issuing a document' })\nexport class IssueDocumentInput {\n @Field({ nullable: true, description: 'What the document is for (용도)' }) purpose?: string\n @Field({ nullable: true, description: 'Where it is handed in (제출처)' }) submittedTo?: string\n @Field({ nullable: true, description: 'The day it speaks of (기준일), YYYY-MM-DD - today in the domain when none' }) asOf?: string\n}\n\n@ObjectType({ description: 'An issued document kind a module registered' })\nexport class IssuedDocumentKindInfo {\n @Field({ description: '<module>.<document>' }) kind: string\n @Field({ description: 'The head of its numbers' }) prefix: string\n @Field({ description: 'What its subject is' }) refType: string\n @Field({ description: 'Whether the issue form asks for the day it speaks of' }) asOf: boolean\n @Field({ description: 'Whether the caller may issue it here, in the ledger - a kind about the company itself, or about the caller' }) issuable: boolean\n @Field({ nullable: true, description: 'The subject it is issued for here - the caller\\'s own, for a kind about the caller' }) refId?: string\n}\n\n/** The ledger rows a person may read, newest first - each row asks its kind's module (`mayRead`). */\nasync function readableRows(context: ResolverContext, where: Record<string, any>): Promise<PDFRelease[]> {\n const { domain } = context.state\n const rows = await getRepository(PDFRelease).find({ where: { domain: { id: domain.id }, ...where }, order: { createdAt: 'DESC' } })\n const kept: PDFRelease[] = []\n for (const row of rows) if (await mayReadRelease(context, row)) kept.push(row)\n return kept\n}\n\nconst SEARCHED = ['number', 'subjectName', 'purpose', 'submittedTo']\n\n/** The ledger's filters - kind, refType, refId, state - and its search words, from a list's parameters. */\nfunction listOf(params: ListParam) {\n const where: Record<string, any> = {}\n let search = ''\n for (const filter of params?.filters ?? []) {\n if (['kind', 'refType', 'refId', 'state'].includes(filter.name)) where[filter.name] = filter.operator === 'in' ? In(filter.value) : filter.value\n else if (filter.name === 'q' || SEARCHED.includes(filter.name)) search = String(filter.value ?? '').replace(/%/g, '').toLowerCase()\n }\n return { where, search }\n}\n\n/** A page of rows, after the search words. */\nfunction pageOf(rows: PDFRelease[], search: string, params: ListParam): PDFReleaseList {\n const found = search ? rows.filter(row => SEARCHED.some(field => String((row as any)[field] ?? '').toLowerCase().includes(search))) : rows\n const { page = 1, limit = 0 } = params?.pagination ?? {}\n return { items: limit > 0 ? found.slice((page - 1) * limit, page * limit) : found, total: found.length }\n}\n\n/** Whether a row is about the caller - its kind's own subject for them (one's own employee record). */\nasync function aboutCaller(context: ResolverContext, row: PDFRelease, own: Map<string, string | null>): Promise<boolean> {\n const kind = issuedDocumentKindOf(row.kind)\n if (!kind?.ownSubject || !row.kind) return false\n if (!own.has(row.kind)) own.set(row.kind, await kind.ownSubject(context).catch(() => null))\n return !!row.refId && own.get(row.kind) === row.refId\n}\n\n/*\n * The issuance ledger (발급 대장, ADR-0176 decision 2), two ways:\n *\n * - The whole ledger - every row's number, kind, subject, purpose, recipient and issuer - is read under its own category\n * `issued-document` (`pdf.issuance-ledger`; management support keeps it, the user 2026-10-30). A row's file still\n * opens by its kind's rule.\n * - Everyone else reads rows by each kind's rule (`mayRead`), asked row by row: their own (내 정보 › 내 증명서,\n * `mine` - about them or issued by them), the registers on the register screen. Issuing and revoking ask the kind (`mayIssue`). These\n * doors carry no `@privilege` and are declared open by design on `schema.openFields`.\n */\n@Resolver(PDFRelease)\n@UseMiddleware(SpeakRefusals)\nexport class PDFReleaseQuery {\n @Directive('@privilege(category: \"issued-document\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => PDFReleaseList, { description: 'The whole issuance ledger, newest first - filter by kind, refType, refId, state; search number, subject, purpose or recipient' })\n async issuedDocuments(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<PDFReleaseList> {\n const { where, search } = listOf(params)\n const rows = await getRepository(PDFRelease).find({ where: { domain: { id: context.state.domain.id }, ...where }, order: { createdAt: 'DESC' } })\n return pageOf(rows, search, params)\n }\n\n @Query(returns => PDFReleaseList, { description: \"The issued documents the caller may read by their kinds' rules, newest first - with mine, those about the caller or issued by them\" })\n async readableIssuedDocuments(\n @Args(type => ListParam) params: ListParam,\n @Arg('mine', { nullable: true, description: 'Only the caller\\'s own: the documents about them and those they issued' }) mine: boolean,\n @Ctx() context: ResolverContext\n ): Promise<PDFReleaseList> {\n const { where, search } = listOf(params)\n let rows = await readableRows(context, where)\n if (mine) {\n const own = new Map<string, string | null>()\n const kept: PDFRelease[] = []\n for (const row of rows) if (row.creatorId === context.state.user?.id || (await aboutCaller(context, row, own))) kept.push(row)\n rows = kept\n }\n return pageOf(rows, search, params)\n }\n\n @Query(returns => PDFRelease, { nullable: true, description: 'One issued document, if the caller may read it' })\n async issuedDocument(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<PDFRelease | null> {\n return (await readableRows(context, { id }))[0] ?? null\n }\n\n @Query(returns => [IssuedDocumentKindInfo], { description: 'The kinds of document the loaded modules issue' })\n async issuedDocumentKinds(@Ctx() context: ResolverContext): Promise<IssuedDocumentKindInfo[]> {\n const domainId = context.state.domain?.id\n const infos: IssuedDocumentKindInfo[] = []\n for (const one of issuedDocumentKinds()) {\n /*\n * Issued here: a kind about the company itself, and a kind about the caller (one's own 재직증명서). Anyone else's\n * is issued from the screen of its subject.\n */\n const own = one.refType === 'Domain' ? null : ((await one.ownSubject?.(context).catch(() => null)) ?? null)\n const subject = one.refType === 'Domain' ? domainId : own\n const issuable = !!subject && (await one.mayIssue(context, subject).catch(() => false))\n infos.push({ kind: one.kind, prefix: one.prefix, refType: one.refType, asOf: !!one.asOf, issuable, refId: issuable && own ? own : undefined })\n }\n return infos\n }\n\n @Directive('@transaction')\n @Query(returns => String, { description: 'A document of a kind as it would be issued, before it is - unnumbered, kept nowhere, marked as a preview; base64 PDF' })\n async previewIssuedDocument(\n @Arg('kind') kind: string,\n @Arg('refId', { nullable: true, description: 'What it is about - none for a document about the company itself' }) refId: string | null,\n @Arg('input', type => IssueDocumentInput, { nullable: true }) input: IssueDocumentInput,\n @Ctx() context: ResolverContext\n ): Promise<string> {\n return (await previewPdf(context, { kind, refId, input })).toString('base64')\n }\n\n @Directive('@transaction')\n @Mutation(returns => PDFRelease, { description: 'To issue a document of a kind for its subject - numbered, printed and kept in the ledger; the kind\\'s module says who may' })\n async issueDocument(\n @Arg('kind') kind: string,\n @Arg('refId', { nullable: true, description: 'What it is about - none for a document about the company itself' }) refId: string | null,\n @Arg('input', type => IssueDocumentInput, { nullable: true }) input: IssueDocumentInput,\n @Ctx() context: ResolverContext\n ): Promise<PDFRelease> {\n return (await releasePdf(context, { kind, refId, input })).release\n }\n\n @Directive('@transaction')\n @Mutation(returns => PDFRelease, { description: 'To revoke an issued document, with the reason - the row and its file stay' })\n async revokeIssuedDocument(@Arg('id') id: string, @Arg('reason') reason: string, @Ctx() context: ResolverContext): Promise<PDFRelease> {\n return await revokeRelease(context, id, reason)\n }\n\n @FieldResolver(type => Boolean, { description: \"Whether the caller may open the file - its kind's rule\" })\n async readable(@Root() pdfRelease: PDFRelease, @Ctx() context: ResolverContext): Promise<boolean> {\n return await mayReadRelease(context, pdfRelease)\n }\n\n @FieldResolver(type => Attachment, { nullable: true, description: \"The PDF file of the release - for whoever may open it by its kind's rule\" })\n async file(@Root() pdfRelease: PDFRelease, @Ctx() context: ResolverContext): Promise<Attachment | null> {\n if (!(await mayReadRelease(context, pdfRelease))) return null\n return await getRepository(Attachment).findOne({ where: { refType: 'PDFRelease', refBy: pdfRelease.id }, order: { createdAt: 'DESC' } })\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() pdfRelease: PDFRelease): Promise<Domain> {\n return pdfRelease.domainId && (await getRepository(Domain).findOneBy({ id: pdfRelease.domainId }))\n }\n\n @FieldResolver(type => User)\n async updater(@Root() pdfRelease: PDFRelease): Promise<User> {\n return pdfRelease.updaterId && (await getRepository(User).findOneBy({ id: pdfRelease.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() pdfRelease: PDFRelease): Promise<User> {\n return pdfRelease.creatorId && (await getRepository(User).findOneBy({ id: pdfRelease.creatorId }))\n }\n}\n\n/** The ledger's doors, open by design (auth-base `openFields`). */\nexport const OPEN_FIELDS = {\n 'Query.readableIssuedDocuments': \"each row is read by its kind's module rule (mayRead)\",\n 'Query.issuedDocument': \"read by its kind's module rule (mayRead)\",\n 'Query.issuedDocumentKinds': 'the names of the kinds the loaded modules issue - no data',\n 'Query.previewIssuedDocument': \"previewed by whoever may issue it - its kind's module rule (mayIssue)\",\n 'Mutation.issueDocument': \"issued by its kind's module rule (mayIssue)\",\n 'Mutation.revokeIssuedDocument': \"revoked by whoever may issue the kind for its subject (mayIssue)\"\n}\n"]}
|