@kernhq/module-hr 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contract/capabilities.d.ts.map +1 -1
- package/dist/contract/capabilities.js +0 -8
- package/dist/contract/capabilities.js.map +1 -1
- package/dist/contract/permissions.d.ts +0 -14
- package/dist/contract/permissions.d.ts.map +1 -1
- package/dist/contract/permissions.js +4 -16
- package/dist/contract/permissions.js.map +1 -1
- package/package.json +1 -1
- package/src/client/capabilities.ts +0 -1
- package/src/client/messages.ts +0 -15
- package/src/client/mock.ts +467 -2
- package/src/client/settings/ApprovalsSettings.svelte +18 -15
- package/src/contract/capabilities.ts +0 -8
- package/src/contract/permissions.ts +4 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,cAAc;;;;;;;;
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,cAAc;;;;;;;;GAiGzB,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAA;AAElE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,WAAmB,CAAA;AAChE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,WAAwB,CAAA;AAE3E;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAmFpE,CAAA"}
|
|
@@ -111,14 +111,6 @@ export const hrCapabilities = defineCapabilities([
|
|
|
111
111
|
defaultEnabled: false,
|
|
112
112
|
level: 1,
|
|
113
113
|
},
|
|
114
|
-
{
|
|
115
|
-
id: 'overtime',
|
|
116
|
-
label: 'Overtime',
|
|
117
|
-
description: 'Detect and approve time worked beyond the schedule',
|
|
118
|
-
dependsOn: ['attendance'],
|
|
119
|
-
defaultEnabled: false,
|
|
120
|
-
level: 2,
|
|
121
|
-
},
|
|
122
114
|
{
|
|
123
115
|
id: 'documents',
|
|
124
116
|
label: 'Employee documents',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,kBAAkB,CAAC;IAC/C;QACE,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,6DAA6D;QAC1E,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,SAAS;QAChB,WAAW,EAAE,+EAA+E;QAC5F,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,iGAAiG;QACjG,+FAA+F;QAC/F,4FAA4F;QAC5F,+FAA+F;QAC/F,+BAA+B;QAC/B,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,mEAAmE;QAChF,iGAAiG;QACjG,4EAA4E;QAC5E,SAAS,EAAE,CAAC,SAAS,CAAC;QACtB,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,wDAAwD;QACrE,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,gGAAgG;QAChG,4CAA4C;QAC5C,cAAc,EAAE,IAAI;QACpB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,OAAO;QACd,WAAW,EAAE,mDAAmD;QAChE,SAAS,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;QAChC,6FAA6F;QAC7F,6EAA6E;QAC7E,cAAc,EAAE,IAAI;QACpB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,SAAS;QAChB,WAAW,EAAE,gEAAgE;QAC7E,SAAS,EAAE,CAAC,OAAO,CAAC;QACpB,8FAA8F;QAC9F,mFAAmF;QACnF,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,4DAA4D;QACzE,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,yEAAyE;QACtF,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,8FAA8F;QAC9F,yEAAyE;QACzE,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,+CAA+C;QAC5D,SAAS,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;QAChC,4FAA4F;QAC5F,yEAAyE;QACzE,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -202,18 +202,6 @@ export declare const hrPermissions: readonly [{
|
|
|
202
202
|
readonly scope: "workspace";
|
|
203
203
|
readonly defaultRoles: ["owner", "admin"];
|
|
204
204
|
readonly dangerous: true;
|
|
205
|
-
}, {
|
|
206
|
-
readonly key: "hr.overtime.view";
|
|
207
|
-
readonly label: "View overtime";
|
|
208
|
-
readonly scope: "workspace";
|
|
209
|
-
readonly defaultRoles: ["owner", "admin"];
|
|
210
|
-
readonly dangerous: false;
|
|
211
|
-
}, {
|
|
212
|
-
readonly key: "hr.overtime.manage";
|
|
213
|
-
readonly label: "Approve and adjust overtime";
|
|
214
|
-
readonly scope: "workspace";
|
|
215
|
-
readonly defaultRoles: ["owner", "admin"];
|
|
216
|
-
readonly dangerous: false;
|
|
217
205
|
}, {
|
|
218
206
|
readonly key: "hr.policy.view";
|
|
219
207
|
readonly label: "View accrual, overtime and rounding policies";
|
|
@@ -286,8 +274,6 @@ export declare const HR_PERMISSIONS: {
|
|
|
286
274
|
readonly attendanceView: "hr.attendance.view";
|
|
287
275
|
readonly attendanceViewTeam: "hr.attendance.view_team";
|
|
288
276
|
readonly attendanceManage: "hr.attendance.manage";
|
|
289
|
-
readonly overtimeView: "hr.overtime.view";
|
|
290
|
-
readonly overtimeManage: "hr.overtime.manage";
|
|
291
277
|
readonly policyView: "hr.policy.view";
|
|
292
278
|
readonly policyManage: "hr.policy.manage";
|
|
293
279
|
readonly periodManage: "hr.period.manage";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/contract/permissions.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/contract/permissions.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmSxB,CAAA;AAEF,+DAA+D;AAC/D,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCjB,CAAA"}
|
|
@@ -249,20 +249,10 @@ export const hrPermissions = definePermissions([
|
|
|
249
249
|
defaultRoles: ['owner', 'admin'],
|
|
250
250
|
dangerous: true,
|
|
251
251
|
},
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
defaultRoles: ['owner', 'admin'],
|
|
257
|
-
dangerous: false,
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
key: 'hr.overtime.manage',
|
|
261
|
-
label: 'Approve and adjust overtime',
|
|
262
|
-
scope: 'workspace',
|
|
263
|
-
defaultRoles: ['owner', 'admin'],
|
|
264
|
-
dangerous: false,
|
|
265
|
-
},
|
|
252
|
+
// No `hr.overtime.*` here. Overtime is detected, stored and shown as part of attendance, and
|
|
253
|
+
// nothing asks a question these keys could answer — a role checkbox that gates nothing teaches an
|
|
254
|
+
// administrator the same lesson a dead capability switch does. They come back with the approval
|
|
255
|
+
// flow that needs them.
|
|
266
256
|
// ---------------------------------------------------------------- policies and periods
|
|
267
257
|
{
|
|
268
258
|
key: 'hr.policy.view',
|
|
@@ -344,8 +334,6 @@ export const HR_PERMISSIONS = {
|
|
|
344
334
|
attendanceView: 'hr.attendance.view',
|
|
345
335
|
attendanceViewTeam: 'hr.attendance.view_team',
|
|
346
336
|
attendanceManage: 'hr.attendance.manage',
|
|
347
|
-
overtimeView: 'hr.overtime.view',
|
|
348
|
-
overtimeManage: 'hr.overtime.manage',
|
|
349
337
|
policyView: 'hr.policy.view',
|
|
350
338
|
policyManage: 'hr.policy.manage',
|
|
351
339
|
periodManage: 'hr.period.manage',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/contract/permissions.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/contract/permissions.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/client/messages.ts
CHANGED
|
@@ -469,8 +469,6 @@ export const en: Record<string, Message> = {
|
|
|
469
469
|
'hr.cap_legal_entities_desc': 'Several employing companies, for a group operating across borders',
|
|
470
470
|
'hr.cap_offices': 'Offices',
|
|
471
471
|
'hr.cap_offices_desc': 'More than one place of work, each with its own country, timezone and holidays',
|
|
472
|
-
'hr.cap_overtime': 'Overtime',
|
|
473
|
-
'hr.cap_overtime_desc': 'Detect and approve time worked beyond the schedule',
|
|
474
472
|
'hr.cap_periods': 'Payroll periods',
|
|
475
473
|
'hr.cap_periods_desc': 'Close a month so a filed payroll cannot move underneath it',
|
|
476
474
|
'hr.capabilities_desc':
|
|
@@ -549,7 +547,6 @@ export const en: Record<string, Message> = {
|
|
|
549
547
|
'hr.chain_perm_attendance': 'Manage attendance',
|
|
550
548
|
'hr.chain_perm_leave': 'Manage time off',
|
|
551
549
|
'hr.chain_perm_office': 'Manage offices',
|
|
552
|
-
'hr.chain_perm_overtime': 'Manage overtime',
|
|
553
550
|
'hr.chain_perm_person': 'Manage people',
|
|
554
551
|
'hr.chain_remove_approver': 'Remove this approver',
|
|
555
552
|
'hr.chain_remove_step': 'Remove this step',
|
|
@@ -1857,8 +1854,6 @@ export const ar: Record<string, Message> = {
|
|
|
1857
1854
|
'hr.cap_legal_entities_desc': 'عدة شركات موظِّفة، لمجموعة تعمل عبر الحدود',
|
|
1858
1855
|
'hr.cap_offices': 'المكاتب',
|
|
1859
1856
|
'hr.cap_offices_desc': 'أكثر من مكان عمل، لكلٍّ منه بلده ومنطقته الزمنية وعطلاته',
|
|
1860
|
-
'hr.cap_overtime': 'العمل الإضافي',
|
|
1861
|
-
'hr.cap_overtime_desc': 'رصد العمل خارج المناوبة والموافقة عليه',
|
|
1862
1857
|
'hr.cap_periods': 'فترات الرواتب',
|
|
1863
1858
|
'hr.cap_periods_desc': 'إغلاق الشهر حتى لا يتغيّر كشف رواتب مُعتمد بعد اعتماده',
|
|
1864
1859
|
'hr.capabilities_desc':
|
|
@@ -1933,7 +1928,6 @@ export const ar: Record<string, Message> = {
|
|
|
1933
1928
|
'hr.chain_perm_attendance': 'إدارة الحضور',
|
|
1934
1929
|
'hr.chain_perm_leave': 'إدارة الإجازات',
|
|
1935
1930
|
'hr.chain_perm_office': 'إدارة المكاتب',
|
|
1936
|
-
'hr.chain_perm_overtime': 'إدارة العمل الإضافي',
|
|
1937
1931
|
'hr.chain_perm_person': 'إدارة الأفراد',
|
|
1938
1932
|
'hr.chain_remove_approver': 'إزالة هذا الموقّع',
|
|
1939
1933
|
'hr.chain_remove_step': 'إزالة هذه الخطوة',
|
|
@@ -3271,8 +3265,6 @@ export const de: Record<string, Message> = {
|
|
|
3271
3265
|
'hr.cap_offices': 'Standorte',
|
|
3272
3266
|
'hr.cap_offices_desc':
|
|
3273
3267
|
'Mehr als ein Arbeitsort, jeder mit eigenem Land, eigener Zeitzone und eigenen Feiertagen',
|
|
3274
|
-
'hr.cap_overtime': 'Überstunden',
|
|
3275
|
-
'hr.cap_overtime_desc': 'Über die Arbeitszeit hinaus geleistete Zeit erkennen und freigeben',
|
|
3276
3268
|
'hr.cap_periods': 'Abrechnungszeiträume',
|
|
3277
3269
|
'hr.cap_periods_desc':
|
|
3278
3270
|
'Einen Monat schließen, damit eine eingereichte Abrechnung sich nicht nachträglich verschiebt',
|
|
@@ -3355,7 +3347,6 @@ export const de: Record<string, Message> = {
|
|
|
3355
3347
|
'hr.chain_perm_attendance': 'Zeiterfassung verwalten',
|
|
3356
3348
|
'hr.chain_perm_leave': 'Abwesenheit verwalten',
|
|
3357
3349
|
'hr.chain_perm_office': 'Standorte verwalten',
|
|
3358
|
-
'hr.chain_perm_overtime': 'Überstunden verwalten',
|
|
3359
3350
|
'hr.chain_perm_person': 'Personen verwalten',
|
|
3360
3351
|
'hr.chain_remove_approver': 'Diese freigebende Person entfernen',
|
|
3361
3352
|
'hr.chain_remove_step': 'Diesen Schritt entfernen',
|
|
@@ -4607,8 +4598,6 @@ export const fa: Record<string, Message> = {
|
|
|
4607
4598
|
'hr.cap_legal_entities_desc': 'چند شرکت کارفرما، برای گروهی که در چند کشور فعالیت میکند',
|
|
4608
4599
|
'hr.cap_offices': 'دفاتر',
|
|
4609
4600
|
'hr.cap_offices_desc': 'بیش از یک محل کار، هرکدام با کشور، منطقهٔ زمانی و تعطیلات خودش',
|
|
4610
|
-
'hr.cap_overtime': 'اضافهکاری',
|
|
4611
|
-
'hr.cap_overtime_desc': 'تشخیص و تأیید کارکرد بیش از شیفت',
|
|
4612
4601
|
'hr.cap_periods': 'دورههای حقوق و دستمزد',
|
|
4613
4602
|
'hr.cap_periods_desc': 'بستن یک ماه تا حقوق ثبتشده دیگر تغییر نکند',
|
|
4614
4603
|
'hr.capabilities_desc':
|
|
@@ -4687,7 +4676,6 @@ export const fa: Record<string, Message> = {
|
|
|
4687
4676
|
'hr.chain_perm_attendance': 'مدیریت حضور',
|
|
4688
4677
|
'hr.chain_perm_leave': 'مدیریت مرخصی',
|
|
4689
4678
|
'hr.chain_perm_office': 'مدیریت دفترها',
|
|
4690
|
-
'hr.chain_perm_overtime': 'مدیریت اضافهکار',
|
|
4691
4679
|
'hr.chain_perm_person': 'مدیریت افراد',
|
|
4692
4680
|
'hr.chain_remove_approver': 'برداشتن این تأییدکننده',
|
|
4693
4681
|
'hr.chain_remove_step': 'برداشتن این مرحله',
|
|
@@ -5911,8 +5899,6 @@ export const tr: Record<string, Message> = {
|
|
|
5911
5899
|
'hr.cap_legal_entities_desc': 'Sınır ötesinde faaliyet gösteren bir grup için birden fazla işveren şirket',
|
|
5912
5900
|
'hr.cap_offices': 'Ofisler',
|
|
5913
5901
|
'hr.cap_offices_desc': 'Birden fazla çalışma yeri; her biri kendi ülkesi, saat dilimi ve tatilleriyle',
|
|
5914
|
-
'hr.cap_overtime': 'Fazla mesai',
|
|
5915
|
-
'hr.cap_overtime_desc': 'Vardiyanın ötesinde çalışılan süreyi bulun ve onaylayın',
|
|
5916
5902
|
'hr.cap_periods': 'Bordro dönemleri',
|
|
5917
5903
|
'hr.cap_periods_desc': 'Bir ayı kapatın; böylece verilmiş bordro sonradan kaymaz',
|
|
5918
5904
|
'hr.capabilities_desc':
|
|
@@ -5990,7 +5976,6 @@ export const tr: Record<string, Message> = {
|
|
|
5990
5976
|
'hr.chain_perm_attendance': 'Devamı yönetme',
|
|
5991
5977
|
'hr.chain_perm_leave': 'İzinleri yönetme',
|
|
5992
5978
|
'hr.chain_perm_office': 'Ofisleri yönetme',
|
|
5993
|
-
'hr.chain_perm_overtime': 'Fazla mesaiyi yönetme',
|
|
5994
5979
|
'hr.chain_perm_person': 'Personeli yönetme',
|
|
5995
5980
|
'hr.chain_remove_approver': 'Bu onaylayanı kaldır',
|
|
5996
5981
|
'hr.chain_remove_step': 'Bu adımı kaldır',
|
package/src/client/mock.ts
CHANGED
|
@@ -32,7 +32,7 @@ import type {
|
|
|
32
32
|
ResolvedCalendarDay,
|
|
33
33
|
WorkingWeek,
|
|
34
34
|
} from '../contract/models.js'
|
|
35
|
-
import type { Period } from '../contract/policies.js'
|
|
35
|
+
import type { Period, Policy, PolicyAssignment, PolicySubjectKind } from '../contract/policies.js'
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* A refusal the client cannot tell from the server's.
|
|
@@ -254,6 +254,7 @@ export function createMockHrApi() {
|
|
|
254
254
|
{
|
|
255
255
|
id: id('d001'),
|
|
256
256
|
displayName: 'Ayşe Yılmaz',
|
|
257
|
+
hiredOn: day(-400),
|
|
257
258
|
workEmail: 'ayse@example.test',
|
|
258
259
|
status: 'active',
|
|
259
260
|
timezone: 'Europe/Istanbul',
|
|
@@ -262,6 +263,7 @@ export function createMockHrApi() {
|
|
|
262
263
|
{
|
|
263
264
|
id: id('d002'),
|
|
264
265
|
displayName: 'Sanne de Vries',
|
|
266
|
+
hiredOn: day(-300),
|
|
265
267
|
workEmail: 'sanne@example.test',
|
|
266
268
|
status: 'active',
|
|
267
269
|
timezone: 'Europe/Amsterdam',
|
|
@@ -270,6 +272,7 @@ export function createMockHrApi() {
|
|
|
270
272
|
{
|
|
271
273
|
id: id('d003'),
|
|
272
274
|
displayName: 'Mehmet Kaya',
|
|
275
|
+
hiredOn: day(-2000),
|
|
273
276
|
workEmail: 'mehmet@example.test',
|
|
274
277
|
status: 'on_leave',
|
|
275
278
|
timezone: 'Europe/Istanbul',
|
|
@@ -278,6 +281,7 @@ export function createMockHrApi() {
|
|
|
278
281
|
{
|
|
279
282
|
id: id('d004'),
|
|
280
283
|
displayName: 'Jonas Weber',
|
|
284
|
+
hiredOn: day(-80),
|
|
281
285
|
workEmail: 'jonas@example.test',
|
|
282
286
|
status: 'active',
|
|
283
287
|
timezone: 'Europe/Berlin',
|
|
@@ -369,7 +373,6 @@ export function createMockHrApi() {
|
|
|
369
373
|
personalEmail: null,
|
|
370
374
|
phone: null,
|
|
371
375
|
photoFileId: null,
|
|
372
|
-
hiredOn: day(-400),
|
|
373
376
|
terminatedOn: null,
|
|
374
377
|
custom: {},
|
|
375
378
|
createdAt: iso(400 * 86_400_000),
|
|
@@ -1149,6 +1152,270 @@ export function createMockHrApi() {
|
|
|
1149
1152
|
return weekday !== 'sat' && weekday !== 'sun' && date <= day(0)
|
|
1150
1153
|
}).length
|
|
1151
1154
|
|
|
1155
|
+
// ---------------------------------------------------------------- accrual policies
|
|
1156
|
+
|
|
1157
|
+
/** The ladder made explicit, straight from `SUBJECT_PRIORITY` in the contract. */
|
|
1158
|
+
const PRIORITY: Record<PolicySubjectKind, number> = {
|
|
1159
|
+
person: 100,
|
|
1160
|
+
office: 80,
|
|
1161
|
+
legal_entity: 60,
|
|
1162
|
+
org_unit: 40,
|
|
1163
|
+
position: 30,
|
|
1164
|
+
workspace: 0,
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* Two policies that differ in more than their name.
|
|
1169
|
+
*
|
|
1170
|
+
* A list whose column reads the same sentence twice demonstrates nothing — these take different
|
|
1171
|
+
* branches of the evaluator: one accrues monthly with a waiting period for joiners, the other on
|
|
1172
|
+
* the employee's own anniversary with seniority tiers.
|
|
1173
|
+
*/
|
|
1174
|
+
const policies: Row<Policy>[] = [
|
|
1175
|
+
{
|
|
1176
|
+
id: id('b011'),
|
|
1177
|
+
kind: 'accrual',
|
|
1178
|
+
name: 'Monthly accrual',
|
|
1179
|
+
config: {
|
|
1180
|
+
frequency: 'monthly',
|
|
1181
|
+
daysPerYear: 20,
|
|
1182
|
+
minutesPerDay: 480,
|
|
1183
|
+
seniorityTiers: [],
|
|
1184
|
+
waitingPeriodMonths: 3,
|
|
1185
|
+
calendar: 'gregorian',
|
|
1186
|
+
roundToMinutes: 30,
|
|
1187
|
+
leaveTypeKey: 'annual',
|
|
1188
|
+
},
|
|
1189
|
+
effectiveFrom: `${YEAR}-01-01`,
|
|
1190
|
+
effectiveTo: null,
|
|
1191
|
+
source: 'custom',
|
|
1192
|
+
packKey: null,
|
|
1193
|
+
configHash: 'a1b2c3d4',
|
|
1194
|
+
archivedAt: null,
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
id: id('b012'),
|
|
1198
|
+
kind: 'accrual',
|
|
1199
|
+
name: 'Anniversary accrual, with seniority',
|
|
1200
|
+
config: {
|
|
1201
|
+
frequency: 'anniversary',
|
|
1202
|
+
daysPerYear: 22,
|
|
1203
|
+
minutesPerDay: 480,
|
|
1204
|
+
seniorityTiers: [
|
|
1205
|
+
{ afterYears: 5, daysPerYear: 26 },
|
|
1206
|
+
{ afterYears: 10, daysPerYear: 30 },
|
|
1207
|
+
],
|
|
1208
|
+
waitingPeriodMonths: 0,
|
|
1209
|
+
calendar: 'gregorian',
|
|
1210
|
+
roundToMinutes: 0,
|
|
1211
|
+
leaveTypeKey: 'annual',
|
|
1212
|
+
},
|
|
1213
|
+
effectiveFrom: `${YEAR}-01-01`,
|
|
1214
|
+
effectiveTo: null,
|
|
1215
|
+
source: 'custom',
|
|
1216
|
+
packKey: null,
|
|
1217
|
+
configHash: 'e5f6a7b8',
|
|
1218
|
+
archivedAt: null,
|
|
1219
|
+
},
|
|
1220
|
+
]
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Two rungs, on purpose.
|
|
1224
|
+
*
|
|
1225
|
+
* The screen's copy says the nearest subject wins; with everything assigned at one rung nothing on
|
|
1226
|
+
* screen tests that claim. The workspace-wide monthly policy is what most people get, and Sanne
|
|
1227
|
+
* has the anniversary one at the `person` rung — which must visibly beat the office below it.
|
|
1228
|
+
*/
|
|
1229
|
+
const policyAssignments: Row<PolicyAssignment>[] = [
|
|
1230
|
+
{
|
|
1231
|
+
id: id('b0a1'),
|
|
1232
|
+
policyId: id('b011'),
|
|
1233
|
+
subjectKind: 'workspace',
|
|
1234
|
+
subjectId: null,
|
|
1235
|
+
effectiveFrom: `${YEAR}-01-01`,
|
|
1236
|
+
effectiveTo: null,
|
|
1237
|
+
priority: PRIORITY.workspace,
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
id: id('b0a2'),
|
|
1241
|
+
policyId: id('b012'),
|
|
1242
|
+
subjectKind: 'office',
|
|
1243
|
+
subjectId: id('e002'),
|
|
1244
|
+
effectiveFrom: `${YEAR}-01-01`,
|
|
1245
|
+
effectiveTo: null,
|
|
1246
|
+
priority: PRIORITY.office,
|
|
1247
|
+
},
|
|
1248
|
+
// Mehmet has been here five years, so the tier above `afterYears: 5` is the one that answers
|
|
1249
|
+
// for him — without somebody long-serving the seniority branch of the evaluator never fires and
|
|
1250
|
+
// the second policy's whole reason for existing goes untested.
|
|
1251
|
+
{
|
|
1252
|
+
id: id('b0a4'),
|
|
1253
|
+
policyId: id('b012'),
|
|
1254
|
+
subjectKind: 'person',
|
|
1255
|
+
subjectId: people[2]!.id,
|
|
1256
|
+
effectiveFrom: `${YEAR}-01-01`,
|
|
1257
|
+
effectiveTo: null,
|
|
1258
|
+
priority: PRIORITY.person,
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
id: id('b0a3'),
|
|
1262
|
+
policyId: id('b012'),
|
|
1263
|
+
subjectKind: 'person',
|
|
1264
|
+
subjectId: people[1]!.id,
|
|
1265
|
+
effectiveFrom: `${YEAR}-01-01`,
|
|
1266
|
+
effectiveTo: null,
|
|
1267
|
+
priority: PRIORITY.person,
|
|
1268
|
+
},
|
|
1269
|
+
]
|
|
1270
|
+
|
|
1271
|
+
const assignmentsOf = (policyId: string) => policyAssignments.filter((a) => a.policyId === policyId)
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* Which policy applies to somebody, and which rung answered.
|
|
1275
|
+
*
|
|
1276
|
+
* Nearest wins, by the priority the contract publishes — so a policy given to one person beats the
|
|
1277
|
+
* one on their office, which beats their legal entity, their department, their position, and
|
|
1278
|
+
* finally the whole workspace. This is the claim the screen's copy makes, so it has to be the
|
|
1279
|
+
* claim the fixture keeps.
|
|
1280
|
+
*/
|
|
1281
|
+
function resolvePolicyFor(personId: string) {
|
|
1282
|
+
const officeId = primaryOfficeId(personId)
|
|
1283
|
+
const job = employments.find((e) => e.personId === personId && e.effectiveTo === null)
|
|
1284
|
+
const matches = (a: Row<PolicyAssignment>) => {
|
|
1285
|
+
switch (a.subjectKind) {
|
|
1286
|
+
case 'person':
|
|
1287
|
+
return a.subjectId === personId
|
|
1288
|
+
case 'office':
|
|
1289
|
+
return a.subjectId === officeId
|
|
1290
|
+
case 'legal_entity':
|
|
1291
|
+
return a.subjectId === job?.legalEntityId
|
|
1292
|
+
case 'org_unit':
|
|
1293
|
+
return a.subjectId === job?.orgUnitId
|
|
1294
|
+
case 'position':
|
|
1295
|
+
return a.subjectId === job?.positionId
|
|
1296
|
+
default:
|
|
1297
|
+
return true
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
const best = policyAssignments
|
|
1301
|
+
.filter((a) => {
|
|
1302
|
+
if (a.effectiveTo !== null) return false
|
|
1303
|
+
const policy = policies.find((x) => x.id === a.policyId)
|
|
1304
|
+
return Boolean(policy && policy.archivedAt === null) && matches(a)
|
|
1305
|
+
})
|
|
1306
|
+
.sort((a, b) => b.priority - a.priority)[0]
|
|
1307
|
+
const policy = best ? policies.find((x) => x.id === best.policyId) : undefined
|
|
1308
|
+
return best && policy ? { assignment: best, policy } : null
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
const wholeMonthsBetween = (from: string, to: string) => {
|
|
1312
|
+
const a = new Date(`${from}T00:00:00Z`)
|
|
1313
|
+
const b = new Date(`${to}T00:00:00Z`)
|
|
1314
|
+
let months = (b.getUTCFullYear() - a.getUTCFullYear()) * 12 + (b.getUTCMonth() - a.getUTCMonth())
|
|
1315
|
+
if (b.getUTCDate() < a.getUTCDate()) months -= 1
|
|
1316
|
+
return months
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
/**
|
|
1320
|
+
* What a run would credit — computed, never written.
|
|
1321
|
+
*
|
|
1322
|
+
* `preview` and `run` share this function for the reason the contract gives: a preview computed
|
|
1323
|
+
* differently from the thing it previews is a preview that eventually lies. Only `run` writes,
|
|
1324
|
+
* and it writes from these rows.
|
|
1325
|
+
*/
|
|
1326
|
+
function accrualRows(from: string, to: string, onlyPersonId?: string) {
|
|
1327
|
+
const rows: Array<{
|
|
1328
|
+
personId: string
|
|
1329
|
+
displayName: string
|
|
1330
|
+
leaveTypeId: string
|
|
1331
|
+
leaveTypeName: string
|
|
1332
|
+
minutes: number
|
|
1333
|
+
days: number
|
|
1334
|
+
reason: string
|
|
1335
|
+
alreadyAccrued: boolean
|
|
1336
|
+
}> = []
|
|
1337
|
+
const skipped: Array<{ personId: string; displayName: string; reason: string }> = []
|
|
1338
|
+
|
|
1339
|
+
for (const who of people) {
|
|
1340
|
+
if (onlyPersonId && who.id !== onlyPersonId) continue
|
|
1341
|
+
const skip = (reason: string) =>
|
|
1342
|
+
skipped.push({ personId: who.id, displayName: who.displayName, reason })
|
|
1343
|
+
|
|
1344
|
+
if (who.status === 'terminated') {
|
|
1345
|
+
skip('No longer employed')
|
|
1346
|
+
continue
|
|
1347
|
+
}
|
|
1348
|
+
const applicable = resolvePolicyFor(who.id)
|
|
1349
|
+
if (!applicable) {
|
|
1350
|
+
skip('No accrual policy applies')
|
|
1351
|
+
continue
|
|
1352
|
+
}
|
|
1353
|
+
const config = applicable.policy.config as {
|
|
1354
|
+
frequency: string
|
|
1355
|
+
daysPerYear: number
|
|
1356
|
+
minutesPerDay: number
|
|
1357
|
+
seniorityTiers: Array<{ afterYears: number; daysPerYear: number }>
|
|
1358
|
+
waitingPeriodMonths: number
|
|
1359
|
+
roundToMinutes: number
|
|
1360
|
+
leaveTypeKey: string
|
|
1361
|
+
}
|
|
1362
|
+
const served = wholeMonthsBetween(who.hiredOn, from)
|
|
1363
|
+
if (served < config.waitingPeriodMonths) {
|
|
1364
|
+
skip(`Within the ${config.waitingPeriodMonths}-month waiting period — ${served} served`)
|
|
1365
|
+
continue
|
|
1366
|
+
}
|
|
1367
|
+
const leaveType = leaveTypes.find((lt) => lt.key === config.leaveTypeKey && lt.archivedAt === null)
|
|
1368
|
+
if (!leaveType) {
|
|
1369
|
+
skip(`No leave type keyed "${config.leaveTypeKey}"`)
|
|
1370
|
+
continue
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
// Most senior tier reached wins, whatever order they are written in.
|
|
1374
|
+
const years = Math.floor(served / 12)
|
|
1375
|
+
const tier = [...(config.seniorityTiers ?? [])]
|
|
1376
|
+
.filter((t) => years >= t.afterYears)
|
|
1377
|
+
.sort((a, b) => b.afterYears - a.afterYears)[0]
|
|
1378
|
+
const perYear = tier?.daysPerYear ?? config.daysPerYear
|
|
1379
|
+
|
|
1380
|
+
let minutes = Math.round((perYear * config.minutesPerDay) / 12)
|
|
1381
|
+
if (config.roundToMinutes > 0) {
|
|
1382
|
+
minutes = Math.round(minutes / config.roundToMinutes) * config.roundToMinutes
|
|
1383
|
+
}
|
|
1384
|
+
const alreadyAccrued = ledger.some(
|
|
1385
|
+
(e) =>
|
|
1386
|
+
e.personId === who.id &&
|
|
1387
|
+
e.leaveTypeId === leaveType.id &&
|
|
1388
|
+
e.kind === 'accrual' &&
|
|
1389
|
+
e.effectiveOn >= from &&
|
|
1390
|
+
e.effectiveOn <= to,
|
|
1391
|
+
)
|
|
1392
|
+
const basis = tier
|
|
1393
|
+
? `${perYear} days a year after ${tier.afterYears} years' service`
|
|
1394
|
+
: `${perYear} days a year`
|
|
1395
|
+
rows.push({
|
|
1396
|
+
personId: who.id,
|
|
1397
|
+
displayName: who.displayName,
|
|
1398
|
+
leaveTypeId: leaveType.id,
|
|
1399
|
+
leaveTypeName: leaveType.name,
|
|
1400
|
+
minutes,
|
|
1401
|
+
days: Math.round((minutes / config.minutesPerDay) * 100) / 100,
|
|
1402
|
+
reason: alreadyAccrued
|
|
1403
|
+
? `${basis}, ${config.frequency} — already credited for this period`
|
|
1404
|
+
: `${basis}, ${config.frequency}`,
|
|
1405
|
+
alreadyAccrued,
|
|
1406
|
+
})
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
return {
|
|
1410
|
+
periodFrom: from,
|
|
1411
|
+
periodTo: to,
|
|
1412
|
+
rows,
|
|
1413
|
+
// What the run would actually add: a row already credited contributes nothing to it.
|
|
1414
|
+
totalMinutes: rows.filter((r) => !r.alreadyAccrued).reduce((sum, r) => sum + r.minutes, 0),
|
|
1415
|
+
skipped,
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1152
1419
|
// ---------------------------------------------------------------- approval chains
|
|
1153
1420
|
|
|
1154
1421
|
const chains: Row<ApprovalChain>[] = [
|
|
@@ -1477,6 +1744,7 @@ export function createMockHrApi() {
|
|
|
1477
1744
|
workEmail: input.workEmail ?? '',
|
|
1478
1745
|
status: 'active' as const,
|
|
1479
1746
|
timezone: 'Europe/Istanbul',
|
|
1747
|
+
hiredOn: input.hiredOn ?? day(0),
|
|
1480
1748
|
employeeNo: input.employeeNo ?? `E-${people.length + 1}`,
|
|
1481
1749
|
}
|
|
1482
1750
|
people.push(added)
|
|
@@ -3037,6 +3305,203 @@ export function createMockHrApi() {
|
|
|
3037
3305
|
},
|
|
3038
3306
|
},
|
|
3039
3307
|
|
|
3308
|
+
policies: {
|
|
3309
|
+
list: async ({
|
|
3310
|
+
workspaceId,
|
|
3311
|
+
kind,
|
|
3312
|
+
includeArchived = false,
|
|
3313
|
+
}: {
|
|
3314
|
+
workspaceId: string
|
|
3315
|
+
kind?: string
|
|
3316
|
+
includeArchived?: boolean
|
|
3317
|
+
}) =>
|
|
3318
|
+
policies
|
|
3319
|
+
.filter((row) => (!kind || row.kind === kind) && (includeArchived || row.archivedAt === null))
|
|
3320
|
+
.map((row) => ({
|
|
3321
|
+
...row,
|
|
3322
|
+
workspaceId,
|
|
3323
|
+
assignments: assignmentsOf(row.id).map((a) => ({ ...a, workspaceId })),
|
|
3324
|
+
})),
|
|
3325
|
+
|
|
3326
|
+
get: async ({ workspaceId, policyId }: { workspaceId: string; policyId: string }) => {
|
|
3327
|
+
const found = policies.find((row) => row.id === policyId)
|
|
3328
|
+
if (!found) refuse('NOT_FOUND', 'Policy not found')
|
|
3329
|
+
return {
|
|
3330
|
+
...found,
|
|
3331
|
+
workspaceId,
|
|
3332
|
+
assignments: assignmentsOf(found.id).map((a) => ({ ...a, workspaceId })),
|
|
3333
|
+
}
|
|
3334
|
+
},
|
|
3335
|
+
|
|
3336
|
+
create: async (input: {
|
|
3337
|
+
workspaceId: string
|
|
3338
|
+
kind: Policy['kind']
|
|
3339
|
+
name: string
|
|
3340
|
+
config: Record<string, unknown>
|
|
3341
|
+
effectiveFrom: string
|
|
3342
|
+
effectiveTo?: string | null
|
|
3343
|
+
}) => {
|
|
3344
|
+
const created: Row<Policy> = {
|
|
3345
|
+
id: crypto.randomUUID(),
|
|
3346
|
+
kind: input.kind,
|
|
3347
|
+
name: input.name,
|
|
3348
|
+
config: clone(input.config),
|
|
3349
|
+
effectiveFrom: input.effectiveFrom,
|
|
3350
|
+
effectiveTo: input.effectiveTo ?? null,
|
|
3351
|
+
source: 'custom',
|
|
3352
|
+
packKey: null,
|
|
3353
|
+
// A hash of the config, because that is what a derived row records — a literal would make
|
|
3354
|
+
// every policy look identical to a recomputation deciding whether a figure is stale.
|
|
3355
|
+
configHash: Math.abs(
|
|
3356
|
+
[...JSON.stringify(input.config)].reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 7),
|
|
3357
|
+
)
|
|
3358
|
+
.toString(16)
|
|
3359
|
+
.padStart(8, '0'),
|
|
3360
|
+
archivedAt: null,
|
|
3361
|
+
}
|
|
3362
|
+
policies.push(created)
|
|
3363
|
+
return { ...created, workspaceId: input.workspaceId }
|
|
3364
|
+
},
|
|
3365
|
+
|
|
3366
|
+
update: async (input: {
|
|
3367
|
+
workspaceId: string
|
|
3368
|
+
policyId: string
|
|
3369
|
+
name?: string
|
|
3370
|
+
config?: Record<string, unknown>
|
|
3371
|
+
effectiveTo?: string | null
|
|
3372
|
+
}) => {
|
|
3373
|
+
const found = policies.find((row) => row.id === input.policyId)
|
|
3374
|
+
if (!found) refuse('NOT_FOUND', 'Policy not found')
|
|
3375
|
+
if (input.name !== undefined) found.name = input.name
|
|
3376
|
+
if (input.config !== undefined) found.config = clone(input.config)
|
|
3377
|
+
if (input.effectiveTo !== undefined) found.effectiveTo = input.effectiveTo
|
|
3378
|
+
return { ...found, workspaceId: input.workspaceId }
|
|
3379
|
+
},
|
|
3380
|
+
|
|
3381
|
+
/**
|
|
3382
|
+
* Archived, never deleted, and **the assignments are left where they are**.
|
|
3383
|
+
*
|
|
3384
|
+
* The router neither refuses nor cascades — a ledger entry names the policy that produced it,
|
|
3385
|
+
* so a movement whose policy had vanished would be a number nobody can explain. That means an
|
|
3386
|
+
* archived policy with live assignments is a state an administrator genuinely reaches, and the
|
|
3387
|
+
* fixture can reach it too rather than only in theory.
|
|
3388
|
+
*/
|
|
3389
|
+
archive: async ({ policyId }: { workspaceId: string; policyId: string }) => {
|
|
3390
|
+
const found = policies.find((row) => row.id === policyId)
|
|
3391
|
+
if (!found) refuse('NOT_FOUND', 'Policy not found')
|
|
3392
|
+
found.archivedAt = iso()
|
|
3393
|
+
return { ok: true as const }
|
|
3394
|
+
},
|
|
3395
|
+
|
|
3396
|
+
assign: async (input: {
|
|
3397
|
+
workspaceId: string
|
|
3398
|
+
policyId: string
|
|
3399
|
+
subjectKind: PolicySubjectKind
|
|
3400
|
+
subjectId?: string | null
|
|
3401
|
+
effectiveFrom: string
|
|
3402
|
+
effectiveTo?: string | null
|
|
3403
|
+
}) => {
|
|
3404
|
+
const created: Row<PolicyAssignment> = {
|
|
3405
|
+
id: crypto.randomUUID(),
|
|
3406
|
+
policyId: input.policyId,
|
|
3407
|
+
subjectKind: input.subjectKind,
|
|
3408
|
+
// `workspace` needs no id, and storing one would make the rung look narrower than it is.
|
|
3409
|
+
subjectId: input.subjectKind === 'workspace' ? null : (input.subjectId ?? null),
|
|
3410
|
+
effectiveFrom: input.effectiveFrom,
|
|
3411
|
+
effectiveTo: input.effectiveTo ?? null,
|
|
3412
|
+
priority: PRIORITY[input.subjectKind],
|
|
3413
|
+
}
|
|
3414
|
+
policyAssignments.push(created)
|
|
3415
|
+
return { ...created, workspaceId: input.workspaceId }
|
|
3416
|
+
},
|
|
3417
|
+
|
|
3418
|
+
unassign: async ({ assignmentId }: { workspaceId: string; assignmentId: string }) => {
|
|
3419
|
+
const at = policyAssignments.findIndex((a) => a.id === assignmentId)
|
|
3420
|
+
if (at < 0) refuse('NOT_FOUND', 'Policy assignment not found')
|
|
3421
|
+
policyAssignments.splice(at, 1)
|
|
3422
|
+
return { ok: true as const }
|
|
3423
|
+
},
|
|
3424
|
+
|
|
3425
|
+
resolveFor: async ({ workspaceId, personId }: { workspaceId: string; personId: string }) => {
|
|
3426
|
+
const applicable = resolvePolicyFor(personId)
|
|
3427
|
+
void workspaceId
|
|
3428
|
+
return applicable
|
|
3429
|
+
? [
|
|
3430
|
+
{
|
|
3431
|
+
kind: 'accrual' as const,
|
|
3432
|
+
policyId: applicable.policy.id,
|
|
3433
|
+
policyName: applicable.policy.name,
|
|
3434
|
+
config: applicable.policy.config,
|
|
3435
|
+
from: applicable.assignment.subjectKind,
|
|
3436
|
+
subjectId: applicable.assignment.subjectId,
|
|
3437
|
+
},
|
|
3438
|
+
]
|
|
3439
|
+
: []
|
|
3440
|
+
},
|
|
3441
|
+
},
|
|
3442
|
+
|
|
3443
|
+
accrual: {
|
|
3444
|
+
/**
|
|
3445
|
+
* A query, and it **writes nothing**.
|
|
3446
|
+
*
|
|
3447
|
+
* The contract makes it a query for exactly this reason: a preview that filed ledger entries
|
|
3448
|
+
* would credit everybody the moment somebody looked at the screen meant to tell them what a
|
|
3449
|
+
* run *would* do. It returns the same rows `run` credits from, so the two cannot disagree.
|
|
3450
|
+
*/
|
|
3451
|
+
preview: async ({
|
|
3452
|
+
workspaceId,
|
|
3453
|
+
from,
|
|
3454
|
+
to,
|
|
3455
|
+
personId,
|
|
3456
|
+
}: {
|
|
3457
|
+
workspaceId: string
|
|
3458
|
+
from: string
|
|
3459
|
+
to: string
|
|
3460
|
+
personId?: string
|
|
3461
|
+
}) => {
|
|
3462
|
+
void workspaceId
|
|
3463
|
+
return accrualRows(from, to, personId)
|
|
3464
|
+
},
|
|
3465
|
+
|
|
3466
|
+
/**
|
|
3467
|
+
* Credits the ledger, and is idempotent per person, per leave type, per period.
|
|
3468
|
+
*
|
|
3469
|
+
* A second run over the same window credits nothing, because every row it would write is
|
|
3470
|
+
* already `alreadyAccrued` — an accrual job that double-credits when somebody clicks twice is
|
|
3471
|
+
* worse than one that never ran.
|
|
3472
|
+
*/
|
|
3473
|
+
run: async ({
|
|
3474
|
+
workspaceId,
|
|
3475
|
+
from,
|
|
3476
|
+
to,
|
|
3477
|
+
personId,
|
|
3478
|
+
}: {
|
|
3479
|
+
workspaceId: string
|
|
3480
|
+
from: string
|
|
3481
|
+
to: string
|
|
3482
|
+
personId?: string
|
|
3483
|
+
}) => {
|
|
3484
|
+
void workspaceId
|
|
3485
|
+
const preview = accrualRows(from, to, personId)
|
|
3486
|
+
let credited = 0
|
|
3487
|
+
let totalMinutes = 0
|
|
3488
|
+
for (const row of preview.rows) {
|
|
3489
|
+
if (row.alreadyAccrued) continue
|
|
3490
|
+
ledger.push(
|
|
3491
|
+
entry(row.personId, row.leaveTypeId, 'accrual', row.minutes, to, { reason: row.reason }),
|
|
3492
|
+
)
|
|
3493
|
+
credited += 1
|
|
3494
|
+
totalMinutes += row.minutes
|
|
3495
|
+
}
|
|
3496
|
+
return {
|
|
3497
|
+
credited,
|
|
3498
|
+
// Everything the run passed over: those already credited, and those it never reached.
|
|
3499
|
+
skipped: preview.skipped.length + preview.rows.filter((r) => r.alreadyAccrued).length,
|
|
3500
|
+
totalMinutes,
|
|
3501
|
+
}
|
|
3502
|
+
},
|
|
3503
|
+
},
|
|
3504
|
+
|
|
3040
3505
|
periods: {
|
|
3041
3506
|
list: async ({
|
|
3042
3507
|
workspaceId,
|
|
@@ -77,13 +77,19 @@ const manage = $derived(canHr('approvalManage'))
|
|
|
77
77
|
|
|
78
78
|
// ---------------------------------------------------------------- vocabulary
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
/**
|
|
81
|
+
* What an admin may build a chain *for* — the two things this module can actually raise.
|
|
82
|
+
*
|
|
83
|
+
* `ApprovalSubjectType` still carries `overtime`, `timesheet` and `shift_swap`, because the engine
|
|
84
|
+
* is keyed by subject type on purpose and a stored chain must keep parsing. But offering them here
|
|
85
|
+
* let somebody design, name and save a chain that nothing can ever fire, and then wait for
|
|
86
|
+
* approvals that never arrive — a worse failure than the feature being absent, because it looks
|
|
87
|
+
* configured. They join this list with the code that raises them.
|
|
88
|
+
*
|
|
89
|
+
* `subjectLabel` below stays exhaustive: a workspace that already saved one of those chains must
|
|
90
|
+
* still see it named rather than rendered as a raw enum value.
|
|
91
|
+
*/
|
|
92
|
+
const SUBJECT_TYPES: ApprovalSubjectType[] = ['leave', 'regularization']
|
|
87
93
|
|
|
88
94
|
/** The same names the inbox uses. An approval called one thing here and another there is two things. */
|
|
89
95
|
const subjectLabel = (subject: ApprovalSubjectType): string =>
|
|
@@ -145,7 +151,6 @@ const APPROVER_PERMISSIONS = [
|
|
|
145
151
|
'hr.person.manage',
|
|
146
152
|
'hr.leave.manage',
|
|
147
153
|
'hr.attendance.manage',
|
|
148
|
-
'hr.overtime.manage',
|
|
149
154
|
'hr.office.manage',
|
|
150
155
|
'hr.approval.manage',
|
|
151
156
|
] as const
|
|
@@ -157,13 +162,11 @@ const permissionLabel = (key: string): string =>
|
|
|
157
162
|
? t('chain_perm_leave')
|
|
158
163
|
: key === 'hr.attendance.manage'
|
|
159
164
|
? t('chain_perm_attendance')
|
|
160
|
-
: key === 'hr.
|
|
161
|
-
? t('
|
|
162
|
-
: key === 'hr.
|
|
163
|
-
? t('
|
|
164
|
-
: key
|
|
165
|
-
? t('chain_perm_approval')
|
|
166
|
-
: key
|
|
165
|
+
: key === 'hr.office.manage'
|
|
166
|
+
? t('chain_perm_office')
|
|
167
|
+
: key === 'hr.approval.manage'
|
|
168
|
+
? t('chain_perm_approval')
|
|
169
|
+
: key
|
|
167
170
|
|
|
168
171
|
const modeLabel = (mode: ApprovalStepSpec['mode']): string =>
|
|
169
172
|
mode === 'all' ? t('chain_mode_all') : mode === 'any' ? t('chain_mode_any') : t('chain_mode_quorum')
|
|
@@ -112,14 +112,6 @@ export const hrCapabilities = defineCapabilities([
|
|
|
112
112
|
defaultEnabled: false,
|
|
113
113
|
level: 1,
|
|
114
114
|
},
|
|
115
|
-
{
|
|
116
|
-
id: 'overtime',
|
|
117
|
-
label: 'Overtime',
|
|
118
|
-
description: 'Detect and approve time worked beyond the schedule',
|
|
119
|
-
dependsOn: ['attendance'],
|
|
120
|
-
defaultEnabled: false,
|
|
121
|
-
level: 2,
|
|
122
|
-
},
|
|
123
115
|
{
|
|
124
116
|
id: 'documents',
|
|
125
117
|
label: 'Employee documents',
|
|
@@ -258,20 +258,10 @@ export const hrPermissions = definePermissions([
|
|
|
258
258
|
defaultRoles: ['owner', 'admin'],
|
|
259
259
|
dangerous: true,
|
|
260
260
|
},
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
defaultRoles: ['owner', 'admin'],
|
|
266
|
-
dangerous: false,
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
key: 'hr.overtime.manage',
|
|
270
|
-
label: 'Approve and adjust overtime',
|
|
271
|
-
scope: 'workspace',
|
|
272
|
-
defaultRoles: ['owner', 'admin'],
|
|
273
|
-
dangerous: false,
|
|
274
|
-
},
|
|
261
|
+
// No `hr.overtime.*` here. Overtime is detected, stored and shown as part of attendance, and
|
|
262
|
+
// nothing asks a question these keys could answer — a role checkbox that gates nothing teaches an
|
|
263
|
+
// administrator the same lesson a dead capability switch does. They come back with the approval
|
|
264
|
+
// flow that needs them.
|
|
275
265
|
|
|
276
266
|
// ---------------------------------------------------------------- policies and periods
|
|
277
267
|
{
|
|
@@ -357,8 +347,6 @@ export const HR_PERMISSIONS = {
|
|
|
357
347
|
attendanceView: 'hr.attendance.view',
|
|
358
348
|
attendanceViewTeam: 'hr.attendance.view_team',
|
|
359
349
|
attendanceManage: 'hr.attendance.manage',
|
|
360
|
-
overtimeView: 'hr.overtime.view',
|
|
361
|
-
overtimeManage: 'hr.overtime.manage',
|
|
362
350
|
policyView: 'hr.policy.view',
|
|
363
351
|
policyManage: 'hr.policy.manage',
|
|
364
352
|
periodManage: 'hr.period.manage',
|