@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.
- package/dist/contract/capabilities.d.ts +16 -0
- 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/policy/accrual.d.ts +35 -4
- package/dist/policy/accrual.d.ts.map +1 -1
- package/dist/policy/accrual.js +141 -15
- package/dist/policy/accrual.js.map +1 -1
- package/dist/policy/working-time.d.ts +115 -9
- package/dist/policy/working-time.d.ts.map +1 -1
- package/dist/policy/working-time.js +120 -20
- package/dist/policy/working-time.js.map +1 -1
- package/dist/server/jobs.d.ts +14 -6
- package/dist/server/jobs.d.ts.map +1 -1
- package/dist/server/jobs.js +458 -144
- package/dist/server/jobs.js.map +1 -1
- package/dist/server/packs/index.d.ts +14 -0
- package/dist/server/packs/index.d.ts.map +1 -1
- package/dist/server/packs/index.js +19 -0
- package/dist/server/packs/index.js.map +1 -1
- package/dist/server/router.d.ts +1887 -111
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +129 -63
- package/dist/server/router.js.map +1 -1
- package/dist/server/schema.d.ts +17 -0
- package/dist/server/schema.d.ts.map +1 -1
- package/dist/server/schema.js +81 -2
- package/dist/server/schema.js.map +1 -1
- package/dist/server/services/approvals.d.ts.map +1 -1
- package/dist/server/services/approvals.js +12 -3
- package/dist/server/services/approvals.js.map +1 -1
- package/dist/server/services/attendance.d.ts +120 -6
- package/dist/server/services/attendance.d.ts.map +1 -1
- package/dist/server/services/attendance.js +226 -13
- package/dist/server/services/attendance.js.map +1 -1
- package/dist/server/services/policies.d.ts +6 -0
- package/dist/server/services/policies.d.ts.map +1 -1
- package/dist/server/services/policies.js +6 -0
- package/dist/server/services/policies.js.map +1 -1
- package/migrations/0005_approval_requester.sql +11 -1
- package/migrations/0006_schedule_no_overlap.sql +85 -0
- package/migrations/0007_hot_path_indexes.sql +38 -0
- package/migrations/0009_beyond_cap_minutes.sql +15 -0
- package/migrations/meta/0005_snapshot.json +4047 -0
- package/migrations/meta/0007_snapshot.json +4225 -0
- package/migrations/meta/0009_snapshot.json +4231 -0
- package/migrations/meta/_journal.json +21 -0
- package/package.json +7 -7
- package/src/client/components/ClockControls.svelte +127 -20
- package/src/client/components/ClockControls.test.ts +446 -0
- package/src/client/components/DelegationDialog.svelte +12 -3
- package/src/client/components/LeaveRequestDialog.svelte +254 -25
- package/src/client/components/PersonFormDialog.svelte +53 -3
- package/src/client/components/PersonPanel.svelte +134 -26
- package/src/client/i18n.ts +5 -927
- package/src/client/messages.test.ts +154 -0
- package/src/client/messages.ts +3388 -0
- package/src/client/mock.ts +1573 -161
- package/src/client/module.ts +15 -1
- package/src/client/pages/ApprovalsPage.svelte +120 -46
- package/src/client/pages/AttendancePage.svelte +106 -20
- package/src/client/pages/DirectoryPage.svelte +192 -55
- package/src/client/pages/LeavePage.svelte +280 -25
- package/src/client/pages/OfficesPage.svelte +26 -8
- package/src/client/pages/leave-and-attendance.test.ts +588 -0
- package/src/client/query.ts +12 -0
- package/src/client/settings/CalendarsSettings.svelte +1363 -12
- package/src/client/settings/CapabilitiesSettings.svelte +276 -19
- package/src/client/settings/GeneralSettings.svelte +420 -0
- package/src/client/settings/LeaveSettings.svelte +884 -12
- package/src/client/settings/OfficesSettings.svelte +1182 -12
- package/src/client/settings/SchedulesSettings.svelte +1149 -12
- package/src/client/summary.ts +14 -7
- package/src/client/widgets/ApprovalsWidget.svelte +133 -20
- package/src/client/widgets/HeadcountWidget.svelte +74 -8
- package/src/client/widgets/LeaveBalanceWidget.svelte +40 -5
- package/src/client/widgets/WhosOutWidget.svelte +47 -8
- 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 {
|
|
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
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
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
|
|
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.
|
|
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(
|
|
162
|
+
.where(day)
|
|
111
163
|
.limit(1);
|
|
112
|
-
|
|
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":"AAAA,OAAO,EAAE,SAAS,EAAW,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EACL,eAAe,EACf,UAAU,GAIX,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxG,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAsBnC,sGAAsG;AACtG,MAAM,CAAC,MAAM,WAAW,GAAqB;IAC3C,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;IACpB,QAAQ,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE;IAClD,wBAAwB,EAAE,IAAI;IAC9B,UAAU,EAAE,IAAI;CACjB,CAAA;AAED,MAAM,OAAO,iBAAiB;IAC5B,yFAAyF;IACzF,KAAK,CAAC,WAAW,CAAC,EAAM,EAAE,WAAmB,EAAE,QAAgB,EAAE,EAAU;QACzE,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,EAAE;aAC1B,MAAM,EAAE;aACR,IAAI,CAAC,mBAAmB,CAAC;aACzB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,EAChD,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC1C,SAAS,CAAC,mBAAmB,CAAC,aAAa,EAAE,mBAAmB,CAAC,WAAW,EAAE,EAAE,CAAC,CAClF,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,CAAC,UAAU;YAAE,OAAO,WAAW,CAAA;QAEnC,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,EAAE;aACR,IAAI,CAAC,SAAS,CAAC;aACf,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;aAC3F,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,CAAC,QAAQ;YAAE,OAAO,WAAW,CAAA;QAEjC,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAiB,CAAA;QAClD,OAAO;YACL,UAAU,EAAE,QAAQ,CAAC,EAAE;YACvB,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE;gBACzB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;gBACjC,IAAI,CAAC,GAAG;oBAAE,OAAO,IAAI,CAAA;gBACrB,OAAO;oBACL,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,GAAG,EAAE,GAAG,CAAC,GAAG;oBACZ,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,CAAC;oBACnC,cAAc,EAAE,QAAQ,CAAC,cAAc;oBACvC,eAAe,EAAE,QAAQ,CAAC,eAAe;iBAC1C,CAAA;YACH,CAAC;YACD,QAAQ,EAAE;gBACR,WAAW,EAAE,QAAQ,CAAC,mBAAmB;gBACzC,SAAS,EAAE,QAAQ,CAAC,iBAAgD;aACrE;YACD,wBAAwB,EAAE,QAAQ,CAAC,wBAAwB;SAC5D,CAAA;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CACV,EAAM,EACN,WAAmB,EACnB,KAYC,EACD,QAA0B;QAE1B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;QAC5B,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,IAAI,SAAS,CAAA;QACvC,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACjF,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAEzE,8FAA8F;QAC9F,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAEvG,MAAM,YAAY,GAAG,eAAe,CAClC,EAAE,CAAC,OAAO,EAAE,EACZ,KAAK,CAAC,QAAQ,EACd,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CACrE,CAAA;QAED,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;aACnB,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC;YACN,EAAE,EAAE,MAAM,EAAE;YACZ,WAAW;YACX,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,EAAE;YACF,gBAAgB,EAAE,QAAQ;YAC1B,MAAM;YACN,YAAY;YACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;YAChC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,IAAI;YACtB,KAAK;YACL,cAAc,EAAE,KAAK,CAAC,cAAc,IAAI,IAAI;YAC5C,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;SACzB,CAAC;aACD,SAAS,EAAE,CAAA;QACd,OAAO,GAAI,CAAA;IACb,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,SAAS,CAAC,EAAM,EAAE,WAAmB,EAAE,QAAgB,EAAE,YAAoB;QACjF,OAAO,EAAE;aACN,MAAM,EAAE;aACR,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC9B,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,EACtC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAChC,CACF;aACA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;IAC7B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAChB,EAAM,EACN,WAAmB,EACnB,QAAgB,EAChB,YAAoB,EACpB,QAAgB,EAChB,QAA0B;QAE1B,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,CAAC;aACzC,IAAI,CAAC,cAAc,CAAC;aACpB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,EAC3C,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACrC,EAAE,CAAC,cAAc,CAAC,YAAY,EAAE,YAAY,CAAC,CAC9C,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,QAAQ,EAAE,MAAM;YAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QAE7C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;QAC1E,MAAM,WAAW,GAAiB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjD,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE;YAClB,SAAS,EAAE,CAAC,CAAC,SAAoC;SAClD,CAAC,CAAC,CAAA;QAEH,2FAA2F;QAC3F,sFAAsF;QACtF,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;aACvB,MAAM,CAAC,EAAE,SAAS,EAAE,gBAAgB,CAAC,SAAS,EAAE,CAAC;aACjD,IAAI,CAAC,gBAAgB,CAAC;aACtB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,EAC7C,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACvC,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,YAAY,CAAC,EACvC,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,EAClC,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CACxC,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAA;QAEX,MAAM,QAAQ,GAAG,UAAU,CAAC;YAC1B,YAAY;YACZ,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;YACtC,OAAO,EAAE,WAAW;YACpB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,OAAO,IAAI,QAAQ,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAA;QAElF,MAAM,EAAE;aACL,MAAM,CAAC,cAAc,CAAC;aACtB,MAAM,CAAC;YACN,EAAE,EAAE,MAAM,EAAE;YACZ,WAAW;YACX,QAAQ;YACR,YAAY;YACZ,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;YAC3C,aAAa,EAAE,QAAQ,CAAC,aAAa;YACrC,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;YAC7C,MAAM;YACN,cAAc,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI;YAC1C,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;YAC7D,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;YAC7D,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC;YAClC,UAAU,EAAE,IAAI,IAAI,EAAE;SACvB,CAAC;aACD,kBAAkB,CAAC;YAClB,MAAM,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,YAAY,CAAC;YAC1F,GAAG,EAAE;gBACH,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;gBAC3C,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,eAAe,EAAE,QAAQ,CAAC,eAAe;gBACzC,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;gBAC7C,MAAM;gBACN,cAAc,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI;gBAC1C,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;gBAC7D,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;gBAC7D,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC;gBAClC,UAAU,EAAE,IAAI,IAAI,EAAE;aACvB;SACF,CAAC,CAAA;QAEJ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IAC1B,CAAC;IAED,yFAAyF;IACzF,KAAK,CAAC,gBAAgB,CACpB,EAAM,EACN,WAAmB,EACnB,QAAgB,EAChB,IAAY,EACZ,EAAU;QAEV,MAAM,IAAI,GAAG,MAAM,EAAE;aAClB,cAAc,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;aACtD,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC9B,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,EAC/B,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAC9B,CACF,CAAA;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAA;IAC/C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CACb,EAAM,EACN,WAAmB,EACnB,OAAe,EACf,MAAc,EACd,aAA4B;QAE5B,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,EAAE;aACR,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;aACzE,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,CAAC,QAAQ;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAChD,IAAI,QAAQ,CAAC,eAAe;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,8BAA8B,CAAC,CAAA;QAEtF,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,EAAE;aAC1B,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC;YACN,EAAE,EAAE,MAAM,EAAE;YACZ,WAAW;YACX,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,SAAS,OAAO,KAAK,MAAM,EAAE;SACpC,CAAC;aACD,SAAS,EAAE,CAAA;QAEd,MAAM,EAAE;aACL,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,EAAE,eAAe,EAAE,UAAW,CAAC,EAAE,EAAE,CAAC;aACxC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAEvF,6FAA6F;QAC7F,0CAA0C;QAC1C,MAAM,EAAE;aACL,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,EAAE,eAAe,EAAE,UAAW,CAAC,EAAE,EAAE,CAAC;aACxC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,UAAW,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAE9F,KAAK,aAAa,CAAA;QAClB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAW,EAAE,CAAA;IAC9C,CAAC;CACF;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,QAA0B;IAC9C,OAAO,GAAG,QAAQ,CAAC,UAAU,IAAI,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAA;AAC3G,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"attendance.js","sourceRoot":"","sources":["../../../src/server/services/attendance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAW,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAElF,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EACL,gBAAgB,EAChB,UAAU,EAEV,SAAS,GAIV,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxG,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAsB7C,sGAAsG;AACtG,MAAM,CAAC,MAAM,WAAW,GAAqB;IAC3C,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;IACpB,QAAQ,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE;IAClD,wBAAwB,EAAE,IAAI;IAC9B,UAAU,EAAE,IAAI;CACjB,CAAA;AAwBD,MAAM,OAAO,iBAAiB;IAQT;IACA;IARnB;;;;;OAKG;IACH,YACmB,UAA0B,IAAI,cAAc,EAAE,EAC9C,WAA0B,IAAI,aAAa,CAAC,OAAO,CAAC;QADpD,YAAO,GAAP,OAAO,CAAuC;QAC9C,aAAQ,GAAR,QAAQ,CAA4C;IACpE,CAAC;IAEJ,yFAAyF;IACzF,KAAK,CAAC,WAAW,CAAC,EAAM,EAAE,WAAmB,EAAE,QAAgB,EAAE,EAAU;QACzE,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,EAAE;aAC1B,MAAM,EAAE;aACR,IAAI,CAAC,mBAAmB,CAAC;aACzB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,EAChD,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC1C,SAAS,CAAC,mBAAmB,CAAC,aAAa,EAAE,mBAAmB,CAAC,WAAW,EAAE,EAAE,CAAC,CAClF,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,CAAC,UAAU;YAAE,OAAO,WAAW,CAAA;QAEnC,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,EAAE;aACR,IAAI,CAAC,SAAS,CAAC;aACf,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;aAC3F,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,CAAC,QAAQ;YAAE,OAAO,WAAW,CAAA;QAEjC,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAiB,CAAA;QAClD,OAAO;YACL,UAAU,EAAE,QAAQ,CAAC,EAAE;YACvB,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE;gBACzB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;gBACjC,IAAI,CAAC,GAAG;oBAAE,OAAO,IAAI,CAAA;gBACrB,OAAO;oBACL,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,GAAG,EAAE,GAAG,CAAC,GAAG;oBACZ,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,CAAC;oBACnC,cAAc,EAAE,QAAQ,CAAC,cAAc;oBACvC,eAAe,EAAE,QAAQ,CAAC,eAAe;iBAC1C,CAAA;YACH,CAAC;YACD,QAAQ,EAAE;gBACR,WAAW,EAAE,QAAQ,CAAC,mBAAmB;gBACzC,SAAS,EAAE,QAAQ,CAAC,iBAAgD;aACrE;YACD,wBAAwB,EAAE,QAAQ,CAAC,wBAAwB;SAC5D,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,SAAS,CACb,EAAM,EACN,WAAmB,EACnB,QAAgB,EAChB,IAAY,EACZ,QAAgB,EAChB,QAA0B;QAE1B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACpC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;QAErC,MAAM,IAAI,GAAG,MAAM,EAAE;aAClB,MAAM,EAAE;aACR,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC9B,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EACjD,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAChC,CACF;aACA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;QAE3B,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,IAAI,CAAC,CAAA;QAC7E,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;YAC5F,WAAW,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;YAChD,cAAc,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACvD,kBAAkB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC;SAClD,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;QAClC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAA;IACtE,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,MAAM,CACV,EAAM,EACN,WAAmB,EACnB,KAgBC;QAED,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAA;QAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACjF,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAEzE,8FAA8F;QAC9F,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAErG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;aACnB,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC;YACN,EAAE,EAAE,MAAM,EAAE;YACZ,WAAW;YACX,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,gBAAgB,EAAE,QAAQ;YAC1B,MAAM;YACN,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;YAChC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,IAAI;YACtB,KAAK;YACL,cAAc,EAAE,KAAK,CAAC,cAAc,IAAI,IAAI;YAC5C,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;SACzB,CAAC;aACD,SAAS,EAAE,CAAA;QACd,OAAO,GAAI,CAAA;IACb,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,SAAS,CAAC,EAAM,EAAE,WAAmB,EAAE,QAAgB,EAAE,YAAoB;QACjF,OAAO,EAAE;aACN,MAAM,EAAE;aACR,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC9B,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,EACtC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAChC,CACF;aACA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;IAC7B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAChB,EAAM,EACN,WAAmB,EACnB,QAAgB,EAChB,YAAoB,EACpB,QAAgB,EAChB,QAA0B;QAE1B,MAAM,GAAG,GAAG,GAAG,CACb,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,EAC3C,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACrC,EAAE,CAAC,cAAc,CAAC,YAAY,EAAE,YAAY,CAAC,CAC9C,CAAA;QACD,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,CAAC;aACzC,IAAI,CAAC,cAAc,CAAC;aACpB,KAAK,CAAC,GAAG,CAAC;aACV,KAAK,CAAC,CAAC,CAAC,CAAA;QAEX,gGAAgG;QAChG,2FAA2F;QAC3F,8FAA8F;QAC9F,qFAAqF;QACrF,gGAAgG;QAChG,6EAA6E;QAC7E,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;QAE/F,0FAA0F;QAC1F,6FAA6F;QAC7F,6FAA6F;QAC7F,+FAA+F;QAC/F,8FAA8F;QAC9F,4FAA4F;QAC5F,8DAA8D;QAC9D,EAAE;QACF,gGAAgG;QAChG,6FAA6F;QAC7F,6FAA6F;QAC7F,mEAAmE;QACnE,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,CAAC;YAC/E,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM;gBAAE,MAAM,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAClG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QACzB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;QAC1E,MAAM,WAAW,GAAiB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjD,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE;YAClB,SAAS,EAAE,CAAC,CAAC,SAAoC;SAClD,CAAC,CAAC,CAAA;QAEH,2FAA2F;QAC3F,sFAAsF;QACtF,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;aACvB,MAAM,CAAC,EAAE,SAAS,EAAE,gBAAgB,CAAC,SAAS,EAAE,CAAC;aACjD,IAAI,CAAC,gBAAgB,CAAC;aACtB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,EAC7C,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACvC,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,YAAY,CAAC,EACvC,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,EAClC,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CACxC,CACF;aACA,KAAK,CAAC,CAAC,CAAC,CAAA;QAEX,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;QAC5F,MAAM,QAAQ,GAAG,UAAU,CAAC;YAC1B,YAAY;YACZ,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;YACtC,OAAO,EAAE,WAAW;YACpB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,QAAQ,EAAE,cAAc;YACxB,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,OAAO,IAAI,QAAQ,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAA;QAElF,MAAM,EAAE;aACL,MAAM,CAAC,cAAc,CAAC;aACtB,MAAM,CAAC;YACN,EAAE,EAAE,MAAM,EAAE;YACZ,WAAW;YACX,QAAQ;YACR,YAAY;YACZ,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;YAC3C,aAAa,EAAE,QAAQ,CAAC,aAAa;YACrC,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;YAC3C,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;YAC7C,MAAM;YACN,cAAc,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI;YAC1C,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;YAC7D,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;YAC7D,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC;YAClC,UAAU,EAAE,IAAI,IAAI,EAAE;SACvB,CAAC;aACD,kBAAkB,CAAC;YAClB,MAAM,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,YAAY,CAAC;YAC1F,GAAG,EAAE;gBACH,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;gBAC3C,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,eAAe,EAAE,QAAQ,CAAC,eAAe;gBACzC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;gBAC3C,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;gBAC7C,MAAM;gBACN,cAAc,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI;gBAC1C,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;gBAC7D,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;gBAC7D,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC;gBAClC,UAAU,EAAE,IAAI,IAAI,EAAE;gBACtB,wFAAwF;gBACxF,oFAAoF;gBACpF,sEAAsE;gBACtE,MAAM,EAAE,KAAK;aACd;SACF,CAAC,CAAA;QAEJ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;IAC1B,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,iBAAiB,CAC7B,EAAM,EACN,WAAmB,EACnB,QAAgB,EAChB,YAAoB;QAEpB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,CAAC,CAAA;QACnG,IAAI,CAAC,QAAQ,CAAC,MAAM;YAAE,OAAO,SAAS,CAAA;QACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAA0E,CAAA;QAClG,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,IAAI,IAAI,CAAA;QACnD,OAAO;YACL,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,IAAI,CAAC;YAC9C,UAAU;YACV,qBAAqB,EACnB,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC;SACtG,CAAA;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,qBAAqB,CACjC,EAAM,EACN,WAAmB,EACnB,QAAgB,EAChB,YAAoB;QAEpB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;aACnB,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAQ,gBAAgB,cAAc,CAAC,eAAe,OAAO,EAAE,CAAC;aACrF,IAAI,CAAC,cAAc,CAAC;aACpB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,EAC3C,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACrC,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EACrE,EAAE,CAAC,cAAc,CAAC,YAAY,EAAE,YAAY,CAAC,CAC9C,CACF,CAAA;QACH,OAAO,MAAM,CAAC,GAAG,EAAE,OAAO,IAAI,CAAC,CAAC,CAAA;IAClC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,KAAK,CAAC,aAAa,CACjB,EAAM,EACN,WAAmB,EACnB,MAA0E,EAC1E,MAAe;QAEf,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC;YAC3C,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC;YACjD,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC;SAChD,CAAA;QAED,8FAA8F;QAC9F,6FAA6F;QAC7F,2FAA2F;QAC3F,4BAA4B;QAC5B,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,MAAM,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,MAAM,EAAE;iBACnB,MAAM,CAAC,cAAc,CAAC;iBACtB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;iBACf,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;iBACtB,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE,CAAC,CAAA;YACvC,OAAO,KAAK,CAAC,MAAM,CAAA;QACrB,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,EAAE;aACxB,cAAc,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,QAAQ,EAAE,YAAY,EAAE,cAAc,CAAC,YAAY,EAAE,CAAC;aAChG,IAAI,CAAC,cAAc,CAAC;aACpB,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;QACzB,IAAI,CAAC,UAAU,CAAC,MAAM;YAAE,OAAO,CAAC,CAAA;QAEhC,0FAA0F;QAC1F,qFAAqF;QACrF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAA;QAC5C,KAAK,MAAM,CAAC,IAAI,UAAU;YACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;QACrF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;QACjD,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;YACvF,KAAK,MAAM,EAAE,IAAI,GAAG;gBAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,aAAa,IAAI,IAAI,CAAC,CAAA;QAC9F,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAmB,CAAA;QAC9C,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAAY,EAAE,MAAqB,EAAE,EAAE;YACrE,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,WAAW,IAAI,IAAI,EAAE,CAAA;YAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACjC,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAA;YACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;YAC1E,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;YAC5B,OAAO,MAAM,CAAA;QACf,CAAC,CAAA;QAED,MAAM,IAAI,GAAsD,EAAE,CAAA;QAClE,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC,IAAI,IAAI,CAAA;YACtE,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,KAAK,MAAM,CAAC,aAAa;gBAAE,SAAQ;YACrE,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;gBAAE,SAAQ;YACzE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACd,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,CAAA;QAE1B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAA;QACxC,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;QAE7F,MAAM,IAAI,GAAG,MAAM,EAAE;aAClB,MAAM,CAAC,cAAc,CAAC;aACtB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;aACf,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,EAC3C,EAAE,CACA,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CACrC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CACxF,CACF,CACF,CACF;aACA,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE,CAAC,CAAA;QACvC,OAAO,IAAI,CAAC,MAAM,CAAA;IACpB,CAAC;IAED,yFAAyF;IACzF,KAAK,CAAC,gBAAgB,CACpB,EAAM,EACN,WAAmB,EACnB,QAAgB,EAChB,IAAY,EACZ,EAAU;QAEV,MAAM,IAAI,GAAG,MAAM,EAAE;aAClB,cAAc,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;aACtD,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC9B,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,EAC/B,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAC9B,CACF,CAAA;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAA;IAC/C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CACb,EAAM,EACN,WAAmB,EACnB,OAAe,EACf,MAAc,EACd,aAA4B;QAE5B,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,EAAE;aACR,IAAI,CAAC,OAAO,CAAC;aACb,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;aACzE,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,CAAC,QAAQ;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAChD,IAAI,QAAQ,CAAC,eAAe;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,8BAA8B,CAAC,CAAA;QAEtF,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,EAAE;aAC1B,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC;YACN,EAAE,EAAE,MAAM,EAAE;YACZ,WAAW;YACX,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,SAAS,OAAO,KAAK,MAAM,EAAE;SACpC,CAAC;aACD,SAAS,EAAE,CAAA;QAEd,MAAM,EAAE;aACL,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,EAAE,eAAe,EAAE,UAAW,CAAC,EAAE,EAAE,CAAC;aACxC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAEvF,6FAA6F;QAC7F,0CAA0C;QAC1C,MAAM,EAAE;aACL,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,EAAE,eAAe,EAAE,UAAW,CAAC,EAAE,EAAE,CAAC;aACxC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,UAAW,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAE9F,KAAK,aAAa,CAAA;QAClB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAW,EAAE,CAAA;IAC9C,CAAC;CACF;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,QAA0B;IAC9C,OAAO,GAAG,QAAQ,CAAC,UAAU,IAAI,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAA;AAC3G,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAA"}
|
|
@@ -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
|
|
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;
|