@things-factory/organization 10.1.228 → 10.1.230

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist-client/component/department-selector.js +0 -7
  2. package/dist-client/component/department-selector.js.map +1 -1
  3. package/dist-client/pages/department/department-list-page.js +1 -1
  4. package/dist-client/pages/department/department-list-page.js.map +1 -1
  5. package/dist-client/tsconfig.tsbuildinfo +1 -1
  6. package/dist-server/role-tasks.js +2 -0
  7. package/dist-server/role-tasks.js.map +1 -1
  8. package/dist-server/service/department/department-query.d.ts +1 -0
  9. package/dist-server/service/department/department-query.js +26 -3
  10. package/dist-server/service/department/department-query.js.map +1 -1
  11. package/dist-server/service/department/department.js +3 -1
  12. package/dist-server/service/department/department.js.map +1 -1
  13. package/dist-server/service/employee-profile/employee-profile-document.d.ts +10 -4
  14. package/dist-server/service/employee-profile/employee-profile-document.js +84 -39
  15. package/dist-server/service/employee-profile/employee-profile-document.js.map +1 -1
  16. package/dist-server/service/employee-profile/employee-profile-mutation.js.map +1 -1
  17. package/dist-server/service/employee-profile/employee-profile-rules.d.ts +12 -0
  18. package/dist-server/service/employee-profile/employee-profile-rules.js +25 -0
  19. package/dist-server/service/employee-profile/employee-profile-rules.js.map +1 -1
  20. package/dist-server/service/employee-profile/employee-profile.d.ts +1 -0
  21. package/dist-server/service/employee-profile/employee-profile.js +14 -1
  22. package/dist-server/service/employee-profile/employee-profile.js.map +1 -1
  23. package/dist-server/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +2 -2
  25. package/tests/department-open-fields.test.ts +72 -0
  26. package/tests/employee-profile-db.test.ts +14 -0
  27. package/tests/employee-profile-document.test.ts +66 -3
  28. package/translations/en.json +2 -0
  29. package/translations/es.json +2 -0
  30. package/translations/ja.json +2 -0
  31. package/translations/ko.json +2 -0
  32. package/translations/ms.json +2 -0
  33. package/translations/zh.json +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"employee-profile-document.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-document.ts"],"names":[],"mappings":"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","sourcesContent":["import { Borders, Style, Workbook, Worksheet } from 'exceljs'\n\nimport { todayOf } from './employee-profile-rules'\n\n/*\n * The employee profiles a quotation attaches, as a document a person can hand in as it is (ADR-0169 decisions 6 · 8):\n * a page a person, made to show what the person is worth - the name large with where they stand, the figures a buyer\n * weighs (total experience, projects delivered, certificates held), the expertise in their own words and skills, then\n * the projects first, the careers, certificates and education - laid out for A4. Several people open with a roster.\n *\n * One layout (`profileSheetLayout`, `rosterLayout`) is painted twice: as an Excel workbook, a sheet a page\n * (`profileWorkbook`), and as HTML printed to PDF, a page break a sheet (`profileHtml`). Pure - the door reads the data\n * and the pdf module prints.\n */\n\n/** A row of any of the four tables - each has some of these. */\ntype Row = {\n school?: string\n major?: string\n degree?: string\n name?: string\n issuer?: string\n acquiredOn?: string\n company?: string\n department?: string\n position?: string\n duties?: string\n client?: string\n role?: string\n technologies?: string\n startedOn?: string\n endedOn?: string\n}\n\nexport type ProfilePerson = {\n name?: string | null\n departmentName?: string | null\n jobPosition?: string | null\n jobResponsibility?: string | null\n hiredOn?: string | null\n profile?: {\n summary?: string | null\n skills?: string[] | null\n educations?: Row[] | null\n certificates?: Row[] | null\n careers?: Row[] | null\n projects?: Row[] | null\n } | null\n}\n\n/** The words of the document, in the reader's language - handed in so this stays free of i18next. */\nexport type ProfileSheetWords = Record<\n | 'title'\n | 'rosterTitle'\n | 'expertise'\n | 'name'\n | 'department'\n | 'jobPosition'\n | 'hiredOn'\n | 'careerLength'\n | 'projectsDone'\n | 'certificatesHeld'\n | 'summary'\n | 'skills'\n | 'educations'\n | 'certificates'\n | 'careers'\n | 'projects'\n | 'school'\n | 'major'\n | 'degree'\n | 'period'\n | 'certificate'\n | 'issuer'\n | 'acquiredOn'\n | 'company'\n | 'position'\n | 'duties'\n | 'project'\n | 'client'\n | 'role'\n | 'technologies'\n | 'ongoing'\n | 'none'\n | 'writtenOn'\n | 'averageCareer'\n | 'number',\n string\n> & {\n /** 「12년 3개월」 */\n years: (years: number, months: number) => string\n /** 「8건」 */\n projectCount: (count: number) => string\n /** 「3개」 */\n certificateCount: (count: number) => string\n /** 「5명」 */\n peopleCount: (count: number) => string\n}\n\n/** What a cell is - the painter styles by it. */\nexport type CellRole =\n | 'company'\n | 'kicker'\n | 'name'\n | 'tagline'\n | 'rule'\n | 'statLabel'\n | 'statValue'\n | 'section'\n | 'summary'\n | 'label'\n | 'skills'\n | 'head'\n | 'value'\n | 'none'\n\n/** A cell of the six-column grid: `col` from 1, spanning `span` columns. */\nexport type LayoutCell = { col: number; span?: number; value: string; role: CellRole }\n\n/** A line of the grid; `zebra` shades every other row of a table. */\nexport type LayoutLine = { cells: LayoutCell[]; height?: number; zebra?: boolean }\n\n/** The grid's six columns, in characters - together about the width of A4 in portrait. */\nexport const COLUMN_WIDTHS = [18, 20, 15, 12, 21, 18]\n\n/** 「2023.03」 from 「2023-03」 or 「2023-03-02」 - the dotted form a staffing profile is read in. */\nexport function dotted(day?: string | null): string {\n return (day ?? '').trim().replace(/-/g, '.')\n}\n\n/** A period as one cell - an open end is still going on. */\nexport function periodOf(startedOn: string | undefined, endedOn: string | undefined, ongoing: string): string {\n if (!startedOn && !endedOn) return ''\n return `${dotted(startedOn)} ~ ${endedOn ? dotted(endedOn) : ongoing}`.trim()\n}\n\nconst monthIndex = (day?: string | null): number | null => {\n const match = /^(\\d{4})-(\\d{2})/.exec((day ?? '').trim())\n return match ? Number(match[1]) * 12 + Number(match[2]) - 1 : null\n}\n\n/**\n * The months a person has worked: the careers before this company and the time here since the hire day, counted\n * once where they overlap. A career with no end runs to `today`; one with no start is left out.\n */\nexport function careerMonths(person: ProfilePerson, today = new Date()): number {\n const now = today.getFullYear() * 12 + today.getMonth()\n const months = new Set<number>()\n const spans = [\n ...(person.profile?.careers ?? []).map(row => [monthIndex(row.startedOn), row.endedOn ? monthIndex(row.endedOn) : now] as const),\n [monthIndex(person.hiredOn), now] as const\n ]\n for (const [from, to] of spans) {\n if (from === null || to === null) continue\n for (let month = from; month <= Math.min(to, now); month++) months.add(month)\n }\n return months.size\n}\n\nexport function careerLengthOf(person: ProfilePerson, words: ProfileSheetWords, today = new Date()): string {\n const months = careerMonths(person, today)\n return months ? words.years(Math.floor(months / 12), months % 12) : ''\n}\n\n/** Where the person stands, in one line: department · position / responsibility · hired on. */\nexport function taglineOf(person: ProfilePerson, words: ProfileSheetWords): string {\n const role = [person.jobPosition, person.jobResponsibility].filter(Boolean).join(' / ')\n return [person.departmentName, role, person.hiredOn ? `${words.hiredOn} ${dotted(person.hiredOn)}` : ''].filter(Boolean).join(' · ')\n}\n\n/** The head every page opens with: the employer and what the page is, the name large, a line under it. */\nfunction headOf(company: string, kicker: string, name: string, tagline: string): LayoutLine[] {\n return [\n {\n cells: [\n { col: 1, span: 3, value: company, role: 'company' },\n { col: 4, span: 3, value: kicker, role: 'kicker' }\n ]\n },\n { cells: [{ col: 1, span: 6, value: name, role: 'name' }], height: 40 },\n { cells: [{ col: 1, span: 6, value: tagline, role: 'tagline' }], height: 20 },\n { cells: [{ col: 1, span: 6, value: '', role: 'rule' }], height: 6 }\n ]\n}\n\n/** One person's page, line by line. `company` is the employer's name; `today` the day it is written. */\nexport function profileSheetLayout(person: ProfilePerson, words: ProfileSheetWords, company: string, today = new Date()): LayoutLine[] {\n const profile = person.profile ?? {}\n const lines: LayoutLine[] = [...headOf(company, words.title, person.name ?? '', taglineOf(person, words))]\n const gap = (height = 12) => lines.push({ cells: [], height })\n const section = (title: string) => {\n gap(16)\n lines.push({ cells: [{ col: 1, span: 6, value: title, role: 'section' }], height: 24 })\n gap(6)\n }\n\n /* A table: its head and its rows in the columns given as [col, span], every other row shaded; none says so. */\n const table = (title: string, columns: [number, number, string][], rows: Row[] | null | undefined, cells: (row: Row) => (string | undefined)[]) => {\n section(title)\n lines.push({ cells: columns.map(([col, span, head]) => ({ col, span, value: head, role: 'head' })) })\n if (!rows?.length) return lines.push({ cells: [{ col: 1, span: 6, value: words.none, role: 'none' }] })\n rows.forEach((row, index) =>\n lines.push({\n cells: cells(row).map((text, at) => ({ col: columns[at][0], span: columns[at][1], value: text ?? '', role: 'value' })),\n ...(index % 2 ? { zebra: true } : {})\n })\n )\n }\n\n /* The figures a buyer weighs first. */\n const projects = profile.projects?.length ?? 0\n const certificates = profile.certificates?.length ?? 0\n gap(14)\n lines.push({\n cells: [\n { col: 1, span: 2, value: words.careerLength, role: 'statLabel' },\n { col: 3, span: 2, value: words.projectsDone, role: 'statLabel' },\n { col: 5, span: 2, value: words.certificatesHeld, role: 'statLabel' }\n ],\n height: 20\n })\n lines.push({\n cells: [\n { col: 1, span: 2, value: careerLengthOf(person, words, today) || '—', role: 'statValue' },\n { col: 3, span: 2, value: projects ? words.projectCount(projects) : '—', role: 'statValue' },\n { col: 5, span: 2, value: certificates ? words.certificateCount(certificates) : '—', role: 'statValue' }\n ],\n height: 34\n })\n\n section(words.expertise)\n if (profile.summary?.trim()) lines.push({ cells: [{ col: 1, span: 6, value: profile.summary.trim(), role: 'summary' }] })\n lines.push({\n cells: [\n { col: 1, value: words.skills, role: 'label' },\n { col: 2, span: 5, value: (profile.skills ?? []).join(', '), role: 'skills' }\n ]\n })\n\n table(\n words.projects,\n [[1, 1, words.period], [2, 1, words.project], [3, 1, words.client], [4, 1, words.role], [5, 1, words.duties], [6, 1, words.technologies]],\n profile.projects,\n row => [periodOf(row.startedOn, row.endedOn, words.ongoing), row.name, row.client, row.role, row.duties, row.technologies]\n )\n table(\n words.careers,\n [[1, 1, words.period], [2, 1, words.company], [3, 1, words.department], [4, 1, words.position], [5, 2, words.duties]],\n profile.careers,\n row => [periodOf(row.startedOn, row.endedOn, words.ongoing), row.company, row.department, row.position, row.duties]\n )\n table(words.certificates, [[1, 1, words.acquiredOn], [2, 3, words.certificate], [5, 2, words.issuer]], profile.certificates, row => [\n dotted(row.acquiredOn),\n row.name,\n row.issuer\n ])\n table(words.educations, [[1, 1, words.period], [2, 2, words.school], [4, 2, words.major], [6, 1, words.degree]], profile.educations, row => [\n periodOf(row.startedOn, row.endedOn, words.ongoing),\n row.school,\n row.major,\n row.degree\n ])\n return lines\n}\n\n/** How many people, and their experience on average - the team's weight in one line. */\nexport function rosterTaglineOf(people: ProfilePerson[], words: ProfileSheetWords, today = new Date()): string {\n const months = people.map(person => careerMonths(person, today))\n const average = people.length ? Math.round(months.reduce((sum, one) => sum + one, 0) / people.length) : 0\n return [words.peopleCount(people.length), average ? `${words.averageCareer} ${words.years(Math.floor(average / 12), average % 12)}` : ''].filter(Boolean).join(' · ')\n}\n\n/** The roster that opens a document of several people - one line a person, in the order picked. */\nexport function rosterLayout(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): LayoutLine[] {\n return [\n ...headOf(company, `${words.writtenOn} ${dotted(todayOf(today))}`, words.rosterTitle, rosterTaglineOf(people, words, today)),\n { cells: [], height: 16 },\n {\n cells: [words.number, words.name, words.department, words.jobPosition, words.careerLength, words.skills].map((value, index) => ({ col: index + 1, value, role: 'head' as const }))\n },\n ...people.map((person, index) => ({\n cells: [\n String(index + 1),\n person.name ?? '',\n person.departmentName ?? '',\n person.jobPosition ?? '',\n careerLengthOf(person, words, today),\n (person.profile?.skills ?? []).join(', ')\n ].map((value, column) => ({ col: column + 1, value, role: 'value' as const })),\n ...(index % 2 ? { zebra: true } : {})\n }))\n ]\n}\n\n/**\n * A sheet name for each person. Excel takes at most 31 characters, none of \\ / ? * [ ] :, and no two alike ignoring\n * case - two people of one name become 「홍길동」 and 「홍길동 (2)」. `reserved` are names already in the book.\n */\nexport function sheetNamesOf(names: (string | null | undefined)[], reserved: string[] = []): string[] {\n const taken = new Set<string>(reserved.map(name => name.toLowerCase()))\n return names.map((name, index) => {\n const base = (name ?? '').replace(/[\\\\/?*[\\]:]/g, ' ').replace(/^'+|'+$/g, '').trim() || `#${index + 1}`\n let candidate = base.slice(0, 31)\n for (let n = 2; taken.has(candidate.toLowerCase()); n++) {\n const tail = ` (${n})`\n candidate = base.slice(0, 31 - tail.length) + tail\n }\n taken.add(candidate.toLowerCase())\n return candidate\n })\n}\n\n/** The document's colours - a deep navy for what leads the eye, a pale blue-grey ground, quiet lines. */\nexport const PALETTE = { navy: '1F3A5F', ground: 'EEF3F8', zebra: 'F7F9FB', line: 'C9D2DC', ink: '17242C', muted: '5F6B76' }\n\nconst FONT = 'Malgun Gothic'\nconst argb = (hex: string) => ({ argb: `FF${hex}` })\nconst LINE = { style: 'thin' as const, color: argb(PALETTE.line) }\nconst RULED: Partial<Borders> = { top: LINE, left: LINE, bottom: LINE, right: LINE }\nconst ground = (hex: string) => ({ type: 'pattern' as const, pattern: 'solid' as const, fgColor: argb(hex) })\nconst font = (size: number, extra: Partial<Style['font']> = {}) => ({ name: FONT, size, color: argb(PALETTE.ink), ...extra })\n\n/** How each role of cell is painted in Excel. */\nconst PAINT: Record<CellRole, Partial<Style>> = {\n company: { font: font(9, { color: argb(PALETTE.muted) }), alignment: { horizontal: 'left', vertical: 'bottom' } },\n kicker: { font: font(9, { bold: true, color: argb(PALETTE.navy) }), alignment: { horizontal: 'right', vertical: 'bottom' } },\n name: { font: font(22, { bold: true, color: argb(PALETTE.navy) }), alignment: { horizontal: 'left', vertical: 'bottom' } },\n tagline: { font: font(10.5, { color: argb(PALETTE.muted) }), alignment: { horizontal: 'left', vertical: 'top' } },\n rule: { border: { bottom: { style: 'thick', color: argb(PALETTE.navy) } } },\n statLabel: {\n font: font(9, { color: argb(PALETTE.muted) }),\n fill: ground(PALETTE.ground),\n alignment: { horizontal: 'center', vertical: 'bottom' },\n border: { top: { style: 'medium', color: argb(PALETTE.navy) } }\n },\n statValue: { font: font(16, { bold: true, color: argb(PALETTE.navy) }), fill: ground(PALETTE.ground), alignment: { horizontal: 'center', vertical: 'middle' } },\n section: { font: font(12, { bold: true, color: argb(PALETTE.navy) }), alignment: { horizontal: 'left', vertical: 'bottom' }, border: { bottom: { style: 'medium', color: argb(PALETTE.navy) } } },\n summary: {\n font: font(10.5),\n fill: ground(PALETTE.ground),\n alignment: { horizontal: 'left', vertical: 'middle', wrapText: true, indent: 1 },\n border: { left: { style: 'thick', color: argb(PALETTE.navy) } }\n },\n label: { font: font(9.5, { bold: true, color: argb(PALETTE.navy) }), fill: ground(PALETTE.ground), alignment: { horizontal: 'center', vertical: 'middle', wrapText: true }, border: RULED },\n skills: { font: font(10, { bold: true }), alignment: { horizontal: 'left', vertical: 'middle', wrapText: true, indent: 1 }, border: RULED },\n head: {\n font: font(9.5, { bold: true, color: argb('FFFFFF') }),\n fill: ground(PALETTE.navy),\n alignment: { horizontal: 'center', vertical: 'middle', wrapText: true },\n border: { top: { style: 'thin', color: argb(PALETTE.navy) }, bottom: { style: 'thin', color: argb(PALETTE.navy) }, left: LINE, right: LINE }\n },\n value: { font: font(9.5), alignment: { horizontal: 'left', vertical: 'middle', wrapText: true, indent: 1 }, border: RULED },\n none: { font: font(9.5, { color: argb(PALETTE.muted) }), alignment: { horizontal: 'center', vertical: 'middle' }, border: RULED }\n}\n\n/**\n * A line's height in points, for as many text lines as its longest boxed cell wraps into - Excel does not grow a row\n * for wrapped text written by a program. A full-width character is about two of the column's character units.\n */\nexport function heightOf(line: LayoutLine): number | undefined {\n const boxed = line.cells.filter(cell => ['label', 'skills', 'summary', 'head', 'value', 'none'].includes(cell.role))\n if (!boxed.length) return undefined\n const wraps = boxed.map(cell => {\n const width = COLUMN_WIDTHS.slice(cell.col - 1, cell.col - 1 + (cell.span ?? 1)).reduce((sum, one) => sum + one, 0) - (cell.role === 'summary' ? 4 : 1)\n return cell.value.split('\\n').reduce((lines, text) => {\n const units = [...text].reduce((sum, char) => sum + (char.charCodeAt(0) > 0x2e7f ? 1.9 : 0.9), 0)\n return lines + Math.max(1, Math.ceil(units / Math.max(width, 1)))\n }, 0)\n })\n const lines = Math.max(...wraps)\n return boxed.some(cell => cell.role === 'summary') ? lines * 16 + 14 : lines * 15 + 7\n}\n\n/** Paint a layout on a sheet: values, spans merged, each cell of a span painted so a boxed cell is boxed all round. */\nexport function paintSheet(sheet: Worksheet, lines: LayoutLine[], footer = '') {\n COLUMN_WIDTHS.forEach((width, index) => (sheet.getColumn(index + 1).width = width))\n lines.forEach((line, index) => {\n const row = sheet.getRow(index + 1)\n const height = Math.max(line.height ?? 0, heightOf(line) ?? 0)\n if (height) row.height = height\n for (const cell of line.cells) {\n const span = cell.span ?? 1\n const style = line.zebra && cell.role === 'value' ? { ...PAINT.value, fill: ground(PALETTE.zebra) } : PAINT[cell.role]\n for (let col = cell.col; col < cell.col + span; col++) Object.assign(row.getCell(col), { style })\n row.getCell(cell.col).value = cell.value\n if (span > 1) sheet.mergeCells(index + 1, cell.col, index + 1, cell.col + span - 1)\n }\n })\n sheet.views = [{ showGridLines: false }]\n sheet.pageSetup = {\n paperSize: 9,\n orientation: 'portrait',\n fitToPage: true,\n fitToWidth: 1,\n fitToHeight: 0,\n horizontalCentered: true,\n margins: { left: 0.5, right: 0.5, top: 0.6, bottom: 0.7, header: 0.3, footer: 0.3 }\n }\n /* The employer at the foot of every printed page, and the page of how many. `&` is Excel's escape. */\n sheet.headerFooter = { oddFooter: `&L&8${footer.replace(/&/g, '&&')}&R&8&P / &N` }\n}\n\n/** The workbook of the people given, in their order - opened by a roster when there are several. */\nexport function profileWorkbook(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): Workbook {\n const book = new Workbook()\n const footer = [company, words.title].filter(Boolean).join(' · ')\n /* The roster's name follows Excel's rules as the people's do. */\n const roster = people.length > 1 ? sheetNamesOf([words.rosterTitle]) : []\n if (roster.length) paintSheet(book.addWorksheet(roster[0]), rosterLayout(people, words, company, today), footer)\n const names = sheetNamesOf(people.map(person => person.name), roster)\n people.forEach((person, index) => paintSheet(book.addWorksheet(names[index]), profileSheetLayout(person, words, company, today), footer))\n return book\n}\n\nconst escapeHtml = (text: string) => text.replace(/[&<>\"]/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;' })[c]!)\n\n/** A cell's content as HTML: skills as tags, line breaks kept, everything escaped. */\nfunction cellHtml(cell: LayoutCell): string {\n if (cell.role === 'skills') {\n return cell.value\n .split(', ')\n .filter(Boolean)\n .map(skill => `<span class=\"tag\">${escapeHtml(skill)}</span>`)\n .join('')\n }\n return escapeHtml(cell.value).replace(/\\n/g, '<br>')\n}\n\n/** The same layout as HTML: a table of the six columns a page, the roles as classes. */\nexport function layoutHtml(lines: LayoutLine[]): string {\n const total = COLUMN_WIDTHS.reduce((sum, width) => sum + width, 0)\n const columns = COLUMN_WIDTHS.map(width => `<col style=\"width:${((width / total) * 100).toFixed(2)}%\">`).join('')\n const rows = lines.map(line => {\n const style = line.height ? ` style=\"height:${Math.round(line.height * 1.33)}px\"` : ''\n if (!line.cells.length) return `<tr class=\"gap\"${style}><td colspan=\"6\"></td></tr>`\n let next = 1\n const cells: string[] = []\n for (const cell of line.cells) {\n if (cell.col > next) cells.push(`<td colspan=\"${cell.col - next}\"></td>`)\n const span = cell.span ?? 1\n cells.push(`<td class=\"${cell.role}\"${span > 1 ? ` colspan=\"${span}\"` : ''}>${cellHtml(cell)}</td>`)\n next = cell.col + span\n }\n if (next <= 6) cells.push(`<td colspan=\"${7 - next}\"></td>`)\n return `<tr${line.zebra ? ' class=\"zebra\"' : ''}${style}>${cells.join('')}</tr>`\n })\n return `<table><colgroup>${columns}</colgroup>${rows.join('')}</table>`\n}\n\n/** How the roles look on paper - the workbook's paint in CSS. */\nexport const PROFILE_CSS = `\nbody { margin: 0; font-family: 'Pretendard', 'Malgun Gothic', 'Apple SD Gothic Neo', 'Noto Sans KR', sans-serif; font-size: 9.5pt; color: #${PALETTE.ink};\n -webkit-print-color-adjust: exact; print-color-adjust: exact }\n.sheet { break-after: page }\n.sheet:last-child { break-after: auto }\ntable { width: 100%; border-collapse: collapse; table-layout: fixed }\ntd { padding: 5px 7px; vertical-align: middle; word-break: keep-all; overflow-wrap: anywhere; line-height: 1.45 }\ntr.gap td { padding: 0 }\ntd.company { font-size: 8.5pt; color: #${PALETTE.muted}; padding: 0 0 2px }\ntd.kicker { font-size: 8.5pt; font-weight: 700; color: #${PALETTE.navy}; text-align: right; letter-spacing: 0.08em; padding: 0 0 2px }\ntd.name { font-size: 24pt; font-weight: 800; color: #${PALETTE.navy}; letter-spacing: 0.02em; padding: 6px 0 0; vertical-align: bottom }\ntd.tagline { font-size: 10.5pt; color: #${PALETTE.muted}; padding: 2px 0 8px; vertical-align: top }\ntd.rule { border-bottom: 3px solid #${PALETTE.navy}; padding: 0 }\ntd.statLabel { background: #${PALETTE.ground}; border-top: 2px solid #${PALETTE.navy}; text-align: center; font-size: 8.5pt; color: #${PALETTE.muted}; padding: 8px 0 0 }\ntd.statValue { background: #${PALETTE.ground}; text-align: center; font-size: 17pt; font-weight: 800; color: #${PALETTE.navy}; padding: 0 0 8px }\ntd.statLabel + td.statLabel, td.statValue + td.statValue { border-left: 8px solid #fff }\ntd.section { font-size: 12pt; font-weight: 800; color: #${PALETTE.navy}; border-bottom: 2px solid #${PALETTE.navy}; padding: 0 0 4px; vertical-align: bottom }\ntd.summary { background: #${PALETTE.ground}; border-left: 4px solid #${PALETTE.navy}; font-size: 10.5pt; padding: 10px 14px }\ntd.label { background: #${PALETTE.ground}; color: #${PALETTE.navy}; font-weight: 700; text-align: center; border: 1px solid #${PALETTE.line} }\ntd.skills { border: 1px solid #${PALETTE.line}; padding: 6px 8px }\n.tag { display: inline-block; margin: 2px 4px 2px 0; padding: 2px 9px; border-radius: 10px; background: #${PALETTE.navy}; color: #fff; font-size: 8.5pt; font-weight: 600 }\ntd.head { background: #${PALETTE.navy}; color: #fff; font-weight: 700; text-align: center; border: 1px solid #${PALETTE.navy}; font-size: 9pt }\ntd.value { border: 1px solid #${PALETTE.line} }\ntr.zebra td.value { background: #${PALETTE.zebra} }\ntd.none { border: 1px solid #${PALETTE.line}; color: #${PALETTE.muted}; text-align: center }\ntr { break-inside: avoid }\n`\n\n/** On a screen, the pages as sheets of A4 on a grey desk - the preview reads as the PDF will (ADR-0169 decision 9). */\nexport const PROFILE_SCREEN_CSS = `\n@media screen {\n html { background: #e9edf1 }\n body { padding: 24px 0 }\n .sheet { box-sizing: border-box; width: 210mm; min-height: 297mm; margin: 0 auto 24px; padding: 14mm 12mm; background: #fff;\n box-shadow: 0 1px 3px rgba(23, 36, 44, .12), 0 8px 24px rgba(23, 36, 44, .08) }\n}\n`\n\n/** The preview: the same pages as one HTML document, to be shown in a frame. */\nexport function profilePreviewHtml(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): string {\n return `<!doctype html><html><head><meta charset=\"utf-8\"><style>${PROFILE_CSS}${PROFILE_SCREEN_CSS}</style></head><body>${profileHtml(people, words, company, today)}</body></html>`\n}\n\n/** The document as one HTML page set: the roster first when there are several, then a page a person. */\nexport function profileHtml(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): string {\n const sheets = [\n ...(people.length > 1 ? [rosterLayout(people, words, company, today)] : []),\n ...people.map(person => profileSheetLayout(person, words, company, today))\n ]\n return sheets.map(lines => `<section class=\"sheet\">${layoutHtml(lines)}</section>`).join('')\n}\n\n/** The foot of every printed PDF page: the employer and the document at the left, the page of how many at the right. */\nexport function profileFooterHtml(company: string, words: ProfileSheetWords): string {\n /* The footer is a Handlebars template in the pdf module - a brace in the name must not open one. */\n const left = escapeHtml([company, words.title].filter(Boolean).join(' · ')).replace(/[{}]/g, c => (c === '{' ? '&#123;' : '&#125;'))\n return (\n `<div style=\"width:100%;padding:0 12mm;display:flex;justify-content:space-between;font-family:'Malgun Gothic','Apple SD Gothic Neo','Noto Sans KR',sans-serif;` +\n `font-size:7.5pt;color:#${PALETTE.muted}\"><span>${left}</span><span><span class=\"pageNumber\"></span> / <span class=\"totalPages\"></span></span></div>`\n )\n}\n\n/** 「인력프로필-20261027.xlsx」 - the word in the reader's language, the day the profiles were taken. */\nexport function profileFileName(word: string, extension: 'xlsx' | 'pdf' | 'html', day = new Date()): string {\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${word}-${day.getFullYear()}${pad(day.getMonth() + 1)}${pad(day.getDate())}.${extension}`\n}\n\n/** A word as a document heads with it - its first letter capital where the language has capitals (「proyectos」 → 「Proyectos」). */\nexport function lead(word: string): string {\n return word ? word.charAt(0).toLocaleUpperCase() + word.slice(1) : word\n}\n\n/** The document's words from the server's translator - the reader's language, each as a heading begins. */\nexport function profileWordsOf(translate: (key: string, options?: any) => string): ProfileSheetWords {\n const t = (key: string, options?: any) => lead(translate(key, options))\n const p = (name: string) => t(`label.employee-profile-${name}`)\n return {\n title: t('text.employee-profile-doc-title'),\n rosterTitle: t('text.employee-profile-doc-roster'),\n expertise: t('text.employee-profile-doc-expertise'),\n name: t('field.name'),\n department: t('label.department'),\n jobPosition: t('label.job-position'),\n hiredOn: t('label.hired-on'),\n careerLength: p('career-length'),\n projectsDone: t('text.employee-profile-doc-projects-done'),\n certificatesHeld: t('text.employee-profile-doc-certificates-held'),\n summary: p('summary'),\n skills: p('skills'),\n educations: p('educations'),\n certificates: p('certificates'),\n careers: p('careers'),\n projects: p('projects'),\n school: p('school'),\n major: p('major'),\n degree: p('degree'),\n period: p('period'),\n certificate: p('certificate'),\n issuer: p('issuer'),\n acquiredOn: p('acquired-on'),\n company: p('company'),\n position: p('position'),\n duties: p('duties'),\n project: p('project'),\n client: p('client'),\n role: p('role'),\n technologies: p('technologies'),\n ongoing: t('text.employee-profile-doc-ongoing'),\n none: t('text.employee-profile-doc-none'),\n writtenOn: t('text.employee-profile-doc-written-on'),\n number: t('text.employee-profile-doc-number'),\n years: (years, months) => t('text.employee-profile-doc-years', { years, months }),\n projectCount: n => t('text.employee-profile-doc-project-count', { n }),\n certificateCount: n => t('text.employee-profile-doc-certificate-count', { n }),\n peopleCount: n => t('text.employee-profile-doc-people', { n }),\n averageCareer: t('text.employee-profile-doc-average-career')\n }\n}\n"]}
