@kernhq/module-hr 0.18.1 → 0.19.0
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/contract/capabilities.d.ts.map +1 -1
- package/dist/contract/capabilities.js +16 -0
- package/dist/contract/capabilities.js.map +1 -1
- package/dist/contract/exports.d.ts +459 -0
- package/dist/contract/exports.d.ts.map +1 -0
- package/dist/contract/exports.js +331 -0
- package/dist/contract/exports.js.map +1 -0
- package/dist/contract/index.d.ts +1 -0
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +1 -0
- package/dist/contract/index.js.map +1 -1
- package/dist/contract/permissions.d.ts +8 -0
- package/dist/contract/permissions.d.ts.map +1 -1
- package/dist/contract/permissions.js +32 -3
- package/dist/contract/permissions.js.map +1 -1
- package/dist/contract/router.d.ts +272 -0
- package/dist/contract/router.d.ts.map +1 -1
- package/dist/contract/router.js +67 -0
- package/dist/contract/router.js.map +1 -1
- package/dist/server/router.d.ts +283 -0
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +116 -0
- package/dist/server/router.js.map +1 -1
- package/dist/server/services/exports.d.ts +321 -0
- package/dist/server/services/exports.d.ts.map +1 -0
- package/dist/server/services/exports.js +765 -0
- package/dist/server/services/exports.js.map +1 -0
- package/package.json +1 -1
- package/src/client/messages.ts +13 -0
- package/src/contract/capabilities.ts +16 -0
- package/src/contract/exports.ts +354 -0
- package/src/contract/index.ts +1 -0
- package/src/contract/permissions.ts +34 -3
- package/src/contract/router.ts +73 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { type Tx } from '@kernhq/kernel';
|
|
2
|
+
import type { IsoDate, PayrollExport, PayrollExportManifest, PayrollExportRefusal, PayrollExportTotals, PayrollHoursRow, PayrollLeaveRow, ReportFinality } from '../../contract/index.js';
|
|
3
|
+
import { type ReportsService } from './reports.js';
|
|
4
|
+
/**
|
|
5
|
+
* The payroll export: what it refuses, how it is spelled, and where each number comes from.
|
|
6
|
+
*
|
|
7
|
+
* Same shape as `reports.ts` next door and for the same reason. **Everything above the class is
|
|
8
|
+
* pure** — no `tx`, no clock, no kernel — because the decisions worth pinning here are decisions
|
|
9
|
+
* about *characters*, and a character is invisible in a query plan. A display name with a comma, a
|
|
10
|
+
* quote or a newline is the oldest bug in this format and the one a customer finds first; a
|
|
11
|
+
* `beyond_cap_minutes` written as `0` instead of an empty field is the one that causes a wrong
|
|
12
|
+
* payment. Neither throws, neither fails a type-check, and both look like a working file.
|
|
13
|
+
*
|
|
14
|
+
* **Everything below the class is aggregated in the database.** Day sheets and approved leave are
|
|
15
|
+
* grouped in Postgres, one query per set of people who belonged to the entity on the same days —
|
|
16
|
+
* which for a month nobody transferred through is one query for the whole entity. Nothing here reads
|
|
17
|
+
* a period of day sheets into the process to add them up.
|
|
18
|
+
*
|
|
19
|
+
* Kern does not compute pay. There is no rate, no gross, no net, no deduction and no currency amount
|
|
20
|
+
* below this line, and there must not be one above it either.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* UTF-8 byte order mark.
|
|
24
|
+
*
|
|
25
|
+
* Excel on Windows reads a BOM-less UTF-8 CSV as the system code page and mangles every Turkish and
|
|
26
|
+
* Persian name in it — and this module ships country packs for both. Frozen with the rest of the
|
|
27
|
+
* format: v1 has a BOM for as long as v1 is published.
|
|
28
|
+
*/
|
|
29
|
+
export declare const CSV_BOM = "\uFEFF";
|
|
30
|
+
/** CRLF, per RFC 4180 and frozen with the rest of the format. */
|
|
31
|
+
export declare const CSV_EOL = "\r\n";
|
|
32
|
+
/**
|
|
33
|
+
* One CSV field, RFC 4180.
|
|
34
|
+
*
|
|
35
|
+
* **Null is an empty field, never `0` and never the word "null".** That distinction is the whole
|
|
36
|
+
* point of `beyond_cap_minutes`: empty means no statutory ceiling was in force, `0` means one was and
|
|
37
|
+
* nothing exceeded it, and a provider reading `0` for empty is the one place this export can cause a
|
|
38
|
+
* wrong payment.
|
|
39
|
+
*
|
|
40
|
+
* A value is never altered to defend a spreadsheet. Prefixing a leading `=` or `+` to stop Excel
|
|
41
|
+
* evaluating it is the usual advice, and it would make this file disagree with `people.display_name`
|
|
42
|
+
* — a payroll file that quietly edits the names in it is worse than one that renders a strange name
|
|
43
|
+
* strangely.
|
|
44
|
+
*/
|
|
45
|
+
export declare function csvField(value: string | null | undefined): string;
|
|
46
|
+
/** One CSV record, terminated. */
|
|
47
|
+
export declare function csvLine(fields: ReadonlyArray<string | null | undefined>): string;
|
|
48
|
+
/**
|
|
49
|
+
* A whole CSV: BOM, the column names, then the rows.
|
|
50
|
+
*
|
|
51
|
+
* **Row 1 is the column names and nothing else.** No version banner above them: a line like
|
|
52
|
+
* `kern-payroll-v1` in row 1 is read as the first column name by every importer that assumes the
|
|
53
|
+
* header is the first row — which is most of them and all of the spreadsheet ones — and every field
|
|
54
|
+
* then lands one row down. The version rides in the first *column* instead, where an importer sees
|
|
55
|
+
* it as data.
|
|
56
|
+
*/
|
|
57
|
+
export declare function csvDocument(columns: readonly string[], rows: ReadonlyArray<ReadonlyArray<string | null>>): string;
|
|
58
|
+
/** An integer, as text. */
|
|
59
|
+
export declare const fmtInt: (value: number) => string;
|
|
60
|
+
/** An integer that may be unknown. Null stays null so `csvField` writes an empty field. */
|
|
61
|
+
export declare const fmtNullableInt: (value: number | null) => string | null;
|
|
62
|
+
/**
|
|
63
|
+
* Two decimal places, `.` separated, and never `-0.00`.
|
|
64
|
+
*
|
|
65
|
+
* `fte` and every leave-day figure are written this way, frozen: halves and quarters add up exactly
|
|
66
|
+
* at two places, and a locale-dependent separator would make one customer's file unreadable by
|
|
67
|
+
* another's importer.
|
|
68
|
+
*/
|
|
69
|
+
export declare function fmtDecimal(value: number): string;
|
|
70
|
+
/** `true` / `false`, spelled out. Not 1/0, which a spreadsheet turns into a number column. */
|
|
71
|
+
export declare const fmtBool: (value: boolean) => string;
|
|
72
|
+
/**
|
|
73
|
+
* A legal entity's name, safe for a filename on any filesystem a bureau might use.
|
|
74
|
+
*
|
|
75
|
+
* `Kern Türkiye A.Ş.` → `kern-turkiye-a-s`. Lossy on purpose: the exact name travels in the manifest
|
|
76
|
+
* and in every row of both CSVs, so the filename only has to be legible and stable.
|
|
77
|
+
*/
|
|
78
|
+
export declare function entitySlug(name: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* `2026-06` for a whole calendar month, `2026-06-01_2026-06-15` for anything else.
|
|
81
|
+
*
|
|
82
|
+
* A payroll period is nearly always a month and a bureau reads `2026-06` at a glance; a period that
|
|
83
|
+
* is not one says so rather than being rounded to the month it mostly falls in.
|
|
84
|
+
*/
|
|
85
|
+
export declare function periodLabel(from: IsoDate, to: IsoDate): string;
|
|
86
|
+
/**
|
|
87
|
+
* `kern-payroll-v1_kern-turkiye-a-s_2026-06_hours.csv`, and `DRAFT` where it belongs.
|
|
88
|
+
*
|
|
89
|
+
* The filename is the only part of this export that survives being emailed to a bureau, dropped on a
|
|
90
|
+
* shared drive and opened by somebody who never saw the API, so the contract version leads it. A
|
|
91
|
+
* bureau that receives two files six months apart and opens both under one mapping is the failure
|
|
92
|
+
* this prevents, and it is a failure nobody sees an error for.
|
|
93
|
+
*/
|
|
94
|
+
export declare function exportFilename(input: {
|
|
95
|
+
entityName: string;
|
|
96
|
+
from: IsoDate;
|
|
97
|
+
to: IsoDate;
|
|
98
|
+
file: 'hours' | 'leave' | 'manifest';
|
|
99
|
+
draft: boolean;
|
|
100
|
+
}): string;
|
|
101
|
+
/** What every row of both files repeats, so a row that has lost its manifest still identifies itself. */
|
|
102
|
+
export interface PayrollFileHeader {
|
|
103
|
+
legalEntityId: string;
|
|
104
|
+
legalEntityName: string;
|
|
105
|
+
periodStart: IsoDate;
|
|
106
|
+
periodEnd: IsoDate;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* One `hours.csv` record, in `PAYROLL_HOURS_COLUMNS` order.
|
|
110
|
+
*
|
|
111
|
+
* The order is the file format. Nothing here may be reordered, renamed, added to or removed while v1
|
|
112
|
+
* is published — a positional importer shifts on an appended column, and the shift lands on
|
|
113
|
+
* `unpaid_leave_days`, which is a deduction.
|
|
114
|
+
*/
|
|
115
|
+
export declare function hoursCsvRow(header: PayrollFileHeader, row: PayrollHoursRow): Array<string | null>;
|
|
116
|
+
/** One `leave.csv` record, in `PAYROLL_LEAVE_COLUMNS` order. Frozen exactly as above. */
|
|
117
|
+
export declare function leaveCsvRow(header: PayrollFileHeader, row: PayrollLeaveRow): Array<string | null>;
|
|
118
|
+
/**
|
|
119
|
+
* Everything over the whole population, so a screen states a total before a file exists.
|
|
120
|
+
*
|
|
121
|
+
* `beyondCapMinutes` is totalled through `capTotal` rather than added up: a sum that coalesces null
|
|
122
|
+
* to zero would report "nothing exceeded the ceiling" for a workspace where no ceiling ever applied.
|
|
123
|
+
*/
|
|
124
|
+
export declare function totalsOf(rows: readonly PayrollHoursRow[]): PayrollExportTotals;
|
|
125
|
+
/**
|
|
126
|
+
* Why this export will not be written — the whole list, so a screen shows all of it at once.
|
|
127
|
+
*
|
|
128
|
+
* **Refuse rather than guess** is the rule, and each of these is a case where the alternative is a
|
|
129
|
+
* row of zeros somebody pays from:
|
|
130
|
+
*
|
|
131
|
+
* - **An open period may still move.** `reconcile-days` runs at 02:30 over a fourteen-day window and
|
|
132
|
+
* rebuilds every day a period does not close, so the same export at 18:00 and at 09:00 the next
|
|
133
|
+
* morning can differ with nobody having touched anything. Somebody pays from the first file and
|
|
134
|
+
* reconciles against the second. `draft` is the one escape hatch, and it is a statement the caller
|
|
135
|
+
* makes which the file then repeats — never a toast, because the toast does not travel with the CSV.
|
|
136
|
+
* - **An entity with nobody in it** is a mistyped id or an entity nobody has been moved into yet. An
|
|
137
|
+
* empty file with a correct header looks like a month in which nobody worked.
|
|
138
|
+
* - **A person with no employment row** has no employment type, no FTE, no cost centre and no
|
|
139
|
+
* position — every field a provider picks a rate from, blank. They reach the population through
|
|
140
|
+
* their office rather than their employment, which is a real state the ladder allows and not one
|
|
141
|
+
* anything should be paid on.
|
|
142
|
+
*/
|
|
143
|
+
export declare function exportRefusals(input: {
|
|
144
|
+
legalEntityName: string;
|
|
145
|
+
periodStart: IsoDate;
|
|
146
|
+
periodEnd: IsoDate;
|
|
147
|
+
periodStatus: 'open' | 'locked';
|
|
148
|
+
draft: boolean;
|
|
149
|
+
population: number;
|
|
150
|
+
withoutEmployment: ReadonlyArray<{
|
|
151
|
+
personId: string;
|
|
152
|
+
displayName: string;
|
|
153
|
+
}>;
|
|
154
|
+
}): PayrollExportRefusal[];
|
|
155
|
+
/** Everything `assembleExport` needs that is not one of the rows. */
|
|
156
|
+
export interface PayrollExportAssembly {
|
|
157
|
+
entity: {
|
|
158
|
+
id: string;
|
|
159
|
+
name: string;
|
|
160
|
+
country: string;
|
|
161
|
+
currency: string | null;
|
|
162
|
+
};
|
|
163
|
+
period: {
|
|
164
|
+
id: string;
|
|
165
|
+
startsOn: IsoDate;
|
|
166
|
+
endsOn: IsoDate;
|
|
167
|
+
status: 'open' | 'locked';
|
|
168
|
+
};
|
|
169
|
+
draft: boolean;
|
|
170
|
+
generatedAt: string;
|
|
171
|
+
kernVersion: string;
|
|
172
|
+
/** The keys that produced this population, on the response so two readers cannot disagree silently. */
|
|
173
|
+
permissions: string[];
|
|
174
|
+
dayLengthMinutes: number;
|
|
175
|
+
population: number;
|
|
176
|
+
counted: number;
|
|
177
|
+
attendance: ReportFinality;
|
|
178
|
+
hours: readonly PayrollHoursRow[];
|
|
179
|
+
leave: readonly PayrollLeaveRow[];
|
|
180
|
+
}
|
|
181
|
+
/** The manifest, without the files — shared by the export and its preview. */
|
|
182
|
+
export declare function exportManifest(input: PayrollExportAssembly): PayrollExportManifest;
|
|
183
|
+
/**
|
|
184
|
+
* The three files, from rows that have already been fetched.
|
|
185
|
+
*
|
|
186
|
+
* Pure, so the test pins the bytes without a database: the column order, the quoting, the empty
|
|
187
|
+
* `beyond_cap_minutes`, the filenames and the manifest beside them are all decided here.
|
|
188
|
+
*/
|
|
189
|
+
export declare function assembleExport(input: PayrollExportAssembly): PayrollExport;
|
|
190
|
+
/** What one person's employment looked like over their days in this entity. */
|
|
191
|
+
interface EmploymentFacts {
|
|
192
|
+
employmentType: string;
|
|
193
|
+
fte: number;
|
|
194
|
+
contractHoursWeek: number | null;
|
|
195
|
+
costCenterCode: string | null;
|
|
196
|
+
positionTitle: string | null;
|
|
197
|
+
changedInPeriod: boolean;
|
|
198
|
+
}
|
|
199
|
+
/** A set of people over a set of dates, the same spelling `ReportsService.groupsFor` returns. */
|
|
200
|
+
interface DateGroup {
|
|
201
|
+
personIds: string[] | null;
|
|
202
|
+
dates: string[] | null;
|
|
203
|
+
}
|
|
204
|
+
interface LeaveAggregateRow {
|
|
205
|
+
personId: string;
|
|
206
|
+
leaveTypeKey: string;
|
|
207
|
+
leaveTypeName: string;
|
|
208
|
+
paid: boolean;
|
|
209
|
+
unit: 'day' | 'half_day' | 'hour';
|
|
210
|
+
days: number;
|
|
211
|
+
requests: number;
|
|
212
|
+
}
|
|
213
|
+
/** Everything one export needs, before it is turned into bytes. */
|
|
214
|
+
export interface PayrollExportData {
|
|
215
|
+
entity: {
|
|
216
|
+
id: string;
|
|
217
|
+
name: string;
|
|
218
|
+
country: string;
|
|
219
|
+
currency: string | null;
|
|
220
|
+
};
|
|
221
|
+
period: {
|
|
222
|
+
id: string;
|
|
223
|
+
startsOn: string;
|
|
224
|
+
endsOn: string;
|
|
225
|
+
status: 'open' | 'locked';
|
|
226
|
+
};
|
|
227
|
+
population: number;
|
|
228
|
+
counted: number;
|
|
229
|
+
attendance: ReportFinality;
|
|
230
|
+
hours: PayrollHoursRow[];
|
|
231
|
+
leave: PayrollLeaveRow[];
|
|
232
|
+
refusals: PayrollExportRefusal[];
|
|
233
|
+
totals: PayrollExportTotals;
|
|
234
|
+
}
|
|
235
|
+
export declare class PayrollExportService {
|
|
236
|
+
private readonly reports;
|
|
237
|
+
constructor(reports: ReportsService);
|
|
238
|
+
/**
|
|
239
|
+
* One entity, one period, every row — and every reason it should not be written.
|
|
240
|
+
*
|
|
241
|
+
* The refusals are *returned* rather than thrown, because `payroll.export.preview` has to show all
|
|
242
|
+
* of them at once on a screen. `payroll.export.v1` throws the first.
|
|
243
|
+
*
|
|
244
|
+
* The membership question is the whole design in one line: a row is keyed by (entity, period,
|
|
245
|
+
* person), and a person who transfers mid-period produces two rows, one in each entity's file,
|
|
246
|
+
* each carrying only that entity's days. `ReportsService.population` already answers it — the
|
|
247
|
+
* ladder resolves `employment.legalEntityId ?? office.legalEntityId` per **date**, which is what
|
|
248
|
+
* `setPeriodLock` does on the write side. Attributing the whole period to the entity somebody
|
|
249
|
+
* happened to end it in would report one employer's hours under the other's name and be wrong for
|
|
250
|
+
* both.
|
|
251
|
+
*/
|
|
252
|
+
collect(tx: Tx, input: {
|
|
253
|
+
workspaceId: string;
|
|
254
|
+
legalEntityId: string;
|
|
255
|
+
periodId: string;
|
|
256
|
+
draft: boolean;
|
|
257
|
+
}): Promise<PayrollExportData>;
|
|
258
|
+
/** The employer this file is addressed on behalf of: the fields a filing is made under. */
|
|
259
|
+
entity(tx: Tx, workspaceId: string, legalEntityId: string): Promise<{
|
|
260
|
+
id: string;
|
|
261
|
+
name: string;
|
|
262
|
+
country: string;
|
|
263
|
+
currency: string | null;
|
|
264
|
+
} | undefined>;
|
|
265
|
+
/** The period, which is the range. A caller does not get to draw their own boundary. */
|
|
266
|
+
period(tx: Tx, workspaceId: string, periodId: string): Promise<{
|
|
267
|
+
id: string;
|
|
268
|
+
kind: string;
|
|
269
|
+
legalEntityId: string | null;
|
|
270
|
+
startsOn: string;
|
|
271
|
+
endsOn: string;
|
|
272
|
+
status: string;
|
|
273
|
+
} | undefined>;
|
|
274
|
+
/** Identity and the two dates a provider prorates a joiner or a leaver on. */
|
|
275
|
+
peopleFacts(tx: Tx, workspaceId: string, personIds: string[]): Promise<Map<string, {
|
|
276
|
+
employeeNo: string | null;
|
|
277
|
+
displayName: string;
|
|
278
|
+
hiredOn: string | null;
|
|
279
|
+
terminatedOn: string | null;
|
|
280
|
+
}>>;
|
|
281
|
+
/**
|
|
282
|
+
* The employment facts that let a provider pick a rate, per person — and whether they moved.
|
|
283
|
+
*
|
|
284
|
+
* Two different questions over one set of rows, and answering both from the same filter is a bug
|
|
285
|
+
* this had until it was run against a database:
|
|
286
|
+
*
|
|
287
|
+
* **Which facts to publish** is a question about *this entity's days*. A row qualifies when it
|
|
288
|
+
* overlaps the days the person belonged to this entity and it either names this entity or names
|
|
289
|
+
* none — the second half because the ladder falls back from the employment to the office, so
|
|
290
|
+
* somebody employed with a null entity is genuinely in this file through their desk. The **last**
|
|
291
|
+
* qualifying row wins, so a transferring person contributes their TR row to the TR file and their
|
|
292
|
+
* NL row to the NL file, and neither file carries the other's FTE.
|
|
293
|
+
*
|
|
294
|
+
* **Whether anything changed** is a question about *the period*, over every row, entity or not.
|
|
295
|
+
* Counting only this entity's rows reports `false` for the one case the column exists for: somebody
|
|
296
|
+
* who left the entity on the 15th looks, in this file, like a full-time employee of it for a period
|
|
297
|
+
* running to the 30th, and a monthly-salaried person is then paid a whole month here and a partial
|
|
298
|
+
* month next door. `day_sheets` hints at it and a flag states it. Publishing the end state silently
|
|
299
|
+
* is the failure; the flag is what makes it visible without this module inventing a weighted
|
|
300
|
+
* average nobody asked for.
|
|
301
|
+
*/
|
|
302
|
+
employmentFacts(tx: Tx, workspaceId: string, legalEntityId: string, personIds: string[], datesByPerson: Map<string, string[]> | null, from: string, to: string): Promise<Map<string, EmploymentFacts>>;
|
|
303
|
+
/**
|
|
304
|
+
* Approved leave, per person per type, aggregated in the database.
|
|
305
|
+
*
|
|
306
|
+
* `leave_request_days` filtered `counted and status = 'approved'`, joined out to `leave_requests` →
|
|
307
|
+
* `leave_types`. Three things this is deliberately not:
|
|
308
|
+
*
|
|
309
|
+
* - **not `leave_ledger`**, which is the balance and carries grants, accruals, carry-in and expiry
|
|
310
|
+
* — movements that are not leave anybody took in this period;
|
|
311
|
+
* - **not `leave_requests.minutes` summed per day**, which counts a five-day request five times;
|
|
312
|
+
* - **not converted to minutes**, because `fraction` is exact and `MINUTES_PER_DAY` is a hardcoded
|
|
313
|
+
* eight hours. The manifest publishes the day length for anyone who wants to convert.
|
|
314
|
+
*
|
|
315
|
+
* `sum(fraction)` cannot double count: `hr_leave_days_no_double_booking` refuses a second live row
|
|
316
|
+
* on one person-day, so the join fans out to exactly one row per date.
|
|
317
|
+
*/
|
|
318
|
+
leaveAggregate(tx: Tx, workspaceId: string, group: DateGroup, from: string, to: string): Promise<LeaveAggregateRow[]>;
|
|
319
|
+
}
|
|
320
|
+
export {};
|
|
321
|
+
//# sourceMappingURL=exports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../../src/server/services/exports.ts"],"names":[],"mappings":"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"}
|