@kernhq/module-hr 0.10.0 → 0.10.1

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 (78) hide show
  1. package/dist/contract/capabilities.d.ts +16 -0
  2. package/dist/contract/capabilities.d.ts.map +1 -1
  3. package/dist/contract/capabilities.js +16 -0
  4. package/dist/contract/capabilities.js.map +1 -1
  5. package/dist/policy/accrual.d.ts +35 -4
  6. package/dist/policy/accrual.d.ts.map +1 -1
  7. package/dist/policy/accrual.js +141 -15
  8. package/dist/policy/accrual.js.map +1 -1
  9. package/dist/policy/working-time.d.ts +115 -9
  10. package/dist/policy/working-time.d.ts.map +1 -1
  11. package/dist/policy/working-time.js +120 -20
  12. package/dist/policy/working-time.js.map +1 -1
  13. package/dist/server/jobs.d.ts +14 -6
  14. package/dist/server/jobs.d.ts.map +1 -1
  15. package/dist/server/jobs.js +458 -144
  16. package/dist/server/jobs.js.map +1 -1
  17. package/dist/server/packs/index.d.ts +14 -0
  18. package/dist/server/packs/index.d.ts.map +1 -1
  19. package/dist/server/packs/index.js +19 -0
  20. package/dist/server/packs/index.js.map +1 -1
  21. package/dist/server/router.d.ts +1887 -111
  22. package/dist/server/router.d.ts.map +1 -1
  23. package/dist/server/router.js +129 -63
  24. package/dist/server/router.js.map +1 -1
  25. package/dist/server/schema.d.ts +17 -0
  26. package/dist/server/schema.d.ts.map +1 -1
  27. package/dist/server/schema.js +81 -2
  28. package/dist/server/schema.js.map +1 -1
  29. package/dist/server/services/approvals.d.ts.map +1 -1
  30. package/dist/server/services/approvals.js +12 -3
  31. package/dist/server/services/approvals.js.map +1 -1
  32. package/dist/server/services/attendance.d.ts +120 -6
  33. package/dist/server/services/attendance.d.ts.map +1 -1
  34. package/dist/server/services/attendance.js +226 -13
  35. package/dist/server/services/attendance.js.map +1 -1
  36. package/dist/server/services/policies.d.ts +6 -0
  37. package/dist/server/services/policies.d.ts.map +1 -1
  38. package/dist/server/services/policies.js +6 -0
  39. package/dist/server/services/policies.js.map +1 -1
  40. package/migrations/0005_approval_requester.sql +11 -1
  41. package/migrations/0006_schedule_no_overlap.sql +85 -0
  42. package/migrations/0007_hot_path_indexes.sql +38 -0
  43. package/migrations/0009_beyond_cap_minutes.sql +15 -0
  44. package/migrations/meta/0005_snapshot.json +4047 -0
  45. package/migrations/meta/0007_snapshot.json +4225 -0
  46. package/migrations/meta/0009_snapshot.json +4231 -0
  47. package/migrations/meta/_journal.json +21 -0
  48. package/package.json +7 -7
  49. package/src/client/components/ClockControls.svelte +127 -20
  50. package/src/client/components/ClockControls.test.ts +446 -0
  51. package/src/client/components/DelegationDialog.svelte +12 -3
  52. package/src/client/components/LeaveRequestDialog.svelte +254 -25
  53. package/src/client/components/PersonFormDialog.svelte +53 -3
  54. package/src/client/components/PersonPanel.svelte +134 -26
  55. package/src/client/i18n.ts +5 -927
  56. package/src/client/messages.test.ts +154 -0
  57. package/src/client/messages.ts +3388 -0
  58. package/src/client/mock.ts +1573 -161
  59. package/src/client/module.ts +15 -1
  60. package/src/client/pages/ApprovalsPage.svelte +120 -46
  61. package/src/client/pages/AttendancePage.svelte +106 -20
  62. package/src/client/pages/DirectoryPage.svelte +192 -55
  63. package/src/client/pages/LeavePage.svelte +280 -25
  64. package/src/client/pages/OfficesPage.svelte +26 -8
  65. package/src/client/pages/leave-and-attendance.test.ts +588 -0
  66. package/src/client/query.ts +12 -0
  67. package/src/client/settings/CalendarsSettings.svelte +1363 -12
  68. package/src/client/settings/CapabilitiesSettings.svelte +276 -19
  69. package/src/client/settings/GeneralSettings.svelte +420 -0
  70. package/src/client/settings/LeaveSettings.svelte +884 -12
  71. package/src/client/settings/OfficesSettings.svelte +1182 -12
  72. package/src/client/settings/SchedulesSettings.svelte +1149 -12
  73. package/src/client/summary.ts +14 -7
  74. package/src/client/widgets/ApprovalsWidget.svelte +133 -20
  75. package/src/client/widgets/HeadcountWidget.svelte +74 -8
  76. package/src/client/widgets/LeaveBalanceWidget.svelte +40 -5
  77. package/src/client/widgets/WhosOutWidget.svelte +47 -8
  78. package/src/contract/capabilities.ts +17 -0
