@things-factory/organization 10.1.226 → 10.1.227
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/pages/employee-profile/employee-profile-files.d.ts +23 -0
- package/dist-client/pages/employee-profile/employee-profile-files.js +50 -0
- package/dist-client/pages/employee-profile/employee-profile-files.js.map +1 -0
- package/dist-client/pages/employee-profile/employee-profile-form.d.ts +42 -10
- package/dist-client/pages/employee-profile/employee-profile-form.js +68 -22
- package/dist-client/pages/employee-profile/employee-profile-form.js.map +1 -1
- package/dist-client/pages/employee-profile/employee-profile-list-page.d.ts +19 -5
- package/dist-client/pages/employee-profile/employee-profile-list-page.js +88 -46
- package/dist-client/pages/employee-profile/employee-profile-list-page.js.map +1 -1
- package/dist-client/pages/employee-profile/employee-profile-preview.d.ts +28 -0
- package/dist-client/pages/employee-profile/employee-profile-preview.js +179 -0
- package/dist-client/pages/employee-profile/employee-profile-preview.js.map +1 -0
- package/dist-client/pages/employee-profile/my-employee-profile-page.d.ts +20 -2
- package/dist-client/pages/employee-profile/my-employee-profile-page.js +467 -93
- package/dist-client/pages/employee-profile/my-employee-profile-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/ai-entry/employee-profile-entry.d.ts +10 -0
- package/dist-server/ai-entry/employee-profile-entry.js +88 -0
- package/dist-server/ai-entry/employee-profile-entry.js.map +1 -0
- package/dist-server/ai-entry/entry-target-shape.d.ts +11 -1
- package/dist-server/ai-entry/entry-target-shape.js.map +1 -1
- package/dist-server/ai-entry/organization-entry-targets.d.ts +8 -0
- package/dist-server/ai-entry/organization-entry-targets.js +26 -1
- package/dist-server/ai-entry/organization-entry-targets.js.map +1 -1
- package/dist-server/service/employee-profile/employee-profile-document.d.ts +122 -0
- package/dist-server/service/employee-profile/employee-profile-document.js +439 -0
- package/dist-server/service/employee-profile/employee-profile-document.js.map +1 -0
- package/dist-server/service/employee-profile/employee-profile-mutation.d.ts +1 -0
- package/dist-server/service/employee-profile/employee-profile-mutation.js +29 -0
- package/dist-server/service/employee-profile/employee-profile-mutation.js.map +1 -1
- package/dist-server/service/employee-profile/employee-profile-query.d.ts +9 -1
- package/dist-server/service/employee-profile/employee-profile-query.js +83 -4
- package/dist-server/service/employee-profile/employee-profile-query.js.map +1 -1
- package/dist-server/service/employee-profile/employee-profile-rules.d.ts +6 -0
- package/dist-server/service/employee-profile/employee-profile-rules.js +24 -0
- package/dist-server/service/employee-profile/employee-profile-rules.js.map +1 -1
- package/dist-server/service/employee-profile/employee-profile-type.d.ts +11 -0
- package/dist-server/service/employee-profile/employee-profile-type.js +30 -1
- package/dist-server/service/employee-profile/employee-profile-type.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -7
- package/tests/employee-profile-db.test.ts +65 -4
- package/tests/employee-profile-document.test.ts +219 -0
- package/tests/employee-profile-entry.test.ts +72 -0
- package/tests/employee-profile-rules.test.ts +33 -6
- package/translations/en.json +43 -3
- package/translations/es.json +43 -3
- package/translations/ja.json +43 -3
- package/translations/ko.json +43 -3
- package/translations/ms.json +43 -3
- package/translations/zh.json +43 -3
- package/dist-client/pages/employee-profile/employee-profile-workbook.d.ts +0 -33
- package/dist-client/pages/employee-profile/employee-profile-workbook.js +0 -87
- package/dist-client/pages/employee-profile/employee-profile-workbook.js.map +0 -1
- package/tests/employee-profile-workbook.test.ts +0 -89
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"employee-profile-mutation.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAAsE;AAEtE,iDAAqD;AAErD,+DAA8D;AAC9D,yDAAoD;AACpD,
|
|
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,6 +1,14 @@
|
|
|
1
1
|
import { EmployeeProfile } from './employee-profile';
|
|
2
|
-
import { EmployeeWithProfile } from './employee-profile-type';
|
|
2
|
+
import { EmployeeProfileFile, EmployeeProfileFormat, EmployeeWithProfile } from './employee-profile-type';
|
|
3
3
|
export declare class EmployeeProfileQuery {
|
|
4
4
|
myEmployeeProfile(context: ResolverContext): Promise<EmployeeProfile | null>;
|
|
5
5
|
employeeProfiles(context: ResolverContext): Promise<EmployeeWithProfile[]>;
|
|
6
|
+
employeeProfileDocument(employeeIds: string[], format: EmployeeProfileFormat, language: string, context: ResolverContext): Promise<EmployeeProfileFile>;
|
|
7
|
+
myEmployeeProfileDocument(format: EmployeeProfileFormat, language: string, context: ResolverContext): Promise<EmployeeProfileFile>;
|
|
6
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* The translator of the document's own words: the language asked for, or the reader's. Only the words the document
|
|
11
|
+
* itself prints follow it - names, summaries and projects stay as their employees wrote them. A language the
|
|
12
|
+
* application does not run (`i18n.languages`) is refused rather than printed half in another.
|
|
13
|
+
*/
|
|
14
|
+
export declare function documentTranslator(context: any, language?: string | null): (key: string, options?: any) => string;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EmployeeProfileQuery = void 0;
|
|
4
|
+
exports.documentTranslator = documentTranslator;
|
|
4
5
|
const tslib_1 = require("tslib");
|
|
5
6
|
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const env_1 = require("@things-factory/env");
|
|
6
8
|
const shell_1 = require("@things-factory/shell");
|
|
9
|
+
const pdf_1 = require("@things-factory/pdf");
|
|
7
10
|
const employee_1 = require("../employee/employee");
|
|
8
11
|
const my_employee_js_1 = require("../employee/my-employee.js");
|
|
9
12
|
const employee_profile_1 = require("./employee-profile");
|
|
10
13
|
const employee_profile_rules_1 = require("./employee-profile-rules");
|
|
14
|
+
const employee_profile_document_1 = require("./employee-profile-document");
|
|
11
15
|
const employee_profile_type_1 = require("./employee-profile-type");
|
|
12
16
|
/*
|
|
13
17
|
* Reading profiles (ADR-0169 decisions 3 · 4): one's own under `employee-self`, every active employee's under
|
|
@@ -24,10 +28,22 @@ let EmployeeProfileQuery = class EmployeeProfileQuery {
|
|
|
24
28
|
return await (0, shell_1.getRepository)(employee_profile_1.EmployeeProfile, tx).findOne({ where: { domain: { id: domain.id }, employee: { id: employee.id } } });
|
|
25
29
|
}
|
|
26
30
|
async employeeProfiles(context) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
return await activeWithProfiles(context);
|
|
32
|
+
}
|
|
33
|
+
/*
|
|
34
|
+
* The chosen people's profiles as one file to hand in with a quotation - Excel or PDF, from one layout
|
|
35
|
+
* (employee-profile-document.ts). Only active employees of the domain, in the order chosen; an id that is none of
|
|
36
|
+
* them is left out. The employer's name is the domain's description, as the sign-in page shows it.
|
|
37
|
+
*/
|
|
38
|
+
async employeeProfileDocument(employeeIds, format, language, context) {
|
|
39
|
+
const everyone = await activeWithProfiles(context);
|
|
40
|
+
return await documentOf(employeeIds.map(id => everyone.find(one => one.employeeId === id)).filter(Boolean), format, context, language);
|
|
41
|
+
}
|
|
42
|
+
/* One's own profile as the document sales will hand in - to see it while writing it. */
|
|
43
|
+
async myEmployeeProfileDocument(format, language, context) {
|
|
44
|
+
const mine = (0, my_employee_js_1.theOneEmployee)(await (0, my_employee_js_1.myEmployees)(context), context);
|
|
45
|
+
const everyone = await activeWithProfiles(context);
|
|
46
|
+
return await documentOf(everyone.filter(one => one.employeeId === mine.id), format, context, language);
|
|
31
47
|
}
|
|
32
48
|
};
|
|
33
49
|
exports.EmployeeProfileQuery = EmployeeProfileQuery;
|
|
@@ -52,7 +68,70 @@ tslib_1.__decorate([
|
|
|
52
68
|
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
53
69
|
tslib_1.__metadata("design:returntype", Promise)
|
|
54
70
|
], EmployeeProfileQuery.prototype, "employeeProfiles", null);
|
|
71
|
+
tslib_1.__decorate([
|
|
72
|
+
(0, type_graphql_1.Directive)('@privilege(category: "employee-profile", privilege: "query", domainOwnerGranted: true)'),
|
|
73
|
+
(0, type_graphql_1.Query)(returns => employee_profile_type_1.EmployeeProfileFile, { description: "Prints the chosen active employees' profiles as one Excel workbook or PDF, in the order chosen." }),
|
|
74
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('employeeIds', type => [String], { description: 'The employees, in the order their profiles are printed.' })),
|
|
75
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('format', type => employee_profile_type_1.EmployeeProfileFormat, { description: 'Excel or PDF.' })),
|
|
76
|
+
tslib_1.__param(2, (0, type_graphql_1.Arg)('language', { nullable: true, description: "The language of the document's own words, one the application runs - the reader's when empty." })),
|
|
77
|
+
tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
|
|
78
|
+
tslib_1.__metadata("design:type", Function),
|
|
79
|
+
tslib_1.__metadata("design:paramtypes", [Array, String, String, Object]),
|
|
80
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
81
|
+
], EmployeeProfileQuery.prototype, "employeeProfileDocument", null);
|
|
82
|
+
tslib_1.__decorate([
|
|
83
|
+
(0, type_graphql_1.Directive)('@privilege(category: "employee-self", privilege: "query", domainOwnerGranted: true)'),
|
|
84
|
+
(0, type_graphql_1.Query)(returns => employee_profile_type_1.EmployeeProfileFile, { description: "Prints the caller's own profile as the Excel workbook or PDF a quotation attaches." }),
|
|
85
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('format', type => employee_profile_type_1.EmployeeProfileFormat, { description: 'Excel or PDF.' })),
|
|
86
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('language', { nullable: true, description: "The language of the document's own words, one the application runs - the reader's when empty." })),
|
|
87
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
88
|
+
tslib_1.__metadata("design:type", Function),
|
|
89
|
+
tslib_1.__metadata("design:paramtypes", [String, String, Object]),
|
|
90
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
91
|
+
], EmployeeProfileQuery.prototype, "myEmployeeProfileDocument", null);
|
|
55
92
|
exports.EmployeeProfileQuery = EmployeeProfileQuery = tslib_1.__decorate([
|
|
56
93
|
(0, type_graphql_1.Resolver)(employee_profile_1.EmployeeProfile)
|
|
57
94
|
], EmployeeProfileQuery);
|
|
95
|
+
/**
|
|
96
|
+
* The translator of the document's own words: the language asked for, or the reader's. Only the words the document
|
|
97
|
+
* itself prints follow it - names, summaries and projects stay as their employees wrote them. A language the
|
|
98
|
+
* application does not run (`i18n.languages`) is refused rather than printed half in another.
|
|
99
|
+
*/
|
|
100
|
+
function documentTranslator(context, language) {
|
|
101
|
+
if (!language)
|
|
102
|
+
return (key, options) => String(context.t(key, options));
|
|
103
|
+
const runs = (env_1.config.get('i18n/languages', []) ?? []).map(one => one?.code);
|
|
104
|
+
if (!runs.includes(language))
|
|
105
|
+
throw new Error(`The application does not run the language "${language}".`);
|
|
106
|
+
const fixed = context.i18next.getFixedT(language);
|
|
107
|
+
return (key, options) => String(fixed(key, options));
|
|
108
|
+
}
|
|
109
|
+
/** The people's profiles as one file - Excel or PDF from one layout, the employer named as the sign-in page names it. */
|
|
110
|
+
async function documentOf(people, format, context, language) {
|
|
111
|
+
const t = documentTranslator(context, language);
|
|
112
|
+
const words = (0, employee_profile_document_1.profileWordsOf)(t);
|
|
113
|
+
const company = context.state.domain.description || context.state.domain.name;
|
|
114
|
+
const word = t('text.employee-profile-file');
|
|
115
|
+
if (format === employee_profile_type_1.EmployeeProfileFormat.HTML) {
|
|
116
|
+
return { fileName: (0, employee_profile_document_1.profileFileName)(word, 'html'), mimeType: 'text/html', content: Buffer.from((0, employee_profile_document_1.profilePreviewHtml)(people, words, company), 'utf8').toString('base64') };
|
|
117
|
+
}
|
|
118
|
+
if (format === employee_profile_type_1.EmployeeProfileFormat.PDF) {
|
|
119
|
+
const body = `<style>${employee_profile_document_1.PROFILE_CSS}</style>${(0, employee_profile_document_1.profileHtml)(people, words, company)}`;
|
|
120
|
+
const pdf = await new pdf_1.PdfService().generatePdf({ content_template: '{{{body}}}', footer_template: (0, employee_profile_document_1.profileFooterHtml)(company, words), page_size: 'A4' }, { body });
|
|
121
|
+
return { fileName: (0, employee_profile_document_1.profileFileName)(word, 'pdf'), mimeType: 'application/pdf', content: pdf.toString('base64') };
|
|
122
|
+
}
|
|
123
|
+
const buffer = await (0, employee_profile_document_1.profileWorkbook)(people, words, company).xlsx.writeBuffer();
|
|
124
|
+
return {
|
|
125
|
+
fileName: (0, employee_profile_document_1.profileFileName)(word, 'xlsx'),
|
|
126
|
+
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
127
|
+
content: Buffer.from(buffer).toString('base64')
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/** Every active employee of the domain with their profile - the list and the document read the same people. */
|
|
131
|
+
async function activeWithProfiles(context) {
|
|
132
|
+
const { domain, tx } = context.state;
|
|
133
|
+
const employees = await (0, shell_1.getRepository)(employee_1.Employee, tx).find({ where: { domain: { id: domain.id } }, relations: ['department'] });
|
|
134
|
+
const profiles = await (0, shell_1.getRepository)(employee_profile_1.EmployeeProfile, tx).find({ where: { domain: { id: domain.id } } });
|
|
135
|
+
return (0, employee_profile_rules_1.employeesWithProfiles)(employees, profiles, (0, employee_profile_rules_1.todayOf)());
|
|
136
|
+
}
|
|
58
137
|
//# sourceMappingURL=employee-profile-query.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"employee-profile-query.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA8D;AAE9D,iDAAqD;AAErD,mDAA+C;AAC/C,+DAAwE;AACxE,yDAAoD;AACpD,qEAAyE;AACzE,mEAA6D;AAE7D;;;;GAIG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAMzB,AAAN,KAAK,CAAC,iBAAiB,CAAQ,OAAwB;QACrD,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QACpC,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAW,EAAC,OAAO,CAAC,CAAA;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QAE7B,MAAM,QAAQ,GAAG,IAAA,+BAAc,EAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC9C,OAAO,MAAM,IAAA,qBAAa,EAAC,kCAAe,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;IAClI,CAAC;IAOK,AAAN,KAAK,CAAC,gBAAgB,CAAQ,OAAwB;QACpD,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QACpC,MAAM,SAAS,GAAG,MAAM,IAAA,qBAAa,EAAC,mBAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;QAC7H,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,kCAAe,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAExG,OAAO,IAAA,8CAAqB,EAAC,SAAS,EAAE,QAAQ,EAAE,IAAA,gCAAO,GAAE,CAAC,CAAA;IAC9D,CAAC;CACF,CAAA;AA3BY,oDAAoB;AAMzB;IALL,IAAA,wBAAS,EAAC,qFAAqF,CAAC;IAChG,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,kCAAe,EAAE;QACjC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,sJAAsJ;KACpK,CAAC;IACuB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;6DAO7B;AAOK;IALL,IAAA,wBAAS,EAAC,wFAAwF,CAAC;IACnG,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,2CAAmB,CAAC,EAAE;QACvC,WAAW,EACT,iNAAiN;KACpN,CAAC;IACsB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;4DAM5B;+BA1BU,oBAAoB;IADhC,IAAA,uBAAQ,EAAC,kCAAe,CAAC;GACb,oBAAoB,CA2BhC","sourcesContent":["import { Ctx, Directive, Query, Resolver } from 'type-graphql'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { Employee } from '../employee/employee'\nimport { myEmployees, theOneEmployee } from '../employee/my-employee.js'\nimport { EmployeeProfile } from './employee-profile'\nimport { employeesWithProfiles, todayOf } from './employee-profile-rules'\nimport { EmployeeWithProfile } from './employee-profile-type'\n\n/*\n * Reading profiles (ADR-0169 decisions 3 · 4): one's own under `employee-self`, every active employee's under\n * `employee-profile` - the seats that attach profiles to quotations. Neither reads the employee record beyond the\n * basics a profile sheet shows.\n */\n@Resolver(EmployeeProfile)\nexport class EmployeeProfileQuery {\n @Directive('@privilege(category: \"employee-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EmployeeProfile, {\n nullable: true,\n description: \"Fetches the caller's own profile. Null when the caller has written none, or when the account is not linked to an employee (myEmployees tells which).\"\n })\n async myEmployeeProfile(@Ctx() context: ResolverContext): Promise<EmployeeProfile | null> {\n const { domain, tx } = context.state\n const mine = await myEmployees(context)\n if (!mine.length) return null\n\n const employee = theOneEmployee(mine, context)\n return await getRepository(EmployeeProfile, tx).findOne({ where: { domain: { id: domain.id }, employee: { id: employee.id } } })\n }\n\n @Directive('@privilege(category: \"employee-profile\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [EmployeeWithProfile], {\n description:\n 'Fetches every active employee of the domain - not retired, not marked inactive - with their name, department, position, responsibility, hire day and profile; the profile is empty when they have written none.'\n })\n async employeeProfiles(@Ctx() context: ResolverContext): Promise<EmployeeWithProfile[]> {\n const { domain, tx } = context.state\n const employees = await getRepository(Employee, tx).find({ where: { domain: { id: domain.id } }, relations: ['department'] })\n const profiles = await getRepository(EmployeeProfile, tx).find({ where: { domain: { id: domain.id } } })\n\n return employeesWithProfiles(employees, profiles, todayOf())\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"employee-profile-query.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Query, Resolver } from 'type-graphql'\n\nimport { config } from '@things-factory/env'\nimport { getRepository } from '@things-factory/shell'\nimport { PdfService } from '@things-factory/pdf'\n\nimport { Employee } from '../employee/employee'\nimport { myEmployees, theOneEmployee } from '../employee/my-employee.js'\nimport { EmployeeProfile } from './employee-profile'\nimport { employeesWithProfiles, todayOf } from './employee-profile-rules'\nimport { profileFileName, profileFooterHtml, PROFILE_CSS, profileHtml, profilePreviewHtml, profileWordsOf, profileWorkbook } from './employee-profile-document'\nimport { EmployeeProfileFile, EmployeeProfileFormat, EmployeeWithProfile } from './employee-profile-type'\n\n/*\n * Reading profiles (ADR-0169 decisions 3 · 4): one's own under `employee-self`, every active employee's under\n * `employee-profile` - the seats that attach profiles to quotations. Neither reads the employee record beyond the\n * basics a profile sheet shows.\n */\n@Resolver(EmployeeProfile)\nexport class EmployeeProfileQuery {\n @Directive('@privilege(category: \"employee-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EmployeeProfile, {\n nullable: true,\n description: \"Fetches the caller's own profile. Null when the caller has written none, or when the account is not linked to an employee (myEmployees tells which).\"\n })\n async myEmployeeProfile(@Ctx() context: ResolverContext): Promise<EmployeeProfile | null> {\n const { domain, tx } = context.state\n const mine = await myEmployees(context)\n if (!mine.length) return null\n\n const employee = theOneEmployee(mine, context)\n return await getRepository(EmployeeProfile, tx).findOne({ where: { domain: { id: domain.id }, employee: { id: employee.id } } })\n }\n\n @Directive('@privilege(category: \"employee-profile\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [EmployeeWithProfile], {\n description:\n 'Fetches every active employee of the domain - not retired, not marked inactive - with their name, department, position, responsibility, hire day and profile; the profile is empty when they have written none.'\n })\n async employeeProfiles(@Ctx() context: ResolverContext): Promise<EmployeeWithProfile[]> {\n return await activeWithProfiles(context)\n }\n\n /*\n * The chosen people's profiles as one file to hand in with a quotation - Excel or PDF, from one layout\n * (employee-profile-document.ts). Only active employees of the domain, in the order chosen; an id that is none of\n * them is left out. The employer's name is the domain's description, as the sign-in page shows it.\n */\n @Directive('@privilege(category: \"employee-profile\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EmployeeProfileFile, { description: \"Prints the chosen active employees' profiles as one Excel workbook or PDF, in the order chosen.\" })\n async employeeProfileDocument(\n @Arg('employeeIds', type => [String], { description: 'The employees, in the order their profiles are printed.' }) employeeIds: string[],\n @Arg('format', type => EmployeeProfileFormat, { description: 'Excel or PDF.' }) format: EmployeeProfileFormat,\n @Arg('language', { nullable: true, description: \"The language of the document's own words, one the application runs - the reader's when empty.\" }) language: string,\n @Ctx() context: ResolverContext\n ): Promise<EmployeeProfileFile> {\n const everyone = await activeWithProfiles(context)\n return await documentOf(employeeIds.map(id => everyone.find(one => one.employeeId === id)).filter(Boolean), format, context, language)\n }\n\n /* One's own profile as the document sales will hand in - to see it while writing it. */\n @Directive('@privilege(category: \"employee-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EmployeeProfileFile, { description: \"Prints the caller's own profile as the Excel workbook or PDF a quotation attaches.\" })\n async myEmployeeProfileDocument(\n @Arg('format', type => EmployeeProfileFormat, { description: 'Excel or PDF.' }) format: EmployeeProfileFormat,\n @Arg('language', { nullable: true, description: \"The language of the document's own words, one the application runs - the reader's when empty.\" }) language: string,\n @Ctx() context: ResolverContext\n ): Promise<EmployeeProfileFile> {\n const mine = theOneEmployee(await myEmployees(context), context)\n const everyone = await activeWithProfiles(context)\n return await documentOf(everyone.filter(one => one.employeeId === mine.id), format, context, language)\n }\n}\n\n/**\n * The translator of the document's own words: the language asked for, or the reader's. Only the words the document\n * itself prints follow it - names, summaries and projects stay as their employees wrote them. A language the\n * application does not run (`i18n.languages`) is refused rather than printed half in another.\n */\nexport function documentTranslator(context: any, language?: string | null): (key: string, options?: any) => string {\n if (!language) return (key, options) => String(context.t(key, options))\n const runs = ((config.get('i18n/languages', []) as { code?: string }[]) ?? []).map(one => one?.code)\n if (!runs.includes(language)) throw new Error(`The application does not run the language \"${language}\".`)\n const fixed = context.i18next.getFixedT(language)\n return (key, options) => String(fixed(key, options))\n}\n\n/** The people's profiles as one file - Excel or PDF from one layout, the employer named as the sign-in page names it. */\nasync function documentOf(people: EmployeeWithProfile[], format: EmployeeProfileFormat, context: ResolverContext, language?: string): Promise<EmployeeProfileFile> {\n const t = documentTranslator(context, language)\n const words = profileWordsOf(t)\n const company = context.state.domain.description || context.state.domain.name\n const word = t('text.employee-profile-file')\n\n if (format === EmployeeProfileFormat.HTML) {\n return { fileName: profileFileName(word, 'html'), mimeType: 'text/html', content: Buffer.from(profilePreviewHtml(people, words, company), 'utf8').toString('base64') }\n }\n\n if (format === EmployeeProfileFormat.PDF) {\n const body = `<style>${PROFILE_CSS}</style>${profileHtml(people, words, company)}`\n const pdf = await new PdfService().generatePdf({ content_template: '{{{body}}}', footer_template: profileFooterHtml(company, words), page_size: 'A4' }, { body })\n return { fileName: profileFileName(word, 'pdf'), mimeType: 'application/pdf', content: pdf.toString('base64') }\n }\n\n const buffer = await profileWorkbook(people, words, company).xlsx.writeBuffer()\n return {\n fileName: profileFileName(word, 'xlsx'),\n mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n content: Buffer.from(buffer as ArrayBuffer).toString('base64')\n }\n}\n\n/** Every active employee of the domain with their profile - the list and the document read the same people. */\nasync function activeWithProfiles(context: ResolverContext): Promise<EmployeeWithProfile[]> {\n const { domain, tx } = context.state\n const employees = await getRepository(Employee, tx).find({ where: { domain: { id: domain.id } }, relations: ['department'] })\n const profiles = await getRepository(EmployeeProfile, tx).find({ where: { domain: { id: domain.id } } })\n\n return employeesWithProfiles(employees, profiles, todayOf()) as any\n}\n"]}
|
|
@@ -19,6 +19,12 @@ export declare const PROFILE_ROW_FIELDS: {
|
|
|
19
19
|
* not fill go, and a skill written twice is kept once.
|
|
20
20
|
*/
|
|
21
21
|
export declare function profileDocumentOf(input: any): ProfileDocument;
|
|
22
|
+
/**
|
|
23
|
+
* What is added to a profile kept so far (ADR-0169 decision 10 - the assistant's 입력안 from a résumé): a summary given
|
|
24
|
+
* takes the place of the one kept, skills are added after those held (a skill already held is not added twice), and
|
|
25
|
+
* rows are added after those of their section unless the very same row is there. Nothing kept is taken away.
|
|
26
|
+
*/
|
|
27
|
+
export declare function addedProfileOf(held: Partial<ProfileDocument> | null | undefined, addition: any): ProfileDocument;
|
|
22
28
|
export type ProfileEmployee = {
|
|
23
29
|
id: string;
|
|
24
30
|
controlNo?: string;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.PROFILE_ROW_FIELDS = void 0;
|
|
8
8
|
exports.profileDocumentOf = profileDocumentOf;
|
|
9
|
+
exports.addedProfileOf = addedProfileOf;
|
|
9
10
|
exports.isActiveEmployee = isActiveEmployee;
|
|
10
11
|
exports.employeesWithProfiles = employeesWithProfiles;
|
|
11
12
|
exports.todayOf = todayOf;
|
|
@@ -46,6 +47,29 @@ function profileDocumentOf(input) {
|
|
|
46
47
|
projects: rowsOf(input?.projects, exports.PROFILE_ROW_FIELDS.projects)
|
|
47
48
|
};
|
|
48
49
|
}
|
|
50
|
+
/** Two rows are the same entry when every field they keep is the same - spacing and letter case aside. */
|
|
51
|
+
const sameRow = (a, b) => {
|
|
52
|
+
const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
53
|
+
return [...keys].every(key => text(a[key]).toLowerCase() === text(b[key]).toLowerCase());
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* What is added to a profile kept so far (ADR-0169 decision 10 - the assistant's 입력안 from a résumé): a summary given
|
|
57
|
+
* takes the place of the one kept, skills are added after those held (a skill already held is not added twice), and
|
|
58
|
+
* rows are added after those of their section unless the very same row is there. Nothing kept is taken away.
|
|
59
|
+
*/
|
|
60
|
+
function addedProfileOf(held, addition) {
|
|
61
|
+
const kept = profileDocumentOf(held ?? {});
|
|
62
|
+
const added = profileDocumentOf(addition);
|
|
63
|
+
const rows = (key) => [...kept[key], ...added[key].filter(row => !kept[key].some(one => sameRow(one, row)))];
|
|
64
|
+
return {
|
|
65
|
+
summary: added.summary ?? kept.summary,
|
|
66
|
+
skills: [...kept.skills, ...added.skills.filter(skill => !kept.skills.some(one => one.toLowerCase() === skill.toLowerCase()))],
|
|
67
|
+
educations: rows('educations'),
|
|
68
|
+
certificates: rows('certificates'),
|
|
69
|
+
careers: rows('careers'),
|
|
70
|
+
projects: rows('projects')
|
|
71
|
+
};
|
|
72
|
+
}
|
|
49
73
|
/** Still working here: not marked inactive, and no retire day that has come. `today` is YYYY-MM-DD. */
|
|
50
74
|
function isActiveEmployee(employee, today) {
|
|
51
75
|
if (employee.active === false)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"employee-profile-rules.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-rules.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAwCH,8CAUC;AAeD,4CAGC;AAMD,sDAeC;AAGD,0BAGC;
|
|
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,5 +1,16 @@
|
|
|
1
1
|
import { EmployeeProfile } from './employee-profile';
|
|
2
2
|
import { EmployeeProfileCareer, EmployeeProfileCertificate, EmployeeProfileEducation, EmployeeProfileProject } from './employee-profile-rows';
|
|
3
|
+
/** The two forms the profiles are handed in as, and the page they are previewed on (ADR-0169 decisions 5 · 9). */
|
|
4
|
+
export declare enum EmployeeProfileFormat {
|
|
5
|
+
XLSX = "XLSX",
|
|
6
|
+
PDF = "PDF",
|
|
7
|
+
HTML = "HTML"
|
|
8
|
+
}
|
|
9
|
+
export declare class EmployeeProfileFile {
|
|
10
|
+
fileName: string;
|
|
11
|
+
mimeType: string;
|
|
12
|
+
content: string;
|
|
13
|
+
}
|
|
3
14
|
export declare class EmployeeProfileInput {
|
|
4
15
|
summary?: string;
|
|
5
16
|
skills?: string[];
|
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EmployeeWithProfile = exports.EmployeeProfileInput = void 0;
|
|
3
|
+
exports.EmployeeWithProfile = exports.EmployeeProfileInput = exports.EmployeeProfileFile = exports.EmployeeProfileFormat = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
/* The documents the profile's doors take and give (ADR-0169 decisions 2 · 4). */
|
|
6
6
|
const type_graphql_1 = require("type-graphql");
|
|
7
7
|
const employee_profile_1 = require("./employee-profile");
|
|
8
8
|
const employee_profile_rows_1 = require("./employee-profile-rows");
|
|
9
|
+
/** The two forms the profiles are handed in as, and the page they are previewed on (ADR-0169 decisions 5 · 9). */
|
|
10
|
+
var EmployeeProfileFormat;
|
|
11
|
+
(function (EmployeeProfileFormat) {
|
|
12
|
+
EmployeeProfileFormat["XLSX"] = "XLSX";
|
|
13
|
+
EmployeeProfileFormat["PDF"] = "PDF";
|
|
14
|
+
EmployeeProfileFormat["HTML"] = "HTML";
|
|
15
|
+
})(EmployeeProfileFormat || (exports.EmployeeProfileFormat = EmployeeProfileFormat = {}));
|
|
16
|
+
(0, type_graphql_1.registerEnumType)(EmployeeProfileFormat, {
|
|
17
|
+
name: 'EmployeeProfileFormat',
|
|
18
|
+
description: 'The form of the employee profiles: an Excel workbook or a PDF to download, or an HTML page to preview them on screen.'
|
|
19
|
+
});
|
|
20
|
+
let EmployeeProfileFile = class EmployeeProfileFile {
|
|
21
|
+
};
|
|
22
|
+
exports.EmployeeProfileFile = EmployeeProfileFile;
|
|
23
|
+
tslib_1.__decorate([
|
|
24
|
+
(0, type_graphql_1.Field)({ description: 'The file name, with its extension.' }),
|
|
25
|
+
tslib_1.__metadata("design:type", String)
|
|
26
|
+
], EmployeeProfileFile.prototype, "fileName", void 0);
|
|
27
|
+
tslib_1.__decorate([
|
|
28
|
+
(0, type_graphql_1.Field)({ description: 'The media type.' }),
|
|
29
|
+
tslib_1.__metadata("design:type", String)
|
|
30
|
+
], EmployeeProfileFile.prototype, "mimeType", void 0);
|
|
31
|
+
tslib_1.__decorate([
|
|
32
|
+
(0, type_graphql_1.Field)({ description: 'The bytes of the file, base64.' }),
|
|
33
|
+
tslib_1.__metadata("design:type", String)
|
|
34
|
+
], EmployeeProfileFile.prototype, "content", void 0);
|
|
35
|
+
exports.EmployeeProfileFile = EmployeeProfileFile = tslib_1.__decorate([
|
|
36
|
+
(0, type_graphql_1.ObjectType)({ description: 'A file of employee profiles to download - its name, its media type and its bytes in base64.' })
|
|
37
|
+
], EmployeeProfileFile);
|
|
9
38
|
let EmployeeProfileInput = class EmployeeProfileInput {
|
|
10
39
|
};
|
|
11
40
|
exports.EmployeeProfileInput = EmployeeProfileInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"employee-profile-type.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-type.ts"],"names":[],"mappings":";;;;AAAA,iFAAiF;AACjF,+
|
|
1
|
+
{"version":3,"file":"employee-profile-type.js","sourceRoot":"","sources":["../../../server/service/employee-profile/employee-profile-type.ts"],"names":[],"mappings":"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","sourcesContent":["/* The documents the profile's doors take and give (ADR-0169 decisions 2 · 4). */\nimport { Field, InputType, ObjectType, registerEnumType } from 'type-graphql'\n\nimport { EmployeeProfile } from './employee-profile'\nimport { EmployeeProfileCareer, EmployeeProfileCertificate, EmployeeProfileEducation, EmployeeProfileProject } from './employee-profile-rows'\n\n/** The two forms the profiles are handed in as, and the page they are previewed on (ADR-0169 decisions 5 · 9). */\nexport enum EmployeeProfileFormat {\n XLSX = 'XLSX',\n PDF = 'PDF',\n HTML = 'HTML'\n}\n\nregisterEnumType(EmployeeProfileFormat, {\n name: 'EmployeeProfileFormat',\n description: 'The form of the employee profiles: an Excel workbook or a PDF to download, or an HTML page to preview them on screen.'\n})\n\n@ObjectType({ description: 'A file of employee profiles to download - its name, its media type and its bytes in base64.' })\nexport class EmployeeProfileFile {\n @Field({ description: 'The file name, with its extension.' })\n fileName: string\n\n @Field({ description: 'The media type.' })\n mimeType: string\n\n @Field({ description: 'The bytes of the file, base64.' })\n content: string\n}\n\n@InputType({ description: \"The caller's own profile, whole - what is left out is emptied (ADR-0169 decision 2).\" })\nexport class EmployeeProfileInput {\n @Field({ nullable: true, description: 'A few lines about the employee.' })\n summary?: string\n\n @Field(type => [String], { nullable: true, description: 'The skills, each a word or two.' })\n skills?: string[]\n\n @Field(type => [EmployeeProfileEducation], { nullable: true, description: 'The schools.' })\n educations?: EmployeeProfileEducation[]\n\n @Field(type => [EmployeeProfileCertificate], { nullable: true, description: 'The certificates and licences.' })\n certificates?: EmployeeProfileCertificate[]\n\n @Field(type => [EmployeeProfileCareer], { nullable: true, description: 'The jobs held before, at other companies.' })\n careers?: EmployeeProfileCareer[]\n\n @Field(type => [EmployeeProfileProject], { nullable: true, description: 'The projects worked on.' })\n projects?: EmployeeProfileProject[]\n}\n\n/**\n * One active employee with their profile, for the list a quotation's profiles are taken from (ADR-0169 decisions 1 · 4).\n * The basics are read from the employee record and nothing else of it - no contact, address, birthday, account or pay.\n */\n@ObjectType({ description: 'An active employee of the domain with their profile - empty when they have written none.' })\nexport class EmployeeWithProfile {\n @Field({ description: 'The employee id.' })\n employeeId: string\n\n @Field({ nullable: true, description: 'The employee control number.' })\n controlNo?: string\n\n @Field({ nullable: true, description: 'The name.' })\n name?: string\n\n @Field({ nullable: true, description: 'The name of the department.' })\n departmentName?: string\n\n @Field({ nullable: true, description: 'The position (rank).' })\n jobPosition?: string\n\n @Field({ nullable: true, description: 'The responsibility (title).' })\n jobResponsibility?: string\n\n @Field({ nullable: true, description: 'The hire day, YYYY-MM-DD.' })\n hiredOn?: string\n\n @Field(type => EmployeeProfile, { nullable: true, description: 'The profile - empty when the employee has written none.' })\n profile?: EmployeeProfile\n}\n"]}
|