1
+ {"version":3,"file":"employee-profile-document.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-document.ts"],"names":[],"mappings":"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","sourcesContent":["import { Borders, Style, Workbook, Worksheet } from 'exceljs'\n\nimport { newestFirst, todayOf } from './employee-profile-rules'\n\n/*\n * The employee profiles a quotation attaches, as a document a person can hand in as it is (ADR-0169 decisions 6 · 8):\n * a page a person, made to show what the person is worth - the name large with where they stand, the figures a buyer\n * weighs (total experience, projects delivered, certificates held), the expertise in their own words and skills, then\n * the projects first, the careers, certificates and education - laid out for A4. Several people open with a roster.\n *\n * One layout (`profileSheetLayout`, `rosterLayout`) is painted twice: as an Excel workbook, a sheet a page\n * (`profileWorkbook`), and as HTML printed to PDF, a page break a sheet (`profileHtml`). Pure - the door reads the data\n * and the pdf module prints.\n */\n\n/** A row of any of the four tables - each has some of these. */\ntype Row = {\n school?: string\n major?: string\n degree?: string\n name?: string\n issuer?: string\n acquiredOn?: string\n company?: string\n department?: string\n position?: string\n duties?: string\n client?: string\n role?: string\n technologies?: string\n startedOn?: string\n endedOn?: string\n}\n\nexport type ProfilePerson = {\n name?: string | null\n departmentName?: string | null\n jobPosition?: string | null\n jobResponsibility?: string | null\n hiredOn?: string | null\n profile?: {\n summary?: string | null\n skills?: string[] | null\n educations?: Row[] | null\n certificates?: Row[] | null\n careers?: Row[] | null\n projects?: Row[] | null\n } | null\n}\n\n/** The words of the document, in the reader's language - handed in so this stays free of i18next. */\nexport type ProfileSheetWords = Record<\n | 'title'\n | 'rosterTitle'\n | 'expertise'\n | 'name'\n | 'department'\n | 'jobPosition'\n | 'hiredOn'\n | 'careerLength'\n | 'projectsDone'\n | 'certificatesHeld'\n | 'summary'\n | 'skills'\n | 'educations'\n | 'certificates'\n | 'careers'\n | 'projects'\n | 'school'\n | 'major'\n | 'degree'\n | 'period'\n | 'certificate'\n | 'issuer'\n | 'acquiredOn'\n | 'company'\n | 'position'\n | 'duties'\n | 'project'\n | 'client'\n | 'role'\n | 'technologies'\n | 'ongoing'\n | 'none'\n | 'writtenOn'\n | 'averageCareer'\n | 'number',\n string\n> & {\n /** 「12년 3개월」 */\n years: (years: number, months: number) => string\n /** 「8건」 */\n projectCount: (count: number) => string\n /** 「3개」 */\n certificateCount: (count: number) => string\n /** 「5명」 */\n peopleCount: (count: number) => string\n}\n\n/** What a cell is - the painter styles by it. */\nexport type CellRole =\n | 'company'\n | 'kicker'\n | 'name'\n | 'tagline'\n | 'rule'\n | 'statLabel'\n | 'statValue'\n | 'section'\n | 'summary'\n | 'label'\n | 'skills'\n | 'head'\n | 'value'\n | 'none'\n\n/**\n * A cell of the six-column grid: `col` from 1, spanning `span` columns and `rows` lines - the lines below leave its\n * columns out. A cell over several lines keeps its text where the first line has it, at the top.\n */\nexport type LayoutCell = { col: number; span?: number; rows?: number; value: string; role: CellRole }\n\n/** A line of the grid; `zebra` shades every other row of a table. */\nexport type LayoutLine = { cells: LayoutCell[]; height?: number; zebra?: boolean }\n\n/** The grid's six columns, in characters - together about the width of A4 in portrait. */\nexport const COLUMN_WIDTHS = [18, 20, 15, 12, 21, 18]\n\n/** The roster's six columns: a narrow number, then who - its career spans the last two, its skills the whole line. */\nexport const ROSTER_WIDTHS = [6, 24, 24, 18, 16, 16]\n\n/** 「2023.03」 from 「2023-03」 or 「2023-03-02」 - the dotted form a staffing profile is read in. */\nexport function dotted(day?: string | null): string {\n return (day ?? '').trim().replace(/-/g, '.')\n}\n\n/** A period as one cell - an open end is still going on. */\nexport function periodOf(startedOn: string | undefined, endedOn: string | undefined, ongoing: string): string {\n if (!startedOn && !endedOn) return ''\n return `${dotted(startedOn)} ~ ${endedOn ? dotted(endedOn) : ongoing}`.trim()\n}\n\nconst monthIndex = (day?: string | null): number | null => {\n const match = /^(\\d{4})-(\\d{2})/.exec((day ?? '').trim())\n return match ? Number(match[1]) * 12 + Number(match[2]) - 1 : null\n}\n\n/**\n * The months a person has worked: the careers before this company and the time here since the hire day, counted\n * once where they overlap. A career with no end runs to `today`; one with no start is left out.\n */\nexport function careerMonths(person: ProfilePerson, today = new Date()): number {\n const now = today.getFullYear() * 12 + today.getMonth()\n const months = new Set<number>()\n const spans = [\n ...(person.profile?.careers ?? []).map(row => [monthIndex(row.startedOn), row.endedOn ? monthIndex(row.endedOn) : now] as const),\n [monthIndex(person.hiredOn), now] as const\n ]\n for (const [from, to] of spans) {\n if (from === null || to === null) continue\n for (let month = from; month <= Math.min(to, now); month++) months.add(month)\n }\n return months.size\n}\n\nexport function careerLengthOf(person: ProfilePerson, words: ProfileSheetWords, today = new Date()): string {\n const months = careerMonths(person, today)\n return months ? words.years(Math.floor(months / 12), months % 12) : ''\n}\n\n/** Where the person stands, in one line: department · position / responsibility · hired on. */\nexport function taglineOf(person: ProfilePerson, words: ProfileSheetWords): string {\n const role = [person.jobPosition, person.jobResponsibility].filter(Boolean).join(' / ')\n return [person.departmentName, role, person.hiredOn ? `${words.hiredOn} ${dotted(person.hiredOn)}` : ''].filter(Boolean).join(' · ')\n}\n\n/** The head every page opens with: the employer and what the page is, the name large, a line under it. */\nfunction headOf(company: string, kicker: string, name: string, tagline: string): LayoutLine[] {\n return [\n {\n cells: [\n { col: 1, span: 3, value: company, role: 'company' },\n { col: 4, span: 3, value: kicker, role: 'kicker' }\n ]\n },\n { cells: [{ col: 1, span: 6, value: name, role: 'name' }], height: 40 },\n { cells: [{ col: 1, span: 6, value: tagline, role: 'tagline' }], height: 20 },\n { cells: [{ col: 1, span: 6, value: '', role: 'rule' }], height: 6 }\n ]\n}\n\n/** One person's page, line by line. `company` is the employer's name; `today` the day it is written. */\nexport function profileSheetLayout(person: ProfilePerson, words: ProfileSheetWords, company: string, today = new Date()): LayoutLine[] {\n const profile = person.profile ?? {}\n const lines: LayoutLine[] = [...headOf(company, words.title, person.name ?? '', taglineOf(person, words))]\n const gap = (height = 12) => lines.push({ cells: [], height })\n const section = (title: string) => {\n gap(16)\n lines.push({ cells: [{ col: 1, span: 6, value: title, role: 'section' }], height: 24 })\n gap(6)\n }\n\n /* A table: its head and its rows in the columns given as [col, span], every other row shaded; none says so. */\n const table = (title: string, columns: [number, number, string][], rows: Row[] | null | undefined, cells: (row: Row) => (string | undefined)[]) => {\n section(title)\n lines.push({ cells: columns.map(([col, span, head]) => ({ col, span, value: head, role: 'head' })) })\n if (!rows?.length) return lines.push({ cells: [{ col: 1, span: 6, value: words.none, role: 'none' }] })\n rows.forEach((row, index) =>\n lines.push({\n cells: cells(row).map((text, at) => ({ col: columns[at][0], span: columns[at][1], value: text ?? '', role: 'value' })),\n ...(index % 2 ? { zebra: true } : {})\n })\n )\n }\n\n /* The figures a buyer weighs first. */\n const projects = profile.projects?.length ?? 0\n const certificates = profile.certificates?.length ?? 0\n gap(14)\n lines.push({\n cells: [\n { col: 1, span: 2, value: words.careerLength, role: 'statLabel' },\n { col: 3, span: 2, value: words.projectsDone, role: 'statLabel' },\n { col: 5, span: 2, value: words.certificatesHeld, role: 'statLabel' }\n ],\n height: 20\n })\n lines.push({\n cells: [\n { col: 1, span: 2, value: careerLengthOf(person, words, today) || '—', role: 'statValue' },\n { col: 3, span: 2, value: projects ? words.projectCount(projects) : '—', role: 'statValue' },\n { col: 5, span: 2, value: certificates ? words.certificateCount(certificates) : '—', role: 'statValue' }\n ],\n height: 34\n })\n\n section(words.expertise)\n if (profile.summary?.trim()) lines.push({ cells: [{ col: 1, span: 6, value: profile.summary.trim(), role: 'summary' }] })\n lines.push({\n cells: [\n { col: 1, value: words.skills, role: 'label' },\n { col: 2, span: 5, value: (profile.skills ?? []).join(', '), role: 'skills' }\n ]\n })\n\n table(\n words.projects,\n [[1, 1, words.period], [2, 1, words.project], [3, 1, words.client], [4, 1, words.role], [5, 1, words.duties], [6, 1, words.technologies]],\n newestFirst(profile.projects),\n row => [periodOf(row.startedOn, row.endedOn, words.ongoing), row.name, row.client, row.role, row.duties, row.technologies]\n )\n table(\n words.careers,\n [[1, 1, words.period], [2, 1, words.company], [3, 1, words.department], [4, 1, words.position], [5, 2, words.duties]],\n newestFirst(profile.careers),\n row => [periodOf(row.startedOn, row.endedOn, words.ongoing), row.company, row.department, row.position, row.duties]\n )\n table(words.certificates, [[1, 1, words.acquiredOn], [2, 3, words.certificate], [5, 2, words.issuer]], newestFirst(profile.certificates), row => [\n dotted(row.acquiredOn),\n row.name,\n row.issuer\n ])\n table(words.educations, [[1, 1, words.period], [2, 2, words.school], [4, 2, words.major], [6, 1, words.degree]], newestFirst(profile.educations), row => [\n periodOf(row.startedOn, row.endedOn, words.ongoing),\n row.school,\n row.major,\n row.degree\n ])\n return lines\n}\n\n/** How many people, and their experience on average - the team's weight in one line. */\nexport function rosterTaglineOf(people: ProfilePerson[], words: ProfileSheetWords, today = new Date()): string {\n const months = people.map(person => careerMonths(person, today))\n const average = people.length ? Math.round(months.reduce((sum, one) => sum + one, 0) / people.length) : 0\n return [words.peopleCount(people.length), average ? `${words.averageCareer} ${words.years(Math.floor(average / 12), average % 12)}` : ''].filter(Boolean).join(' · ')\n}\n\n/** The roster that opens a document of several people - one line a person, in the order picked. */\nexport function rosterLayout(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): LayoutLine[] {\n return [\n ...headOf(company, `${words.writtenOn} ${dotted(todayOf(today))}`, words.rosterTitle, rosterTaglineOf(people, words, today)),\n { cells: [], height: 16 },\n {\n cells: [\n ...[words.number, words.name, words.department, words.jobPosition].map((value, index) => ({ col: index + 1, value, role: 'head' as const })),\n { col: 5, span: 2, value: words.careerLength, role: 'head' as const }\n ]\n },\n /*\n * Two lines a person: who, then the skills under the name across the rest of the page - a list too long for one\n * column of six. The number runs down both lines, so it marks where a person starts; a person with no skills\n * written keeps one line.\n */\n ...people.flatMap((person, index) => {\n const shade = index % 2 ? { zebra: true } : {}\n const skills = (person.profile?.skills ?? []).join(', ')\n return [\n {\n cells: [\n { col: 1, rows: skills ? 2 : 1, value: String(index + 1), role: 'value' as const },\n ...[person.name ?? '', person.departmentName ?? '', person.jobPosition ?? ''].map((value, column) => ({ col: column + 2, value, role: 'value' as const })),\n { col: 5, span: 2, value: careerLengthOf(person, words, today), role: 'value' as const }\n ],\n ...shade\n },\n ...(skills\n ? [\n {\n cells: [{ col: 2, span: 5, value: skills, role: 'value' as const }],\n ...shade\n }\n ]\n : [])\n ]\n })\n ]\n}\n\n/**\n * A sheet name for each person. Excel takes at most 31 characters, none of \\ / ? * [ ] :, and no two alike ignoring\n * case - two people of one name become 「홍길동」 and 「홍길동 (2)」. `reserved` are names already in the book.\n */\nexport function sheetNamesOf(names: (string | null | undefined)[], reserved: string[] = []): string[] {\n const taken = new Set<string>(reserved.map(name => name.toLowerCase()))\n return names.map((name, index) => {\n const base = (name ?? '').replace(/[\\\\/?*[\\]:]/g, ' ').replace(/^'+|'+$/g, '').trim() || `#${index + 1}`\n let candidate = base.slice(0, 31)\n for (let n = 2; taken.has(candidate.toLowerCase()); n++) {\n const tail = ` (${n})`\n candidate = base.slice(0, 31 - tail.length) + tail\n }\n taken.add(candidate.toLowerCase())\n return candidate\n })\n}\n\n/** The document's colours - a deep navy for what leads the eye, a pale blue-grey ground, quiet lines. */\nexport const PALETTE = { navy: '1F3A5F', ground: 'EEF3F8', zebra: 'F7F9FB', line: 'C9D2DC', ink: '17242C', muted: '5F6B76' }\n\nconst FONT = 'Malgun Gothic'\nconst argb = (hex: string) => ({ argb: `FF${hex}` })\nconst LINE = { style: 'thin' as const, color: argb(PALETTE.line) }\nconst RULED: Partial<Borders> = { top: LINE, left: LINE, bottom: LINE, right: LINE }\nconst ground = (hex: string) => ({ type: 'pattern' as const, pattern: 'solid' as const, fgColor: argb(hex) })\nconst font = (size: number, extra: Partial<Style['font']> = {}) => ({ name: FONT, size, color: argb(PALETTE.ink), ...extra })\n\n/** How each role of cell is painted in Excel. */\nconst PAINT: Record<CellRole, Partial<Style>> = {\n company: { font: font(9, { color: argb(PALETTE.muted) }), alignment: { horizontal: 'left', vertical: 'bottom' } },\n kicker: { font: font(9, { bold: true, color: argb(PALETTE.navy) }), alignment: { horizontal: 'right', vertical: 'bottom' } },\n name: { font: font(22, { bold: true, color: argb(PALETTE.navy) }), alignment: { horizontal: 'left', vertical: 'bottom' } },\n tagline: { font: font(10.5, { color: argb(PALETTE.muted) }), alignment: { horizontal: 'left', vertical: 'top' } },\n rule: { border: { bottom: { style: 'thick', color: argb(PALETTE.navy) } } },\n statLabel: {\n font: font(9, { color: argb(PALETTE.muted) }),\n fill: ground(PALETTE.ground),\n alignment: { horizontal: 'center', vertical: 'bottom' },\n border: { top: { style: 'medium', color: argb(PALETTE.navy) } }\n },\n statValue: { font: font(16, { bold: true, color: argb(PALETTE.navy) }), fill: ground(PALETTE.ground), alignment: { horizontal: 'center', vertical: 'middle' } },\n section: { font: font(12, { bold: true, color: argb(PALETTE.navy) }), alignment: { horizontal: 'left', vertical: 'bottom' }, border: { bottom: { style: 'medium', color: argb(PALETTE.navy) } } },\n summary: {\n font: font(10.5),\n fill: ground(PALETTE.ground),\n alignment: { horizontal: 'left', vertical: 'middle', wrapText: true, indent: 1 },\n border: { left: { style: 'thick', color: argb(PALETTE.navy) } }\n },\n label: { font: font(9.5, { bold: true, color: argb(PALETTE.navy) }), fill: ground(PALETTE.ground), alignment: { horizontal: 'center', vertical: 'middle', wrapText: true }, border: RULED },\n skills: { font: font(10, { bold: true }), alignment: { horizontal: 'left', vertical: 'middle', wrapText: true, indent: 1 }, border: RULED },\n head: {\n font: font(9.5, { bold: true, color: argb('FFFFFF') }),\n fill: ground(PALETTE.navy),\n alignment: { horizontal: 'center', vertical: 'middle', wrapText: true },\n border: { top: { style: 'thin', color: argb(PALETTE.navy) }, bottom: { style: 'thin', color: argb(PALETTE.navy) }, left: LINE, right: LINE }\n },\n value: { font: font(9.5), alignment: { horizontal: 'left', vertical: 'middle', wrapText: true, indent: 1 }, border: RULED },\n none: { font: font(9.5, { color: argb(PALETTE.muted) }), alignment: { horizontal: 'center', vertical: 'middle' }, border: RULED }\n}\n\n/**\n * A line's height in points, for as many text lines as its longest boxed cell wraps into - Excel does not grow a row\n * for wrapped text written by a program. A full-width character is about two of the column's character units.\n */\nexport function heightOf(line: LayoutLine, widths = COLUMN_WIDTHS): number | undefined {\n const boxed = line.cells.filter(cell => ['label', 'skills', 'summary', 'head', 'value', 'none'].includes(cell.role))\n if (!boxed.length) return undefined\n const wraps = boxed.map(cell => {\n const width = widths.slice(cell.col - 1, cell.col - 1 + (cell.span ?? 1)).reduce((sum, one) => sum + one, 0) - (cell.role === 'summary' ? 4 : 1)\n return cell.value.split('\\n').reduce((lines, text) => {\n const units = [...text].reduce((sum, char) => sum + (char.charCodeAt(0) > 0x2e7f ? 1.9 : 0.9), 0)\n return lines + Math.max(1, Math.ceil(units / Math.max(width, 1)))\n }, 0)\n })\n const lines = Math.max(...wraps)\n return boxed.some(cell => cell.role === 'summary') ? lines * 16 + 14 : lines * 15 + 7\n}\n\n/** Paint a layout on a sheet: values, spans merged, each cell of a span painted so a boxed cell is boxed all round. */\nexport function paintSheet(sheet: Worksheet, lines: LayoutLine[], footer = '', widths = COLUMN_WIDTHS) {\n widths.forEach((width, index) => (sheet.getColumn(index + 1).width = width))\n lines.forEach((line, index) => {\n const row = sheet.getRow(index + 1)\n const height = Math.max(line.height ?? 0, heightOf(line, widths) ?? 0)\n if (height) row.height = height\n for (const cell of line.cells) {\n const span = cell.span ?? 1\n const style = line.zebra && cell.role === 'value' ? { ...PAINT.value, fill: ground(PALETTE.zebra) } : PAINT[cell.role]\n const rows = cell.rows ?? 1\n const painted = rows > 1 ? { ...style, alignment: { ...style.alignment, vertical: 'top' as const } } : style\n for (let at = 0; at < rows; at++) for (let col = cell.col; col < cell.col + span; col++) Object.assign(sheet.getRow(index + 1 + at).getCell(col), { style: painted })\n row.getCell(cell.col).value = cell.value\n if (span > 1 || rows > 1) sheet.mergeCells(index + 1, cell.col, index + rows, cell.col + span - 1)\n }\n })\n sheet.views = [{ showGridLines: false }]\n sheet.pageSetup = {\n paperSize: 9,\n orientation: 'portrait',\n fitToPage: true,\n fitToWidth: 1,\n fitToHeight: 0,\n horizontalCentered: true,\n margins: { left: 0.5, right: 0.5, top: 0.6, bottom: 0.7, header: 0.3, footer: 0.3 }\n }\n /* The employer at the foot of every printed page, and the page of how many. `&` is Excel's escape. */\n sheet.headerFooter = { oddFooter: `&L&8${footer.replace(/&/g, '&&')}&R&8&P / &N` }\n}\n\n/** The workbook of the people given, in their order - opened by a roster when there are several. */\nexport function profileWorkbook(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): Workbook {\n const book = new Workbook()\n const footer = [company, words.title].filter(Boolean).join(' · ')\n /* The roster's name follows Excel's rules as the people's do. */\n const roster = people.length > 1 ? sheetNamesOf([words.rosterTitle]) : []\n if (roster.length) paintSheet(book.addWorksheet(roster[0]), rosterLayout(people, words, company, today), footer, ROSTER_WIDTHS)\n const names = sheetNamesOf(people.map(person => person.name), roster)\n people.forEach((person, index) => paintSheet(book.addWorksheet(names[index]), profileSheetLayout(person, words, company, today), footer))\n return book\n}\n\nconst escapeHtml = (text: string) => text.replace(/[&<>\"]/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;' })[c]!)\n\n/** A cell's content as HTML: skills as tags, line breaks kept, everything escaped. */\nfunction cellHtml(cell: LayoutCell): string {\n if (cell.role === 'skills') {\n return cell.value\n .split(', ')\n .filter(Boolean)\n .map(skill => `<span class=\"tag\">${escapeHtml(skill)}</span>`)\n .join('')\n }\n return escapeHtml(cell.value).replace(/\\n/g, '<br>')\n}\n\n/** The same layout as HTML: a table of the six columns a page, the roles as classes. */\nexport function layoutHtml(lines: LayoutLine[], widths = COLUMN_WIDTHS): string {\n const total = widths.reduce((sum, width) => sum + width, 0)\n const columns = widths.map(width => `<col style=\"width:${((width / total) * 100).toFixed(2)}%\">`).join('')\n /* How many more lines each column is still held by a cell from a line above. */\n const held = [0, 0, 0, 0, 0, 0, 0]\n const rows = lines.map(line => {\n const style = line.height ? ` style=\"height:${Math.round(line.height * 1.33)}px\"` : ''\n const covered = held.map(lines => lines > 0)\n for (let col = 1; col <= 6; col++) held[col] = Math.max(0, held[col] - 1)\n if (!line.cells.length) return `<tr class=\"gap\"${style}><td colspan=\"6\"></td></tr>`\n const cells: string[] = []\n /* Empty columns between cells, as runs that leave out the columns a cell above still holds. */\n const fill = (from: number, to: number) => {\n for (let col = from; col < to; ) {\n if (covered[col]) {\n col++\n continue\n }\n let end = col\n while (end < to && !covered[end]) end++\n cells.push(`<td colspan=\"${end - col}\"></td>`)\n col = end\n }\n }\n let next = 1\n for (const cell of line.cells) {\n fill(next, cell.col)\n const span = cell.span ?? 1\n const rows = cell.rows ?? 1\n for (let col = cell.col; col < cell.col + span; col++) held[col] = rows - 1\n const attributes = `${span > 1 ? ` colspan=\"${span}\"` : ''}${rows > 1 ? ` rowspan=\"${rows}\" style=\"vertical-align:top\"` : ''}`\n cells.push(`<td class=\"${cell.role}\"${attributes}>${cellHtml(cell)}</td>`)\n next = cell.col + span\n }\n fill(next, 7)\n return `<tr${line.zebra ? ' class=\"zebra\"' : ''}${style}>${cells.join('')}</tr>`\n })\n return `<table><colgroup>${columns}</colgroup>${rows.join('')}</table>`\n}\n\n/** How the roles look on paper - the workbook's paint in CSS. */\nexport const PROFILE_CSS = `\nbody { margin: 0; font-family: 'Pretendard', 'Malgun Gothic', 'Apple SD Gothic Neo', 'Noto Sans KR', sans-serif; font-size: 9.5pt; color: #${PALETTE.ink};\n -webkit-print-color-adjust: exact; print-color-adjust: exact }\n.sheet { break-after: page }\n.sheet:last-child { break-after: auto }\ntable { width: 100%; border-collapse: collapse; table-layout: fixed }\ntd { padding: 5px 7px; vertical-align: middle; word-break: keep-all; overflow-wrap: anywhere; line-height: 1.45 }\ntr.gap td { padding: 0 }\ntd.company { font-size: 8.5pt; color: #${PALETTE.muted}; padding: 0 0 2px }\ntd.kicker { font-size: 8.5pt; font-weight: 700; color: #${PALETTE.navy}; text-align: right; letter-spacing: 0.08em; padding: 0 0 2px }\ntd.name { font-size: 24pt; font-weight: 800; color: #${PALETTE.navy}; letter-spacing: 0.02em; padding: 6px 0 0; vertical-align: bottom }\ntd.tagline { font-size: 10.5pt; color: #${PALETTE.muted}; padding: 2px 0 8px; vertical-align: top }\ntd.rule { border-bottom: 3px solid #${PALETTE.navy}; padding: 0 }\ntd.statLabel { background: #${PALETTE.ground}; border-top: 2px solid #${PALETTE.navy}; text-align: center; font-size: 8.5pt; color: #${PALETTE.muted}; padding: 8px 0 0 }\ntd.statValue { background: #${PALETTE.ground}; text-align: center; font-size: 17pt; font-weight: 800; color: #${PALETTE.navy}; padding: 0 0 8px }\ntd.statLabel + td.statLabel, td.statValue + td.statValue { border-left: 8px solid #fff }\ntd.section { font-size: 12pt; font-weight: 800; color: #${PALETTE.navy}; border-bottom: 2px solid #${PALETTE.navy}; padding: 0 0 4px; vertical-align: bottom }\ntd.summary { background: #${PALETTE.ground}; border-left: 4px solid #${PALETTE.navy}; font-size: 10.5pt; padding: 10px 14px }\ntd.label { background: #${PALETTE.ground}; color: #${PALETTE.navy}; font-weight: 700; text-align: center; border: 1px solid #${PALETTE.line} }\ntd.skills { border: 1px solid #${PALETTE.line}; padding: 6px 8px }\n.tag { display: inline-block; margin: 2px 4px 2px 0; padding: 2px 9px; border-radius: 10px; background: #${PALETTE.navy}; color: #fff; font-size: 8.5pt; font-weight: 600 }\ntd.head { background: #${PALETTE.navy}; color: #fff; font-weight: 700; text-align: center; border: 1px solid #${PALETTE.navy}; font-size: 9pt }\ntd.value { border: 1px solid #${PALETTE.line} }\ntr.zebra td.value { background: #${PALETTE.zebra} }\ntd.none { border: 1px solid #${PALETTE.line}; color: #${PALETTE.muted}; text-align: center }\ntr { break-inside: avoid }\n`\n\n/** On a screen, the pages as sheets of A4 on a grey desk - the preview reads as the PDF will (ADR-0169 decision 9). */\nexport const PROFILE_SCREEN_CSS = `\n@media screen {\n html { background: #e9edf1 }\n body { padding: 24px 0 }\n .sheet { box-sizing: border-box; width: 210mm; min-height: 297mm; margin: 0 auto 24px; padding: 14mm 12mm; background: #fff;\n box-shadow: 0 1px 3px rgba(23, 36, 44, .12), 0 8px 24px rgba(23, 36, 44, .08) }\n}\n`\n\n/** The preview: the same pages as one HTML document, to be shown in a frame. */\nexport function profilePreviewHtml(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): string {\n return `<!doctype html><html><head><meta charset=\"utf-8\"><style>${PROFILE_CSS}${PROFILE_SCREEN_CSS}</style></head><body>${profileHtml(people, words, company, today)}</body></html>`\n}\n\n/** The document as one HTML page set: the roster first when there are several, then a page a person. */\nexport function profileHtml(people: ProfilePerson[], words: ProfileSheetWords, company: string, today = new Date()): string {\n const sheets: [LayoutLine[], number[]][] = [\n ...(people.length > 1 ? [[rosterLayout(people, words, company, today), ROSTER_WIDTHS] as [LayoutLine[], number[]]] : []),\n ...people.map(person => [profileSheetLayout(person, words, company, today), COLUMN_WIDTHS] as [LayoutLine[], number[]])\n ]\n return sheets.map(([lines, widths]) => `<section class=\"sheet\">${layoutHtml(lines, widths)}</section>`).join('')\n}\n\n/** The foot of every printed PDF page: the employer and the document at the left, the page of how many at the right. */\nexport function profileFooterHtml(company: string, words: ProfileSheetWords): string {\n /* The footer is a Handlebars template in the pdf module - a brace in the name must not open one. */\n const left = escapeHtml([company, words.title].filter(Boolean).join(' · ')).replace(/[{}]/g, c => (c === '{' ? '&#123;' : '&#125;'))\n return (\n `<div style=\"width:100%;padding:0 12mm;display:flex;justify-content:space-between;font-family:'Malgun Gothic','Apple SD Gothic Neo','Noto Sans KR',sans-serif;` +\n `font-size:7.5pt;color:#${PALETTE.muted}\"><span>${left}</span><span><span class=\"pageNumber\"></span> / <span class=\"totalPages\"></span></span></div>`\n )\n}\n\n/** 「인력프로필-20261027.xlsx」 - the word in the reader's language, the day the profiles were taken. */\nexport function profileFileName(word: string, extension: 'xlsx' | 'pdf' | 'html', day = new Date()): string {\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${word}-${day.getFullYear()}${pad(day.getMonth() + 1)}${pad(day.getDate())}.${extension}`\n}\n\n/** A word as a document heads with it - its first letter capital where the language has capitals (「proyectos」 → 「Proyectos」). */\nexport function lead(word: string): string {\n return word ? word.charAt(0).toLocaleUpperCase() + word.slice(1) : word\n}\n\n/** The document's words from the server's translator - the reader's language, each as a heading begins. */\nexport function profileWordsOf(translate: (key: string, options?: any) => string): ProfileSheetWords {\n const t = (key: string, options?: any) => lead(translate(key, options))\n const p = (name: string) => t(`label.employee-profile-${name}`)\n return {\n title: t('text.employee-profile-doc-title'),\n rosterTitle: t('text.employee-profile-doc-roster'),\n expertise: t('text.employee-profile-doc-expertise'),\n name: t('field.name'),\n department: t('label.department'),\n jobPosition: t('label.job-position'),\n hiredOn: t('label.hired-on'),\n careerLength: p('career-length'),\n projectsDone: t('text.employee-profile-doc-projects-done'),\n certificatesHeld: t('text.employee-profile-doc-certificates-held'),\n summary: p('summary'),\n skills: p('skills'),\n educations: p('educations'),\n certificates: p('certificates'),\n careers: p('careers'),\n projects: p('projects'),\n school: p('school'),\n major: p('major'),\n degree: p('degree'),\n period: p('period'),\n certificate: p('certificate'),\n issuer: p('issuer'),\n acquiredOn: p('acquired-on'),\n company: p('company'),\n position: p('position'),\n duties: p('duties'),\n project: p('project'),\n client: p('client'),\n role: p('role'),\n technologies: p('technologies'),\n ongoing: t('text.employee-profile-doc-ongoing'),\n none: t('text.employee-profile-doc-none'),\n writtenOn: t('text.employee-profile-doc-written-on'),\n number: t('text.employee-profile-doc-number'),\n years: (years, months) => t('text.employee-profile-doc-years', { years, months }),\n projectCount: n => t('text.employee-profile-doc-project-count', { n }),\n certificateCount: n => t('text.employee-profile-doc-certificate-count', { n }),\n peopleCount: n => t('text.employee-profile-doc-people', { n }),\n averageCareer: t('text.employee-profile-doc-average-career')\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"employee-profile-mutation.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { requireMyEmployee } from '../employee/my-employee.js'\nimport { EmployeeProfile } from './employee-profile'\nimport { addedProfileOf, profileDocumentOf } from './employee-profile-rules'\nimport { EmployeeProfileInput } from './employee-profile-type'\n\n/*\n * The employee writes their own profile and nobody else's (ADR-0169 decisions 3 · 4) - no door changes another\n * person's. It is saved as one document, as the screen holds it.\n */\n@Resolver(EmployeeProfile)\nexport class EmployeeProfileMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"employee-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => EmployeeProfile, {\n description: \"Saves the caller's own profile whole - what is left out is emptied. Refused when the account is not linked to exactly one employee.\"\n })\n async saveMyEmployeeProfile(@Arg('profile', type => EmployeeProfileInput) profile: EmployeeProfileInput, @Ctx() context: ResolverContext): Promise<EmployeeProfile> {\n const { domain, user, tx } = context.state\n const employee = await requireMyEmployee(context)\n const repository = getRepository(EmployeeProfile, tx)\n const held = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: employee.id } } })\n\n const saved = await repository.save({\n ...(held ?? { domain, employee, creator: user }),\n ...profileDocumentOf(profile),\n updater: user\n } as EmployeeProfile)\n\n return await repository.findOne({ where: { id: saved.id } })\n }\n\n /*\n * What the assistant read from a résumé the person attached, added to their own profile once they press the card\n * (ADR-0169 decision 10): nothing kept is taken away - a given summary takes the summary's place, skills and rows\n * are added unless already there.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"employee-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => EmployeeProfile, {\n description: \"Adds to the caller's own profile: a given summary replaces the summary, skills and rows are added after those held unless already there. Refused when the account is not linked to exactly one employee.\"\n })\n async addToMyEmployeeProfile(@Arg('profile', type => EmployeeProfileInput) profile: EmployeeProfileInput, @Ctx() context: ResolverContext): Promise<EmployeeProfile> {\n const { domain, user, tx } = context.state\n const employee = await requireMyEmployee(context)\n const repository = getRepository(EmployeeProfile, tx)\n const held = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: employee.id } } })\n\n const saved = await repository.save({\n ...(held ?? { domain, employee, creator: user }),\n ...addedProfileOf(held as any, profile),\n updater: user\n } as EmployeeProfile)\n\n return await repository.findOne({ where: { id: saved.id } })\n }\n}\n"]}
1
+ {"version":3,"file":"employee-profile-mutation.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { requireMyEmployee } from '../employee/my-employee.js'\nimport { EmployeeProfile } from './employee-profile'\nimport { addedProfileOf, profileDocumentOf } from './employee-profile-rules'\nimport { EmployeeProfileInput } from './employee-profile-type'\n\n/*\n * The employee writes their own profile and nobody else's (ADR-0169 decisions 3 · 4) - no door changes another\n * person's. It is saved as one document, as the screen holds it.\n */\n@Resolver(EmployeeProfile)\nexport class EmployeeProfileMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"employee-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => EmployeeProfile, {\n description: \"Saves the caller's own profile whole - what is left out is emptied. Refused when the account is not linked to exactly one employee.\"\n })\n async saveMyEmployeeProfile(@Arg('profile', type => EmployeeProfileInput) profile: EmployeeProfileInput, @Ctx() context: ResolverContext): Promise<EmployeeProfile> {\n const { domain, user, tx } = context.state\n const employee = await requireMyEmployee(context)\n const repository = getRepository(EmployeeProfile, tx)\n const held = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: employee.id } } })\n\n const saved = await repository.save({\n ...(held ?? { domain, employee, creator: user }),\n ...profileDocumentOf(profile),\n updater: user\n } as Partial<EmployeeProfile>)\n\n return await repository.findOne({ where: { id: saved.id } })\n }\n\n /*\n * What the assistant read from a résumé the person attached, added to their own profile once they press the card\n * (ADR-0169 decision 10): nothing kept is taken away - a given summary takes the summary's place, skills and rows\n * are added unless already there.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"employee-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => EmployeeProfile, {\n description: \"Adds to the caller's own profile: a given summary replaces the summary, skills and rows are added after those held unless already there. Refused when the account is not linked to exactly one employee.\"\n })\n async addToMyEmployeeProfile(@Arg('profile', type => EmployeeProfileInput) profile: EmployeeProfileInput, @Ctx() context: ResolverContext): Promise<EmployeeProfile> {\n const { domain, user, tx } = context.state\n const employee = await requireMyEmployee(context)\n const repository = getRepository(EmployeeProfile, tx)\n const held = await repository.findOne({ where: { domain: { id: domain.id }, employee: { id: employee.id } } })\n\n const saved = await repository.save({\n ...(held ?? { domain, employee, creator: user }),\n ...addedProfileOf(held as any, profile),\n updater: user\n } as Partial<EmployeeProfile>)\n\n return await repository.findOne({ where: { id: saved.id } })\n }\n}\n"]}
@@ -58,4 +58,16 @@ export declare function employeesWithProfiles<P extends {
58
58
  }[];
59
59
  /** Today in the server's calendar, YYYY-MM-DD - the form `retiredOn` is kept in. */
60
60
  export declare function todayOf(now?: Date): string;
61
+ /**
62
+ * Newest first, as a résumé reads. A period is ordered by its end - one still going (no end) on top - and two that ended
63
+ * together by the later start; a day (a certificate's) by the day. A row with no date keeps its place, after the dated
64
+ * ones. Only the document is ordered; the profile keeps the rows as they were written.
65
+ */
66
+ export declare function newestFirst<R extends {
67
+ startedOn?: string;
68
+ endedOn?: string;
69
+ acquiredOn?: string;
70
+ }>(rows: R[] | null | undefined): R[];
71
+ /** A profile's dated rows newest first, as every reader is shown them - the screen, the document and the assistant. */
72
+ export declare function inShowingOrder<P extends Partial<Record<'educations' | 'certificates' | 'careers' | 'projects', any[] | null>>>(profile: P): P;
61
73
  export {};
@@ -10,6 +10,8 @@ exports.addedProfileOf = addedProfileOf;
10
10
  exports.isActiveEmployee = isActiveEmployee;
11
11
  exports.employeesWithProfiles = employeesWithProfiles;
12
12
  exports.todayOf = todayOf;
13
+ exports.newestFirst = newestFirst;
14
+ exports.inShowingOrder = inShowingOrder;
13
15
  /** The fields each kind of row keeps; anything else a caller sends is not stored. */
14
16
  exports.PROFILE_ROW_FIELDS = {
15
17
  educations: ['school', 'major', 'degree', 'startedOn', 'endedOn'],
@@ -101,4 +103,27 @@ function todayOf(now = new Date()) {
101
103
  const pad = (n) => String(n).padStart(2, '0');
102
104
  return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
103
105
  }
106
+ /**
107
+ * Newest first, as a résumé reads. A period is ordered by its end - one still going (no end) on top - and two that ended
108
+ * together by the later start; a day (a certificate's) by the day. A row with no date keeps its place, after the dated
109
+ * ones. Only the document is ordered; the profile keeps the rows as they were written.
110
+ */
111
+ function newestFirst(rows) {
112
+ const ONGOING = '9999-99';
113
+ const endOf = (row) => (row.acquiredOn ?? row.endedOn ?? (row.startedOn ? ONGOING : '')).trim();
114
+ const startOf = (row) => (row.acquiredOn ?? row.startedOn ?? '').trim();
115
+ return [...(rows ?? [])].sort((a, b) => {
116
+ const [endA, endB] = [endOf(a), endOf(b)];
117
+ if (!endA || !endB)
118
+ return Number(!endA) - Number(!endB);
119
+ return endB.localeCompare(endA) || startOf(b).localeCompare(startOf(a));
120
+ });
121
+ }
122
+ /** A profile's dated rows newest first, as every reader is shown them - the screen, the document and the assistant. */
123
+ function inShowingOrder(profile) {
124
+ for (const kind of ['educations', 'certificates', 'careers', 'projects'])
125
+ if (Array.isArray(profile[kind]))
126
+ profile[kind] = newestFirst(profile[kind]);
127
+ return profile;
128
+ }
104
129
  //# sourceMappingURL=employee-profile-rules.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"employee-profile-rules.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-rules.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The judgements of the profile's doors (ADR-0169) - pure, apart from the store, so the tests read them without the\n * entities (the employee record pulls in contact, which reads the configuration when it is loaded).\n */\n\ntype Row = Record<string, unknown>\n\nexport type ProfileDocument = {\n summary: string | null\n skills: string[]\n educations: Row[]\n certificates: Row[]\n careers: Row[]\n projects: Row[]\n}\n\n/** The fields each kind of row keeps; anything else a caller sends is not stored. */\nexport const PROFILE_ROW_FIELDS = {\n educations: ['school', 'major', 'degree', 'startedOn', 'endedOn'],\n certificates: ['name', 'issuer', 'acquiredOn'],\n careers: ['company', 'department', 'position', 'startedOn', 'endedOn', 'duties'],\n projects: ['name', 'client', 'startedOn', 'endedOn', 'role', 'duties', 'technologies']\n} as const\n\nconst text = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\n/** A row as kept: its own fields trimmed, empty ones left out. A row with nothing in it is no row. */\nfunction rowsOf(rows: unknown, fields: readonly string[]): Row[] {\n if (!Array.isArray(rows)) return []\n return rows.flatMap(row => {\n const kept: Row = {}\n for (const field of fields) {\n const value = text((row as Row | null)?.[field])\n if (value) kept[field] = value\n }\n return Object.keys(kept).length ? [kept] : []\n })\n}\n\n/**\n * The profile as it is saved - whole, as the screen sent it (ADR-0169 decision 2). Blank rows the screen added and did\n * not fill go, and a skill written twice is kept once.\n */\nexport function profileDocumentOf(input: any): ProfileDocument {\n const skills = [...new Set((Array.isArray(input?.skills) ? input.skills : []).map(text).filter(Boolean))] as string[]\n return {\n summary: text(input?.summary) || null,\n skills,\n educations: rowsOf(input?.educations, PROFILE_ROW_FIELDS.educations),\n certificates: rowsOf(input?.certificates, PROFILE_ROW_FIELDS.certificates),\n careers: rowsOf(input?.careers, PROFILE_ROW_FIELDS.careers),\n projects: rowsOf(input?.projects, PROFILE_ROW_FIELDS.projects)\n }\n}\n\n/** Two rows are the same entry when every field they keep is the same - spacing and letter case aside. */\nconst sameRow = (a: Row, b: Row) => {\n const keys = new Set([...Object.keys(a), ...Object.keys(b)])\n return [...keys].every(key => text(a[key]).toLowerCase() === text(b[key]).toLowerCase())\n}\n\n/**\n * What is added to a profile kept so far (ADR-0169 decision 10 - the assistant's 입력안 from a résumé): a summary given\n * takes the place of the one kept, skills are added after those held (a skill already held is not added twice), and\n * rows are added after those of their section unless the very same row is there. Nothing kept is taken away.\n */\nexport function addedProfileOf(held: Partial<ProfileDocument> | null | undefined, addition: any): ProfileDocument {\n const kept = profileDocumentOf(held ?? {})\n const added = profileDocumentOf(addition)\n const rows = (key: keyof typeof PROFILE_ROW_FIELDS) => [...kept[key], ...added[key].filter(row => !kept[key].some(one => sameRow(one, row)))]\n return {\n summary: added.summary ?? kept.summary,\n skills: [...kept.skills, ...added.skills.filter(skill => !kept.skills.some(one => one.toLowerCase() === skill.toLowerCase()))],\n educations: rows('educations'),\n certificates: rows('certificates'),\n careers: rows('careers'),\n projects: rows('projects')\n }\n}\n\nexport type ProfileEmployee = {\n id: string\n controlNo?: string\n name?: string\n active?: boolean | null\n retiredOn?: string | null\n jobPosition?: string\n jobResponsibility?: string\n hiredOn?: string\n department?: { name?: string } | null\n}\n\n/** Still working here: not marked inactive, and no retire day that has come. `today` is YYYY-MM-DD. */\nexport function isActiveEmployee(employee: ProfileEmployee, today: string): boolean {\n if (employee.active === false) return false\n return !employee.retiredOn || employee.retiredOn > today\n}\n\n/**\n * Every active employee with their profile, by name (ADR-0169 decision 4) - an employee who has written none is listed\n * with an empty one, so the list says who has not written it rather than leaving them out.\n */\nexport function employeesWithProfiles<P extends { employeeId?: string }>(employees: ProfileEmployee[], profiles: P[], today: string) {\n const byEmployee = new Map(profiles.map(profile => [profile.employeeId, profile]))\n return employees\n .filter(employee => isActiveEmployee(employee, today))\n .map(employee => ({\n employeeId: employee.id,\n controlNo: employee.controlNo,\n name: employee.name,\n departmentName: employee.department?.name,\n jobPosition: employee.jobPosition,\n jobResponsibility: employee.jobResponsibility,\n hiredOn: employee.hiredOn,\n profile: byEmployee.get(employee.id) ?? null\n }))\n .sort((a, b) => (a.name ?? '').localeCompare(b.name ?? '', 'ko') || (a.controlNo ?? '').localeCompare(b.controlNo ?? ''))\n}\n\n/** Today in the server's calendar, YYYY-MM-DD - the form `retiredOn` is kept in. */\nexport function todayOf(now = new Date()): string {\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`\n}\n"]}
1
+ {"version":3,"file":"employee-profile-rules.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-rules.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The judgements of the profile's doors (ADR-0169) - pure, apart from the store, so the tests read them without the\n * entities (the employee record pulls in contact, which reads the configuration when it is loaded).\n */\n\ntype Row = Record<string, unknown>\n\nexport type ProfileDocument = {\n summary: string | null\n skills: string[]\n educations: Row[]\n certificates: Row[]\n careers: Row[]\n projects: Row[]\n}\n\n/** The fields each kind of row keeps; anything else a caller sends is not stored. */\nexport const PROFILE_ROW_FIELDS = {\n educations: ['school', 'major', 'degree', 'startedOn', 'endedOn'],\n certificates: ['name', 'issuer', 'acquiredOn'],\n careers: ['company', 'department', 'position', 'startedOn', 'endedOn', 'duties'],\n projects: ['name', 'client', 'startedOn', 'endedOn', 'role', 'duties', 'technologies']\n} as const\n\nconst text = (value: unknown): string => (typeof value === 'string' ? value.trim() : '')\n\n/** A row as kept: its own fields trimmed, empty ones left out. A row with nothing in it is no row. */\nfunction rowsOf(rows: unknown, fields: readonly string[]): Row[] {\n if (!Array.isArray(rows)) return []\n return rows.flatMap(row => {\n const kept: Row = {}\n for (const field of fields) {\n const value = text((row as Row | null)?.[field])\n if (value) kept[field] = value\n }\n return Object.keys(kept).length ? [kept] : []\n })\n}\n\n/**\n * The profile as it is saved - whole, as the screen sent it (ADR-0169 decision 2). Blank rows the screen added and did\n * not fill go, and a skill written twice is kept once.\n */\nexport function profileDocumentOf(input: any): ProfileDocument {\n const skills = [...new Set((Array.isArray(input?.skills) ? input.skills : []).map(text).filter(Boolean))] as string[]\n return {\n summary: text(input?.summary) || null,\n skills,\n educations: rowsOf(input?.educations, PROFILE_ROW_FIELDS.educations),\n certificates: rowsOf(input?.certificates, PROFILE_ROW_FIELDS.certificates),\n careers: rowsOf(input?.careers, PROFILE_ROW_FIELDS.careers),\n projects: rowsOf(input?.projects, PROFILE_ROW_FIELDS.projects)\n }\n}\n\n/** Two rows are the same entry when every field they keep is the same - spacing and letter case aside. */\nconst sameRow = (a: Row, b: Row) => {\n const keys = new Set([...Object.keys(a), ...Object.keys(b)])\n return [...keys].every(key => text(a[key]).toLowerCase() === text(b[key]).toLowerCase())\n}\n\n/**\n * What is added to a profile kept so far (ADR-0169 decision 10 - the assistant's 입력안 from a résumé): a summary given\n * takes the place of the one kept, skills are added after those held (a skill already held is not added twice), and\n * rows are added after those of their section unless the very same row is there. Nothing kept is taken away.\n */\nexport function addedProfileOf(held: Partial<ProfileDocument> | null | undefined, addition: any): ProfileDocument {\n const kept = profileDocumentOf(held ?? {})\n const added = profileDocumentOf(addition)\n const rows = (key: keyof typeof PROFILE_ROW_FIELDS) => [...kept[key], ...added[key].filter(row => !kept[key].some(one => sameRow(one, row)))]\n return {\n summary: added.summary ?? kept.summary,\n skills: [...kept.skills, ...added.skills.filter(skill => !kept.skills.some(one => one.toLowerCase() === skill.toLowerCase()))],\n educations: rows('educations'),\n certificates: rows('certificates'),\n careers: rows('careers'),\n projects: rows('projects')\n }\n}\n\nexport type ProfileEmployee = {\n id: string\n controlNo?: string\n name?: string\n active?: boolean | null\n retiredOn?: string | null\n jobPosition?: string\n jobResponsibility?: string\n hiredOn?: string\n department?: { name?: string } | null\n}\n\n/** Still working here: not marked inactive, and no retire day that has come. `today` is YYYY-MM-DD. */\nexport function isActiveEmployee(employee: ProfileEmployee, today: string): boolean {\n if (employee.active === false) return false\n return !employee.retiredOn || employee.retiredOn > today\n}\n\n/**\n * Every active employee with their profile, by name (ADR-0169 decision 4) - an employee who has written none is listed\n * with an empty one, so the list says who has not written it rather than leaving them out.\n */\nexport function employeesWithProfiles<P extends { employeeId?: string }>(employees: ProfileEmployee[], profiles: P[], today: string) {\n const byEmployee = new Map(profiles.map(profile => [profile.employeeId, profile]))\n return employees\n .filter(employee => isActiveEmployee(employee, today))\n .map(employee => ({\n employeeId: employee.id,\n controlNo: employee.controlNo,\n name: employee.name,\n departmentName: employee.department?.name,\n jobPosition: employee.jobPosition,\n jobResponsibility: employee.jobResponsibility,\n hiredOn: employee.hiredOn,\n profile: byEmployee.get(employee.id) ?? null\n }))\n .sort((a, b) => (a.name ?? '').localeCompare(b.name ?? '', 'ko') || (a.controlNo ?? '').localeCompare(b.controlNo ?? ''))\n}\n\n/** Today in the server's calendar, YYYY-MM-DD - the form `retiredOn` is kept in. */\nexport function todayOf(now = new Date()): string {\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`\n}\n\n/**\n * Newest first, as a résumé reads. A period is ordered by its end - one still going (no end) on top - and two that ended\n * together by the later start; a day (a certificate's) by the day. A row with no date keeps its place, after the dated\n * ones. Only the document is ordered; the profile keeps the rows as they were written.\n */\nexport function newestFirst<R extends { startedOn?: string; endedOn?: string; acquiredOn?: string }>(rows: R[] | null | undefined): R[] {\n const ONGOING = '9999-99'\n const endOf = (row: R) => (row.acquiredOn ?? row.endedOn ?? (row.startedOn ? ONGOING : '')).trim()\n const startOf = (row: R) => (row.acquiredOn ?? row.startedOn ?? '').trim()\n return [...(rows ?? [])].sort((a, b) => {\n const [endA, endB] = [endOf(a), endOf(b)]\n if (!endA || !endB) return Number(!endA) - Number(!endB)\n return endB.localeCompare(endA) || startOf(b).localeCompare(startOf(a))\n })\n}\n\n/** A profile's dated rows newest first, as every reader is shown them - the screen, the document and the assistant. */\nexport function inShowingOrder<P extends Partial<Record<'educations' | 'certificates' | 'careers' | 'projects', any[] | null>>>(profile: P): P {\n for (const kind of ['educations', 'certificates', 'careers', 'projects'] as const) if (Array.isArray(profile[kind])) (profile as any)[kind] = newestFirst(profile[kind])\n return profile\n}\n"]}
@@ -21,4 +21,5 @@ export declare class EmployeeProfile {
21
21
  createdAt?: Date;
22
22
  updatedAt?: Date;
23
23
  deletedAt?: Date;
24
+ showNewestFirst(): void;
24
25
  }
@@ -17,7 +17,12 @@ const shell_1 = require("@things-factory/shell");
17
17
  const auth_base_1 = require("@things-factory/auth-base");
18
18
  const employee_1 = require("../employee/employee");
19
19
  const employee_profile_rows_1 = require("./employee-profile-rows");
20
+ const employee_profile_rules_1 = require("./employee-profile-rules");
20
21
  let EmployeeProfile = class EmployeeProfile {
22
+ /* Shown newest first wherever it is read (2026-10-29, the user: 「보여줄 때 정렬해서」); the stored order is the one written. */
23
+ showNewestFirst() {
24
+ (0, employee_profile_rules_1.inShowingOrder)(this);
25
+ }
21
26
  };
22
27
  exports.EmployeeProfile = EmployeeProfile;
23
28
  tslib_1.__decorate([
@@ -102,8 +107,16 @@ tslib_1.__decorate([
102
107
  tslib_1.__decorate([
103
108
  (0, typeorm_1.DeleteDateColumn)(),
104
109
  (0, type_graphql_1.Field)({ nullable: true, description: 'Soft delete timestamp.' }),
105
- tslib_1.__metadata("design:type", Date)
110
+ tslib_1.__metadata("design:type", Date
111
+ /* Shown newest first wherever it is read (2026-10-29, the user: 「보여줄 때 정렬해서」); the stored order is the one written. */
112
+ )
106
113
  ], EmployeeProfile.prototype, "deletedAt", void 0);
114
+ tslib_1.__decorate([
115
+ (0, typeorm_1.AfterLoad)(),
116
+ tslib_1.__metadata("design:type", Function),
117
+ tslib_1.__metadata("design:paramtypes", []),
118
+ tslib_1.__metadata("design:returntype", void 0)
119
+ ], EmployeeProfile.prototype, "showNewestFirst", null);
107
120
  exports.EmployeeProfile = EmployeeProfile = tslib_1.__decorate([
108
121
  (0, typeorm_1.Entity)(),
109
122
  (0, typeorm_1.Index)('ix_employee_profile_0', (one) => [one.domain, one.employee], { unique: true, where: '"deleted_at" IS NULL' }),
@@ -1 +1 @@
1
- {"version":3,"file":"employee-profile.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * An employee's profile - what they studied, hold, did before and worked on - written by the employee and taken by sales\n * to attach to a quotation (ADR-0169).\n *\n * Its own table beside the employee record, one per employee: the record holds contact, address and the pay account,\n * and the people who read profiles (sales) must not read those. Name, department, position and hire day are read from\n * the record, never copied here. So neither the employee nor the writers are fields of this type - only their ids -\n * and reaching a profile does not reach the record behind it.\n */\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\nimport { Field, ID, ObjectType } from 'type-graphql'\n\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\nimport { Employee } from '../employee/employee'\nimport { EmployeeProfileCareer, EmployeeProfileCertificate, EmployeeProfileEducation, EmployeeProfileProject } from './employee-profile-rows'\n\n@Entity()\n@Index('ix_employee_profile_0', (one: EmployeeProfile) => [one.domain, one.employee], { unique: true, where: '\"deleted_at\" IS NULL' })\n@ObjectType({ description: \"An employee's profile - summary, skills, schools, certificates, past jobs and projects (ADR-0169).\" })\nexport class EmployeeProfile {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Profile id.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the profile is in.' })\n domain?: Domain\n\n @RelationId((one: EmployeeProfile) => one.domain)\n domainId?: string\n\n @ManyToOne(type => Employee)\n employee?: Employee\n\n @RelationId((one: EmployeeProfile) => one.employee)\n @Field({ nullable: true, description: 'The employee whose profile it is.' })\n employeeId?: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'A few lines about the employee.' })\n summary?: string\n\n @Column('simple-json', { nullable: true })\n @Field(type => [String], { nullable: true, description: 'The skills, each a word or two.' })\n skills?: string[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileEducation], { nullable: true, description: 'The schools.' })\n educations?: EmployeeProfileEducation[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileCertificate], { nullable: true, description: 'The certificates and licences.' })\n certificates?: EmployeeProfileCertificate[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileCareer], { nullable: true, description: 'The jobs held before, at other companies.' })\n careers?: EmployeeProfileCareer[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileProject], { nullable: true, description: 'The projects worked on.' })\n projects?: EmployeeProfileProject[]\n\n @ManyToOne(type => User, { nullable: true })\n creator?: User\n\n @RelationId((one: EmployeeProfile) => one.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n updater?: User\n\n @RelationId((one: EmployeeProfile) => one.updater)\n updaterId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft delete timestamp.' })\n deletedAt?: Date\n}\n"]}
1
+ {"version":3,"file":"employee-profile.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * An employee's profile - what they studied, hold, did before and worked on - written by the employee and taken by sales\n * to attach to a quotation (ADR-0169).\n *\n * Its own table beside the employee record, one per employee: the record holds contact, address and the pay account,\n * and the people who read profiles (sales) must not read those. Name, department, position and hire day are read from\n * the record, never copied here. So neither the employee nor the writers are fields of this type - only their ids -\n * and reaching a profile does not reach the record behind it.\n */\nimport { AfterLoad, Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\nimport { Field, ID, ObjectType } from 'type-graphql'\n\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\nimport { Employee } from '../employee/employee'\nimport { EmployeeProfileCareer, EmployeeProfileCertificate, EmployeeProfileEducation, EmployeeProfileProject } from './employee-profile-rows'\nimport { inShowingOrder } from './employee-profile-rules'\n\n@Entity()\n@Index('ix_employee_profile_0', (one: EmployeeProfile) => [one.domain, one.employee], { unique: true, where: '\"deleted_at\" IS NULL' })\n@ObjectType({ description: \"An employee's profile - summary, skills, schools, certificates, past jobs and projects (ADR-0169).\" })\nexport class EmployeeProfile {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Profile id.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the profile is in.' })\n domain?: Domain\n\n @RelationId((one: EmployeeProfile) => one.domain)\n domainId?: string\n\n @ManyToOne(type => Employee)\n employee?: Employee\n\n @RelationId((one: EmployeeProfile) => one.employee)\n @Field({ nullable: true, description: 'The employee whose profile it is.' })\n employeeId?: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'A few lines about the employee.' })\n summary?: string\n\n @Column('simple-json', { nullable: true })\n @Field(type => [String], { nullable: true, description: 'The skills, each a word or two.' })\n skills?: string[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileEducation], { nullable: true, description: 'The schools.' })\n educations?: EmployeeProfileEducation[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileCertificate], { nullable: true, description: 'The certificates and licences.' })\n certificates?: EmployeeProfileCertificate[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileCareer], { nullable: true, description: 'The jobs held before, at other companies.' })\n careers?: EmployeeProfileCareer[]\n\n @Column('simple-json', { nullable: true })\n @Field(type => [EmployeeProfileProject], { nullable: true, description: 'The projects worked on.' })\n projects?: EmployeeProfileProject[]\n\n @ManyToOne(type => User, { nullable: true })\n creator?: User\n\n @RelationId((one: EmployeeProfile) => one.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n updater?: User\n\n @RelationId((one: EmployeeProfile) => one.updater)\n updaterId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft delete timestamp.' })\n deletedAt?: Date\n\n /* Shown newest first wherever it is read (2026-10-29, the user: 「보여줄 때 정렬해서」); the stored order is the one written. */\n @AfterLoad()\n showNewestFirst() {\n inShowingOrder(this)\n }\n}\n"]}