@@ -1,9 +1,12 @@
1
1
  import { KernError, uuidv7 } from '@kernhq/kernel';
2
- import { and, asc, eq, gte, inArray, isNull, lte, sql } from 'drizzle-orm';
2
+ import { and, asc, eq, gte, inArray, isNull, lt, lte, or, sql } from 'drizzle-orm';
3
3
  import { weekdayOf } from '../../policy/calendar.js';
4
- import { businessDateFor, computeDay, } from '../../policy/working-time.js';
4
+ import { dateIn, previousDate } from '../../policy/time.js';
5
+ import { attributeToShift, computeDay, openState, } from '../../policy/working-time.js';
5
6
  import { attendanceDays, leaveRequestDays, punches, scheduleAssignments, schedules } from '../schema.js';
6
7
  import { inForceOn } from './db.js';
8
+ import { PolicyService } from './policies.js';
9
+ import { ResolveService } from './resolve.js';
7
10
  /** A schedule with no shifts: somebody with no assignment still clocks in, they just owe no hours. */
8
11
  export const NO_SCHEDULE = {
9
12
  shiftFor: () => null,
@@ -12,6 +15,18 @@ export const NO_SCHEDULE = {
12
15
  scheduleId: null,
13
16
  };
14
17
  export class AttendanceService {
18
+ resolve;
19
+ policies;
20
+ /**
21
+ * Both collaborators are defaulted so `new AttendanceService()` still reads as a leaf service.
22
+ * The period is asked about on every recomputation, and who belongs to a legal entity is asked
23
+ * on every lock — neither question has a second implementation in this module and neither may
24
+ * grow one here.
25
+ */
26
+ constructor(resolve = new ResolveService(), policies = new PolicyService(resolve)) {
27
+ this.resolve = resolve;
28
+ this.policies = policies;
29
+ }
15
30
  /** The schedule in force for a person on a date, as something the pure layer can use. */
16
31
  async scheduleFor(tx, workspaceId, personId, on) {
17
32
  const [assignment] = await tx
@@ -50,21 +65,57 @@ export class AttendanceService {
50
65
  autoClockOutAfterMinutes: schedule.autoClockOutAfterMinutes,
51
66
  };
52
67
  }
68
+ /**
69
+ * Which shift a punch made at `atMs` joins — decided once, from the punches that are already filed.
70
+ *
71
+ * This is the circularity that made the last three attempts at the night-shift boundary
72
+ * unfixable. The shift a punch belonged to was worked out from the clock alone; the guard that
73
+ * decides whether the punch is even possible was then built by reading `punchesOn(that date)`. So
74
+ * the guard could only ever confirm the attribution's own choice, and where the choice was wrong
75
+ * the person was told they were not clocked in at the end of a shift they had just worked. The
76
+ * fact that settles it — is a shift still open — is a question about punches, so it is asked
77
+ * *before* the attribution instead of after it.
78
+ *
79
+ * Both candidate dates come back in one statement, the punch's own local date and the one before
80
+ * it, on `hr_punches_person_idx`. That is fewer queries than the path it replaces, and it is what
81
+ * makes the guard and the attribution incapable of drifting apart: they are the same rows.
82
+ */
83
+ async attribute(tx, workspaceId, personId, atMs, timezone, schedule) {
84
+ const local = dateIn(atMs, timezone);
85
+ const yesterday = previousDate(local);
86
+ const rows = await tx
87
+ .select()
88
+ .from(punches)
89
+ .where(and(eq(punches.workspaceId, workspaceId), eq(punches.personId, personId), inArray(punches.businessDate, [yesterday, local]), isNull(punches.voidedByPunchId)))
90
+ .orderBy(asc(punches.at));
91
+ const filedOn = (date) => rows.filter((r) => r.businessDate === date);
92
+ const { businessDate, shift } = attributeToShift(atMs, timezone, (d) => schedule.shiftFor(d), {
93
+ onLocalDate: openState(filedOn(local)).clockedIn,
94
+ onPreviousDate: openState(filedOn(yesterday)).clockedIn,
95
+ workedPreviousDate: filedOn(yesterday).length > 0,
96
+ });
97
+ const mine = filedOn(businessDate);
98
+ return { businessDate, shift, punches: mine, open: openState(mine) };
99
+ }
53
100
  /**
54
101
  * Record a punch.
55
102
  *
56
- * `at` is the server's clock, always. `clientReportedAt` is kept beside it with the measured skew
57
- * so an offline sync can be told from a device whose clock is wrong and a claim beyond the
58
- * threshold is marked `disputed` rather than silently accepted or silently dropped.
103
+ * Both the instant and the day it counts towards arrive decided. `at` is the server's clock unless
104
+ * the offline sync path says otherwise, and `businessDate` is `attribute`'s answer for that same
105
+ * instant this method used to attribute the punch a second time, from its own `new Date()`
106
+ * rather than from the instant the caller had already reasoned about. Two answers to one question,
107
+ * a millisecond apart, is how both ends of one shift end up on two sheets.
108
+ *
109
+ * `clientReportedAt` is kept beside the instant with the measured skew so an offline sync can be
110
+ * told from a device whose clock is wrong — and a claim beyond the threshold is marked `disputed`
111
+ * rather than silently accepted or silently dropped.
59
112
  */
60
- async record(tx, workspaceId, input, schedule) {
113
+ async record(tx, workspaceId, input) {
61
114
  const serverNow = new Date();
62
- const at = input.claimedAt ?? serverNow;
63
115
  const clientAt = input.clientReportedAt ? new Date(input.clientReportedAt) : null;
64
116
  const skewMs = clientAt ? clientAt.getTime() - serverNow.getTime() : null;
65
117
  // A claim more than an hour out is not a slow network; it is a clock somebody should look at.
66
- const trust = input.claimedAt ? (Math.abs(skewMs ?? 0) > 3600_000 ? 'disputed' : 'claimed') : 'trusted';
67
- const businessDate = businessDateFor(at.getTime(), input.timezone, schedule.shiftFor(new Date(at.getTime()).toISOString().slice(0, 10)));
118
+ const trust = input.claimed ? (Math.abs(skewMs ?? 0) > 3600_000 ? 'disputed' : 'claimed') : 'trusted';
68
119
  const [row] = await tx
69
120
  .insert(punches)
70
121
  .values({
@@ -72,10 +123,10 @@ export class AttendanceService {
72
123
  workspaceId,
73
124
  personId: input.personId,
74
125
  direction: input.direction,
75
- at,
126
+ at: input.at,
76
127
  clientReportedAt: clientAt,
77
128
  skewMs,
78
- businessDate,
129
+ businessDate: input.businessDate,
79
130
  timezone: input.timezone,
80
131
  method: input.method,
81
132
  officeId: input.officeId ?? null,
@@ -104,13 +155,36 @@ export class AttendanceService {
104
155
  * month looks identical to one that had nothing to do.
105
156
  */
106
157
  async recomputeDay(tx, workspaceId, personId, businessDate, timezone, schedule) {
158
+ const day = and(eq(attendanceDays.workspaceId, workspaceId), eq(attendanceDays.personId, personId), eq(attendanceDays.businessDate, businessDate));
107
159
  const [existing] = await tx
108
160
  .select({ locked: attendanceDays.locked })
109
161
  .from(attendanceDays)
110
- .where(and(eq(attendanceDays.workspaceId, workspaceId), eq(attendanceDays.personId, personId), eq(attendanceDays.businessDate, businessDate)))
162
+ .where(day)
111
163
  .limit(1);
112
- if (existing?.locked)
164
+ // Which entity's payroll a day belongs to is a question **about that day**, so it is asked here
165
+ // rather than taken as an argument. Every caller had one to hand and three of them had the
166
+ // wrong one: `clockContext` resolves as of today and its answer was then applied to arbitrary
167
+ // past dates by `punches.void`, `days.recompute` over a whole range, and an approved
168
+ // regularization — so somebody who changed legal entity had March recomputed against the entity
169
+ // they joined in April, found it open, and wrote into a month already filed.
170
+ const { legalEntityId } = await this.resolve.forPerson(tx, workspaceId, personId, businessDate);
171
+ // The column is a *cache* of the period's status, and the period is the authority — asked
172
+ // first, every time, and in both directions. A cache that defaults to false lies about every
173
+ // date the lock swept before the row existed: `periods.lock` stamps the rows that are there,
174
+ // and the first punch on a date inside a closed month then creates a fresh one at the default.
175
+ // Believing a `true` before asking lied the other way, and only ever grew: a row stamped by a
176
+ // lock that has since been reopened, or by a person's employment being corrected underneath
177
+ // one, refused recomputation for ever with nothing behind it.
178
+ //
179
+ // So where a row exists the flag is repaired from the period in whichever direction disagrees —
180
+ // upwards here, downwards in the rebuild below. Where none exists none is written: an absent
181
+ // sheet reads as "nothing was filed for that day", which is true, while a permanently frozen
182
+ // half-day reads as a figure somebody can act on, which it is not.
183
+ if (await this.policies.isLocked(tx, workspaceId, businessDate, legalEntityId)) {
184
+ if (existing && !existing.locked)
185
+ await tx.update(attendanceDays).set({ locked: true }).where(day);
113
186
  return { locked: true };
187
+ }
114
188
  const rows = await this.punchesOn(tx, workspaceId, personId, businessDate);
115
189
  const punchInputs = rows.map((r) => ({
116
190
  at: r.at.getTime(),
@@ -123,12 +197,14 @@ export class AttendanceService {
123
197
  .from(leaveRequestDays)
124
198
  .where(and(eq(leaveRequestDays.workspaceId, workspaceId), eq(leaveRequestDays.personId, personId), eq(leaveRequestDays.date, businessDate), eq(leaveRequestDays.counted, true), eq(leaveRequestDays.status, 'approved')))
125
199
  .limit(1);
200
+ const overtimePolicy = await this.overtimePolicyFor(tx, workspaceId, personId, businessDate);
126
201
  const computed = computeDay({
127
202
  businessDate,
128
203
  timeZone: timezone,
129
204
  shift: schedule.shiftFor(businessDate),
130
205
  punches: punchInputs,
131
206
  rounding: schedule.rounding,
207
+ overtime: overtimePolicy,
132
208
  excused: !!onLeave,
133
209
  });
134
210
  const status = onLeave && computed.workedMinutes === 0 ? 'leave' : computed.status;
@@ -143,6 +219,7 @@ export class AttendanceService {
143
219
  workedMinutes: computed.workedMinutes,
144
220
  breakMinutes: computed.breakMinutes,
145
221
  overtimeMinutes: computed.overtimeMinutes,
222
+ beyondCapMinutes: computed.beyondCapMinutes,
146
223
  lateMinutes: computed.lateMinutes,
147
224
  earlyLeaveMinutes: computed.earlyLeaveMinutes,
148
225
  status,
@@ -160,6 +237,7 @@ export class AttendanceService {
160
237
  workedMinutes: computed.workedMinutes,
161
238
  breakMinutes: computed.breakMinutes,
162
239
  overtimeMinutes: computed.overtimeMinutes,
240
+ beyondCapMinutes: computed.beyondCapMinutes,
163
241
  lateMinutes: computed.lateMinutes,
164
242
  earlyLeaveMinutes: computed.earlyLeaveMinutes,
165
243
  status,
@@ -169,10 +247,145 @@ export class AttendanceService {
169
247
  lastOut: computed.lastOut ? new Date(computed.lastOut) : null,
170
248
  policyHash: hashSchedule(schedule),
171
249
  computedAt: new Date(),
250
+ // The other half of the repair: no period closes this date, so a row still carrying the
251
+ // flag lets go of it here. Rebuilding the figures while leaving `locked` true would
252
+ // publish a sheet nothing can move next to a flag saying nothing may.
253
+ locked: false,
172
254
  },
173
255
  });
174
256
  return { locked: false };
175
257
  }
258
+ /**
259
+ * The overtime rules that apply to one person on one date, as numbers a pure function can use.
260
+ *
261
+ * Resolved here rather than passed in, unlike the schedule: `computeDay` may not touch the
262
+ * database and every caller of `recomputeDay` would otherwise have to walk the policy ladder
263
+ * itself, which is how a rule ends up applied on three paths out of four.
264
+ *
265
+ * Undefined where no policy applies, which is what a workspace that never configured overtime
266
+ * means — every minute past the schedule counts, exactly as it did before the policy was read at
267
+ * all.
268
+ */
269
+ async overtimePolicyFor(tx, workspaceId, personId, businessDate) {
270
+ const resolved = await this.policies.forPerson(tx, workspaceId, personId, 'overtime', businessDate);
271
+ if (!resolved.config)
272
+ return undefined;
273
+ const config = resolved.config;
274
+ const capMinutes = config.capMinutesPerYear ?? null;
275
+ return {
276
+ thresholdMinutes: config.thresholdMinutes ?? 0,
277
+ capMinutes,
278
+ alreadyCountedMinutes: capMinutes === null ? 0 : await this.overtimeCountedBefore(tx, workspaceId, personId, businessDate),
279
+ };
280
+ }
281
+ /**
282
+ * Overtime already counted this year, on the days *before* this one.
283
+ *
284
+ * Strictly before, so a day's figure depends only on days that precede it and recomputing one
285
+ * cannot depend on the order the sweep happens to visit them in. The days after it are then stale
286
+ * against a cap that filled earlier, which the nightly recomputation settles — an order-dependent
287
+ * sheet would not settle at all.
288
+ *
289
+ * The year is the calendar one, because `capMinutesPerYear` is what the config offers; a legal
290
+ * entity closing its year elsewhere would need the cap to say so first.
291
+ */
292
+ async overtimeCountedBefore(tx, workspaceId, personId, businessDate) {
293
+ const [row] = await tx
294
+ .select({ minutes: sql `coalesce(sum(${attendanceDays.overtimeMinutes}), 0)` })
295
+ .from(attendanceDays)
296
+ .where(and(eq(attendanceDays.workspaceId, workspaceId), eq(attendanceDays.personId, personId), gte(attendanceDays.businessDate, `${businessDate.slice(0, 4)}-01-01`), lt(attendanceDays.businessDate, businessDate)));
297
+ return Number(row?.minutes ?? 0);
298
+ }
299
+ /**
300
+ * Stamp `locked` on every day a period covers — and on nobody else's.
301
+ *
302
+ * A period with no legal entity is the whole workspace's. One that names an entity closes *that
303
+ * entity's* month: `PolicyService.isLocked` has always read it that way, and until this method
304
+ * existed the day sheet did not, so closing the Turkish entity's January froze the Dutch and
305
+ * Iranian ones too. Two enforcement mechanisms disagreeing about who a period covers is worse
306
+ * than either of them being wrong on its own, because each looks right from where it is read.
307
+ *
308
+ * Membership is asked of the resolution ladder rather than joined here: which entity somebody is
309
+ * in is not a column on `people` — the employment in force says, and where it does not, their
310
+ * primary office does — and that order has exactly one implementation in this module. It is asked
311
+ * **as of each day**, the same date `isLocked` will be asked about later, because the day is what
312
+ * belongs to an entity: resolving everybody once at the period's last day stamped the whole month
313
+ * of somebody who transferred in halfway through it, including the half they spent elsewhere —
314
+ * days no Dutch period had closed, frozen by a Turkish one.
315
+ *
316
+ * Releasing is not the mirror of stamping. The exclusion constraint keys on
317
+ * `coalesce(legal_entity_id, …)`, so a workspace-wide period and an entity's period may cover the
318
+ * same dates on purpose — and reopening the narrower one must not unlock a month the wider one
319
+ * has filed. So a day is released only where nothing still closes it. That reads the period's own
320
+ * status, which the handler writes before calling this: a period reopening itself would otherwise
321
+ * be the reason it cannot let go.
322
+ */
323
+ async setPeriodLock(tx, workspaceId, period, locked) {
324
+ const inRange = [
325
+ eq(attendanceDays.workspaceId, workspaceId),
326
+ gte(attendanceDays.businessDate, period.startsOn),
327
+ lte(attendanceDays.businessDate, period.endsOn),
328
+ ];
329
+ // Closing a period that names no entity closes the workspace, and there is nothing to ask the
330
+ // ladder about: one statement, as it always was. Every other combination needs to know which
331
+ // entity somebody was in on the day — to decide whether the period covers them, or whether
332
+ // anything else still does.
333
+ if (!period.legalEntityId && locked) {
334
+ const swept = await tx
335
+ .update(attendanceDays)
336
+ .set({ locked })
337
+ .where(and(...inRange))
338
+ .returning({ id: attendanceDays.id });
339
+ return swept.length;
340
+ }
341
+ const candidates = await tx
342
+ .selectDistinct({ personId: attendanceDays.personId, businessDate: attendanceDays.businessDate })
343
+ .from(attendanceDays)
344
+ .where(and(...inRange));
345
+ if (!candidates.length)
346
+ return 0;
347
+ // One resolution per date rather than per row: a month is at most thirty-one ladder walks
348
+ // whatever the headcount, where a walk per person-day would be that times everybody.
349
+ const peopleOn = new Map();
350
+ for (const c of candidates)
351
+ peopleOn.set(c.businessDate, [...(peopleOn.get(c.businessDate) ?? []), c.personId]);
352
+ const entityOn = new Map();
353
+ for (const [date, ids] of peopleOn) {
354
+ const resolved = await this.resolve.forPeople(tx, workspaceId, [...new Set(ids)], date);
355
+ for (const id of ids)
356
+ entityOn.set(`${id}|${date}`, resolved.get(id)?.legalEntityId ?? null);
357
+ }
358
+ const stillClosed = new Map();
359
+ const closedByAnything = async (date, entity) => {
360
+ const key = `${entity ?? 'workspace'}|${date}`;
361
+ const seen = stillClosed.get(key);
362
+ if (seen !== undefined)
363
+ return seen;
364
+ const answer = await this.policies.isLocked(tx, workspaceId, date, entity);
365
+ stillClosed.set(key, answer);
366
+ return answer;
367
+ };
368
+ const mine = [];
369
+ for (const c of candidates) {
370
+ const entity = entityOn.get(`${c.personId}|${c.businessDate}`) ?? null;
371
+ if (period.legalEntityId && entity !== period.legalEntityId)
372
+ continue;
373
+ if (!locked && (await closedByAnything(c.businessDate, entity)))
374
+ continue;
375
+ mine.push(c);
376
+ }
377
+ if (!mine.length)
378
+ return 0;
379
+ const days = new Map();
380
+ for (const m of mine)
381
+ days.set(m.personId, [...(days.get(m.personId) ?? []), m.businessDate]);
382
+ const rows = await tx
383
+ .update(attendanceDays)
384
+ .set({ locked })
385
+ .where(and(eq(attendanceDays.workspaceId, workspaceId), or(...[...days].map(([personId, dates]) => and(eq(attendanceDays.personId, personId), inArray(attendanceDays.businessDate, dates))))))
386
+ .returning({ id: attendanceDays.id });
387
+ return rows.length;
388
+ }
176
389
  /** Which business dates a person has punches on, in a range. Drives a bulk recompute. */
177
390
  async datesWithPunches(tx, workspaceId, personId, from, to) {
178
391
  const rows = await tx
@@ -1 +1 @@
1
- {"version":3,"file":"attendance.js","sourceRoot":"","sources":["../../../src/server/services/attendance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attendance.js","sourceRoot":"","sources":["../../../src/server/services/attendance.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,12 @@ export declare class PolicyService {
36
36
  * The one question every recomputation asks before writing. A locked month must not move
37
37
  * underneath a payroll that has already been filed, so anything affecting it becomes an
38
38
  * adjustment in the open period instead.
39
+ *
40
+ * `attendance_days.locked` is a cache of this answer and defers to it in both directions — the
41
+ * flag is never believed ahead of the period, in either state. `on` and `legalEntityId` have to
42
+ * describe the same moment: the entity is the one that employed the person **on that date**, not
43
+ * the one they are in today, or a month filed under an entity somebody has since left reads as
44
+ * open.
39
45
  */
40
46
  isLocked(tx: Tx, workspaceId: string, on: string, legalEntityId?: string | null): Promise<boolean>;
41
47
  /** Refuses a write into a closed month with a sentence rather than a constraint error. */
@@ -1 +1 @@
1
- {"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../../../src/server/services/policies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,EAAE,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAO,GAAG,EAAY,OAAO,EAAwB,MAAM,aAAa,CAAA;AAC/E,OAAO,EACL,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,yBAAyB,CAAA;AAGhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD;;;;;;;GAOG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAEpD;;;;;;OAMG;IACG,SAAS,CACb,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,EAAE,GAAE,MAAmB,GACtB,OAAO,CAAC,cAAc,CAAC;IAwD1B;;;;;OAKG;IACG,SAAS,CACb,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,UAAU,EAChB,EAAE,GAAE,MAAmB,GACtB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAwDvC,2FAA2F;IAC3F,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM;IAInD;;;;;;OAMG;IACG,QAAQ,CACZ,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,aAAa,GAAE,MAAM,GAAG,IAAW,GAClC,OAAO,CAAC,OAAO,CAAC;IAqBnB,0FAA0F;IACpF,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,GAAE,MAAM,GAAG,IAAW;CAO9F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAQlE;AAED,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../../../src/server/services/policies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,EAAE,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAO,GAAG,EAAY,OAAO,EAAwB,MAAM,aAAa,CAAA;AAC/E,OAAO,EACL,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,yBAAyB,CAAA;AAGhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD;;;;;;;GAOG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAEpD;;;;;;OAMG;IACG,SAAS,CACb,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,EAAE,GAAE,MAAmB,GACtB,OAAO,CAAC,cAAc,CAAC;IAwD1B;;;;;OAKG;IACG,SAAS,CACb,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,UAAU,EAChB,EAAE,GAAE,MAAmB,GACtB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAwDvC,2FAA2F;IAC3F,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM;IAInD;;;;;;;;;;;;OAYG;IACG,QAAQ,CACZ,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,aAAa,GAAE,MAAM,GAAG,IAAW,GAClC,OAAO,CAAC,OAAO,CAAC;IAqBnB,0FAA0F;IACpF,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,aAAa,GAAE,MAAM,GAAG,IAAW;CAO9F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAQlE;AAED,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA"}
@@ -118,6 +118,12 @@ export class PolicyService {
118
118
  * The one question every recomputation asks before writing. A locked month must not move
119
119
  * underneath a payroll that has already been filed, so anything affecting it becomes an
120
120
  * adjustment in the open period instead.
121
+ *
122
+ * `attendance_days.locked` is a cache of this answer and defers to it in both directions — the
123
+ * flag is never believed ahead of the period, in either state. `on` and `legalEntityId` have to
124
+ * describe the same moment: the entity is the one that employed the person **on that date**, not
125
+ * the one they are in today, or a month filed under an entity somebody has since left reads as
126
+ * open.
121
127
  */
122
128
  async isLocked(tx, workspaceId, on, legalEntityId = null) {
123
129
  const [row] = await tx
@@ -1 +1 @@
1
- {"version":3,"file":"policies.js","sourceRoot":"","sources":["../../../src/server/services/policies.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"policies.js","sourceRoot":"","sources":["../../../src/server/services/policies.ts"],"names":[],"mappings":"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"}
@@ -16,5 +16,15 @@ alter table "mod_hr"."approval_requests"
16
16
  -- The inbox lists by approver and then names the requester, so the lookup is by request, not by
17
17
  -- requester — this index is for "everything Ayşe has asked for", which the person page reads.
18
18
  -- `requested_at` is the ORM's name for it; the column is `created_at`, from the shared helper.
19
+ --
20
+ -- `desc nulls last`, not bare `desc`. Postgres reads `desc` as DESC NULLS FIRST, while drizzle
21
+ -- writes DESC NULLS LAST for `t.requestedAt.desc()` — so the database and the snapshot described
22
+ -- the same index differently, permanently and invisibly, until check-snapshot-drift.mjs learned to
23
+ -- compare sort order.
24
+ --
25
+ -- No corrective migration for instances that already ran this. `created_at` is NOT NULL, so the two
26
+ -- orderings are indistinguishable: there is no row for the null ordering to place. Dropping and
27
+ -- rebuilding the index would take an ACCESS EXCLUSIVE lock to change nothing anybody can observe.
28
+ -- Every statement in this file is `if not exists`, so re-running it after this edit is a no-op.
19
29
  create index if not exists "hr_approval_requests_requester_idx"
20
- on "mod_hr"."approval_requests" ("workspace_id", "requester_person_id", "created_at" desc);
30
+ on "mod_hr"."approval_requests" ("workspace_id", "requester_person_id", "created_at" desc nulls last);
@@ -0,0 +1,85 @@
1
+ -- Two schedules may not be in force for one person on the same day.
2
+ --
3
+ -- `employments`, `office_assignments`, `policy_assignments` and `periods` each got an exclusion
4
+ -- constraint the day their table was created; `schedule_assignments` was the one effective-dated
5
+ -- table left with nothing but a btree, and the gap is not theoretical. `scheduleFor` selects the
6
+ -- assignment in force with `limit 1` and no `order by`, so with two rows in force it takes whichever
7
+ -- the executor hands back first — and the inline recompute and the nightly job read at different
8
+ -- times, on different plans. The symptom is `scheduled_minutes`, `late_minutes` and
9
+ -- `overtime_minutes` changing between one computation and the next, on rows a locked payroll period
10
+ -- has already been filed against.
11
+ --
12
+ -- The overlap is easy to create: `attendance.schedules.assign` closes only rows whose `effective_to`
13
+ -- is null, so a backdated assignment lands on top of an already-closed row and neither is trimmed.
14
+
15
+ -- ---------------------------------------------------------------------------------------------
16
+ -- Repair first. An exclusion constraint is validated in full when it is added, so one overlapping
17
+ -- pair anywhere in the instance aborts the whole migration and the release with it.
18
+ --
19
+ -- The repair is the rule `assign` already means to apply, run over every row rather than only the
20
+ -- open one: each assignment ends the day before the next one for that person begins. Nothing is
21
+ -- deleted — an effective-dated table exists to answer "which schedule was she on in March", and a
22
+ -- row removed to satisfy a constraint takes that answer with it. Rows are ordered by
23
+ -- `(effective_from, created_at, id)` so two assignments starting on the same day resolve the same
24
+ -- way every time: the later-created one wins, and the earlier is left recording a period that
25
+ -- covers no day.
26
+ --
27
+ -- `force row level security` is on this table, and a migration runs on a plain pooled connection
28
+ -- with no `app.workspace_id` set — so the policy evaluates to null for every row and an UPDATE here
29
+ -- would report success having touched nothing. FORCE means the owner is not exempt either. The
30
+ -- table is unforced for the length of the repair and forced again immediately; ALTER TABLE holds an
31
+ -- ACCESS EXCLUSIVE lock, and drizzle runs the folder in one transaction, so no other session can
32
+ -- read the table through the gap.
33
+ alter table "mod_hr"."schedule_assignments" no force row level security;--> statement-breakpoint
34
+
35
+ with ordered as (
36
+ select
37
+ "id",
38
+ "effective_from",
39
+ "effective_to",
40
+ lead("effective_from") over (
41
+ partition by "workspace_id", "person_id"
42
+ order by "effective_from", "created_at", "id"
43
+ ) as next_from
44
+ from "mod_hr"."schedule_assignments"
45
+ )
46
+ update "mod_hr"."schedule_assignments" a
47
+ set "effective_to" = ordered.next_from - 1
48
+ from ordered
49
+ where a."id" = ordered."id"
50
+ and ordered.next_from is not null
51
+ and (a."effective_to" is null or a."effective_to" >= ordered.next_from);--> statement-breakpoint
52
+
53
+ alter table "mod_hr"."schedule_assignments" force row level security;--> statement-breakpoint
54
+
55
+ -- ---------------------------------------------------------------------------------------------
56
+ -- The constraint. Same shape as `hr_employments_no_overlap`, with one addition the others do not
57
+ -- carry: rows whose `effective_to` fell before their `effective_from` sit outside it.
58
+ --
59
+ -- `daterange(from, to, '[]')` does not return an empty range for a reversed pair, it raises — so
60
+ -- without the predicate a backdated assignment would fail at `assign` time with a raw Postgres
61
+ -- range error instead of doing the sensible thing. Such a row applies to no day (`inForceOn` needs
62
+ -- `effective_from <= d` and `effective_to >= d` at once, which it can never satisfy), so it cannot
63
+ -- be the second schedule in force that this constraint exists to prevent.
64
+ --
65
+ -- `add constraint` has no `if not exists`, hence the catalogue check — the same shape
66
+ -- `ensure_punch_partition` uses in 0003 for `create policy`.
67
+ do $$
68
+ begin
69
+ if not exists (
70
+ select 1
71
+ from pg_constraint c
72
+ join pg_class t on t.oid = c.conrelid
73
+ join pg_namespace n on n.oid = t.relnamespace
74
+ where n.nspname = 'mod_hr'
75
+ and t.relname = 'schedule_assignments'
76
+ and c.conname = 'hr_schedule_assign_no_overlap'
77
+ ) then
78
+ alter table "mod_hr"."schedule_assignments"
79
+ add constraint "hr_schedule_assign_no_overlap"
80
+ exclude using gist (
81
+ "person_id" with =,
82
+ daterange("effective_from", "effective_to", '[]') with &&
83
+ ) where ("effective_to" is null or "effective_to" >= "effective_from");
84
+ end if;
85
+ end $$;
@@ -0,0 +1,38 @@
1
+ -- Two queries that ran without an index they could use. Neither is new; both only get slower.
2
+
3
+ -- ---------------------------------------------------------------------------------------------
4
+ -- The approvals inbox.
5
+ --
6
+ -- `inboxFor` asks `approver_ids && ARRAY[…]::uuid[]`, and the three btrees on this table cannot
7
+ -- answer an array overlap at all — so the query a manager triggers every time they open the inbox
8
+ -- read the whole table, and the table has no ceiling: a step is written for every request ever
9
+ -- raised and never removed.
10
+ --
11
+ -- Plain GIN, not `btree_gin`: GIN indexes the array's elements, which is exactly what `&&` searches.
12
+ -- Folding `workspace_id` in beside it would need the extension and buys nothing — the overlap has
13
+ -- already reduced the table to the rows naming this approver by the time the workspace filter runs.
14
+ create index if not exists "hr_approval_steps_approvers_idx"
15
+ on "mod_hr"."approval_steps" using gin ("approver_ids");--> statement-breakpoint
16
+
17
+ -- ---------------------------------------------------------------------------------------------
18
+ -- The auto-clock-out sweep.
19
+ --
20
+ -- The hourly job asks for punches on `workspace_id`, `direction = 'in'`, `voided_by_punch_id is
21
+ -- null` and `at <= cutoff`. Before this index none of those four columns was indexed —
22
+ -- `hr_punches_person_idx` starts on `(workspace_id, person_id, …)` and `hr_punches_idem_uq` is
23
+ -- partial on `idempotency_key` — so the sweep scanned every partition of a table sized at half a
24
+ -- million rows a year, once an hour, for every workspace.
25
+ --
26
+ -- Why the split between predicate and columns is the way round it is: `voided_by_punch_id is null`
27
+ -- is emitted literally, so the planner can always prove the query implies the partial predicate,
28
+ -- while `direction = 'in'` arrives as a bind parameter that a generic plan cannot match against a
29
+ -- constant in a predicate. A predicate the planner cannot prove is an index the query never uses.
30
+ --
31
+ -- Created on the partitioned parent, which is what makes it a partitioned index: Postgres builds a
32
+ -- matching index on every existing partition and on every one `ensure_punch_partition` creates
33
+ -- later. That also rules out `concurrently` — Postgres does not support it on a partitioned parent,
34
+ -- and drizzle runs the whole folder in one transaction regardless. On an instance with real punch
35
+ -- history this statement holds a write lock for the length of the build.
36
+ create index if not exists "hr_punches_open_idx"
37
+ on "mod_hr"."punches" ("workspace_id", "direction", "at")
38
+ where "voided_by_punch_id" is null;
@@ -0,0 +1,15 @@
1
+ -- Overtime a statutory ceiling will not take, as a number rather than only as a word.
2
+ --
3
+ -- `computeDay` applies the overtime policy's cap and knows how much went past it, but the day sheet
4
+ -- had nowhere to put the figure: it reached the row only as the `overtime_beyond_cap` anomaly, and
5
+ -- text cannot be summed or filtered. A ceiling like Türkiye's 270 annual hours is exactly the number
6
+ -- somebody has to total over a year to know whether the company is inside the law.
7
+ --
8
+ -- Nullable, and deliberately not defaulted to zero: null means no cap was in force that day, zero
9
+ -- means one was and nothing exceeded it. A report that cannot tell those apart reads every uncapped
10
+ -- day as a compliant one. The anomaly stays beside it — the column is what a report sums, the
11
+ -- anomaly is what puts the day in front of a person.
12
+ --
13
+ -- Additive, so the image before this one reads the table unchanged. Generated by drizzle-kit and
14
+ -- then given `if not exists`, because a migration re-run after an edit must be a no-op.
15
+ ALTER TABLE "mod_hr"."attendance_days" ADD COLUMN IF NOT EXISTS "beyond_cap_minutes" integer;