@kernhq/module-hr 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/contract/capabilities.d.ts +16 -0
  2. package/dist/contract/capabilities.d.ts.map +1 -1
  3. package/dist/contract/capabilities.js +16 -0
  4. package/dist/contract/capabilities.js.map +1 -1
  5. package/dist/policy/accrual.d.ts +35 -4
  6. package/dist/policy/accrual.d.ts.map +1 -1
  7. package/dist/policy/accrual.js +141 -15
  8. package/dist/policy/accrual.js.map +1 -1
  9. package/dist/policy/working-time.d.ts +115 -9
  10. package/dist/policy/working-time.d.ts.map +1 -1
  11. package/dist/policy/working-time.js +120 -20
  12. package/dist/policy/working-time.js.map +1 -1
  13. package/dist/server/jobs.d.ts +14 -6
  14. package/dist/server/jobs.d.ts.map +1 -1
  15. package/dist/server/jobs.js +458 -144
  16. package/dist/server/jobs.js.map +1 -1
  17. package/dist/server/packs/index.d.ts +14 -0
  18. package/dist/server/packs/index.d.ts.map +1 -1
  19. package/dist/server/packs/index.js +19 -0
  20. package/dist/server/packs/index.js.map +1 -1
  21. package/dist/server/router.d.ts +1887 -111
  22. package/dist/server/router.d.ts.map +1 -1
  23. package/dist/server/router.js +129 -63
  24. package/dist/server/router.js.map +1 -1
  25. package/dist/server/schema.d.ts +17 -0
  26. package/dist/server/schema.d.ts.map +1 -1
  27. package/dist/server/schema.js +81 -2
  28. package/dist/server/schema.js.map +1 -1
  29. package/dist/server/services/approvals.d.ts.map +1 -1
  30. package/dist/server/services/approvals.js +12 -3
  31. package/dist/server/services/approvals.js.map +1 -1
  32. package/dist/server/services/attendance.d.ts +120 -6
  33. package/dist/server/services/attendance.d.ts.map +1 -1
  34. package/dist/server/services/attendance.js +226 -13
  35. package/dist/server/services/attendance.js.map +1 -1
  36. package/dist/server/services/policies.d.ts +6 -0
  37. package/dist/server/services/policies.d.ts.map +1 -1
  38. package/dist/server/services/policies.js +6 -0
  39. package/dist/server/services/policies.js.map +1 -1
  40. package/migrations/0005_approval_requester.sql +11 -1
  41. package/migrations/0006_schedule_no_overlap.sql +85 -0
  42. package/migrations/0007_hot_path_indexes.sql +38 -0
  43. package/migrations/0009_beyond_cap_minutes.sql +15 -0
  44. package/migrations/meta/0005_snapshot.json +4047 -0
  45. package/migrations/meta/0007_snapshot.json +4225 -0
  46. package/migrations/meta/0009_snapshot.json +4231 -0
  47. package/migrations/meta/_journal.json +21 -0
  48. package/package.json +7 -7
  49. package/src/client/components/ClockControls.svelte +127 -20
  50. package/src/client/components/ClockControls.test.ts +446 -0
  51. package/src/client/components/DelegationDialog.svelte +12 -3
  52. package/src/client/components/LeaveRequestDialog.svelte +254 -25
  53. package/src/client/components/PersonFormDialog.svelte +53 -3
  54. package/src/client/components/PersonPanel.svelte +134 -26
  55. package/src/client/i18n.ts +5 -927
  56. package/src/client/messages.test.ts +154 -0
  57. package/src/client/messages.ts +3388 -0
  58. package/src/client/mock.ts +1573 -161
  59. package/src/client/module.ts +15 -1
  60. package/src/client/pages/ApprovalsPage.svelte +120 -46
  61. package/src/client/pages/AttendancePage.svelte +106 -20
  62. package/src/client/pages/DirectoryPage.svelte +192 -55
  63. package/src/client/pages/LeavePage.svelte +280 -25
  64. package/src/client/pages/OfficesPage.svelte +26 -8
  65. package/src/client/pages/leave-and-attendance.test.ts +588 -0
  66. package/src/client/query.ts +12 -0
  67. package/src/client/settings/CalendarsSettings.svelte +1363 -12
  68. package/src/client/settings/CapabilitiesSettings.svelte +276 -19
  69. package/src/client/settings/GeneralSettings.svelte +420 -0
  70. package/src/client/settings/LeaveSettings.svelte +884 -12
  71. package/src/client/settings/OfficesSettings.svelte +1182 -12
  72. package/src/client/settings/SchedulesSettings.svelte +1149 -12
  73. package/src/client/summary.ts +14 -7
  74. package/src/client/widgets/ApprovalsWidget.svelte +133 -20
  75. package/src/client/widgets/HeadcountWidget.svelte +74 -8
  76. package/src/client/widgets/LeaveBalanceWidget.svelte +40 -5
  77. package/src/client/widgets/WhosOutWidget.svelte +47 -8
  78. package/src/contract/capabilities.ts +17 -0
@@ -31,6 +31,22 @@ export declare const hrCapabilities: readonly {
31
31
  description?: string | undefined;
32
32
  }[];
33
33
  export type HrCapabilityId = (typeof hrCapabilities)[number]['id'];
34
+ /**
35
+ * The message ids a screen reads a capability's `label` and `description` through.
36
+ *
37
+ * `CapabilityDef.label` is documented as "an i18n message id or an English fallback", and putting
38
+ * the id *in* the field would leave the fallback nowhere: core's module admin and the shell's mock
39
+ * read this manifest raw, with no HR bundle merged, so they would print `hr.cap_leave` at a person.
40
+ * So the literals above stay the fallback and the id is derived from the capability's own id — a
41
+ * capability added to the list becomes translatable the moment somebody writes its two strings, and
42
+ * nothing that parses this list sees a new field.
43
+ *
44
+ * The `hr.` prefix is written out rather than left to `scopedT`, because a caller has to be able to
45
+ * tell a resolved string from a key that resolved to itself, and `t()` answers a miss with the
46
+ * *namespaced* key.
47
+ */
48
+ export declare const capabilityLabelKey: (id: string) => string;
49
+ export declare const capabilityDescriptionKey: (id: string) => string;
34
50
  /**
35
51
  * Which procedures sit behind which capability.
36
52
  *
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,cAAc;;;;;;;;GAyGzB,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAA;AAElE;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAmFpE,CAAA"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,cAAc;;;;;;;;GAyGzB,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"}
@@ -128,6 +128,22 @@ export const hrCapabilities = defineCapabilities([
128
128
  level: 2,
129
129
  },
130
130
  ]);
131
+ /**
132
+ * The message ids a screen reads a capability's `label` and `description` through.
133
+ *
134
+ * `CapabilityDef.label` is documented as "an i18n message id or an English fallback", and putting
135
+ * the id *in* the field would leave the fallback nowhere: core's module admin and the shell's mock
136
+ * read this manifest raw, with no HR bundle merged, so they would print `hr.cap_leave` at a person.
137
+ * So the literals above stay the fallback and the id is derived from the capability's own id — a
138
+ * capability added to the list becomes translatable the moment somebody writes its two strings, and
139
+ * nothing that parses this list sees a new field.
140
+ *
141
+ * The `hr.` prefix is written out rather than left to `scopedT`, because a caller has to be able to
142
+ * tell a resolved string from a key that resolved to itself, and `t()` answers a miss with the
143
+ * *namespaced* key.
144
+ */
145
+ export const capabilityLabelKey = (id) => `hr.cap_${id}`;
146
+ export const capabilityDescriptionKey = (id) => `hr.cap_${id}_desc`;
131
147
  /**
132
148
  * Which procedures sit behind which capability.
133
149
  *
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"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"}
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,UAAU;QACd,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,oDAAoD;QACjE,SAAS,EAAE,CAAC,YAAY,CAAC;QACzB,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;IACD;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,iEAAiE;QAC9E,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,CAAC;KACT;CACF,CAAC,CAAA;AAIF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE,CAAA;AAChE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,UAAU,EAAE,OAAO,CAAA;AAE3E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsC;IACvE,OAAO,EAAE;QACP,cAAc;QACd,aAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,iBAAiB;QACjB,oBAAoB;QACpB,gBAAgB;QAChB,kBAAkB;QAClB,gBAAgB;KACjB;IACD,cAAc,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,CAAC;IAC3G,SAAS,EAAE;QACT,gBAAgB;QAChB,eAAe;QACf,kBAAkB;QAClB,kBAAkB;QAClB,mBAAmB;QACnB,qBAAqB;QACrB,oBAAoB;QACpB,uBAAuB;QACvB,uBAAuB;QACvB,wBAAwB;QACxB,sBAAsB;QACtB,uBAAuB;KACxB;IACD,SAAS,EAAE,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IACrE,KAAK,EAAE;QACL,kBAAkB;QAClB,oBAAoB;QACpB,oBAAoB;QACpB,qBAAqB;QACrB,mBAAmB;QACnB,mBAAmB;QACnB,cAAc;QACd,qBAAqB;QACrB,oBAAoB;QACpB,yBAAyB;QACzB,uBAAuB;QACvB,uBAAuB;QACvB,qBAAqB;KACtB;IACD,UAAU,EAAE;QACV,kBAAkB;QAClB,oBAAoB;QACpB,qBAAqB;QACrB,uBAAuB;QACvB,qBAAqB;QACrB,yBAAyB;QACzB,yBAAyB;QACzB,sBAAsB;QACtB,2BAA2B;QAC3B,2BAA2B;QAC3B,6BAA6B;QAC7B,6BAA6B;QAC7B,8BAA8B;QAC9B,6BAA6B;QAC7B,iCAAiC;QACjC,oCAAoC;KACrC;IACD,aAAa,EAAE;QACb,eAAe;QACf,cAAc;QACd,iBAAiB;QACjB,iBAAiB;QACjB,kBAAkB;QAClB,iBAAiB;QACjB,mBAAmB;QACnB,qBAAqB;QACrB,iBAAiB;QACjB,aAAa;KACd;IACD,OAAO,EAAE,CAAC,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,CAAC;IAC7E,SAAS,EAAE;QACT,uBAAuB;QACvB,yBAAyB;QACzB,yBAAyB;QACzB,0BAA0B;QAC1B,oBAAoB;QACpB,4BAA4B;QAC5B,uBAAuB;KACxB;CACF,CAAA"}
@@ -34,8 +34,18 @@ export interface AccrualPolicy {
34
34
  roundToMinutes?: number;
35
35
  }
36
36
  export interface CarryForwardPolicy {
37
- /** Maximum minutes that survive into the next entitlement year. 0 means none carries. */
38
- maxMinutes: number;
37
+ /** Maximum days that survive into the next entitlement year. 0 means none carries. */
38
+ maxDays: number;
39
+ /**
40
+ * Minutes in one working day, for converting `maxDays` into the minutes the ledger holds.
41
+ *
42
+ * The same figure the accrual policy credits at, and it is an argument rather than a constant
43
+ * because the contract lets it be anything from 1 to 1440. A cap converted at an assumed eight
44
+ * hours is wrong in both directions: on a seven-and-a-half-hour day five days reads as 2400
45
+ * minutes against 2250 accrued, so the cap never bites, and on a nine-hour day it expires leave
46
+ * somebody was entitled to keep.
47
+ */
48
+ minutesPerDay: number;
39
49
  /** Months into the new year before carried leave expires. Null never expires. */
40
50
  expiresAfterMonths: number | null;
41
51
  }
@@ -72,6 +82,11 @@ export interface AccrualResult {
72
82
  * `fte` scales it again — a half-time contract earns half. The two multiply rather than the larger
73
83
  * winning, because a half-time joiner on the 20th has earned a sixth of a month and both facts are
74
84
  * true at once.
85
+ *
86
+ * The **frequency decides what a period grants**, and each of the four answers a different
87
+ * question — see `grantForPeriod`. The job runs on the same schedule whichever is configured: an
88
+ * annual or anniversary policy simply grants nothing in the months that hold no grant date, so
89
+ * changing the frequency never means changing how often the job runs.
75
90
  */
76
91
  export declare function accrueForPeriod(opts: {
77
92
  policy: AccrualPolicy;
@@ -84,6 +99,10 @@ export declare function accrueForPeriod(opts: {
84
99
  fte: number;
85
100
  /** Unpaid leave inside the period, which most policies do not accrue against. */
86
101
  unpaidDays?: number;
102
+ /** Minutes actually worked in the period. `per_hour_worked` accrues against it. */
103
+ workedMinutes?: number;
104
+ /** Minutes the schedule called for over the same period. `per_hour_worked` needs both. */
105
+ scheduledMinutes?: number;
87
106
  }): AccrualResult;
88
107
  /**
89
108
  * What survives into the next entitlement year, and what lapses.
@@ -92,9 +111,12 @@ export declare function accrueForPeriod(opts: {
92
111
  * the difference — a balance that silently shrinks at midnight on the 1st of January is the single
93
112
  * most disputed number in any leave system.
94
113
  */
95
- export declare function carryForward(balanceMinutes: number, policy: CarryForwardPolicy): {
114
+ export declare function carryForward(balanceMinutes: number, policy: CarryForwardPolicy,
115
+ /** First day of the entitlement year the leave is carried *into*. */
116
+ yearStart: IsoDate): {
96
117
  carriedMinutes: number;
97
118
  expiredMinutes: number;
119
+ expiresOn: IsoDate | null;
98
120
  };
99
121
  /**
100
122
  * The date carried leave lapses, if it does.
@@ -103,7 +125,16 @@ export declare function carryForward(balanceMinutes: number, policy: CarryForwar
103
125
  * "three months to use it" means three months of the new year for everybody — not three months from
104
126
  * whenever the job happened to run.
105
127
  */
106
- export declare function carryExpiryDate(yearStart: IsoDate, policy: CarryForwardPolicy): IsoDate | null;
128
+ export declare function carryExpiryDate(yearStart: IsoDate, expiresAfterMonths: number | null): IsoDate | null;
129
+ /**
130
+ * Has carried leave lapsed by a date?
131
+ *
132
+ * The expiry date is the **first day it is no longer available**, so leave carried with three
133
+ * months to use it survives the whole of March and is gone on 1 April. Somebody booking on the last
134
+ * morning and the sweep that takes it away have to read the boundary the same way, so it is read
135
+ * here and nowhere else.
136
+ */
137
+ export declare function carryHasLapsed(on: IsoDate, expiresOn: IsoDate | null): boolean;
107
138
  /**
108
139
  * Overtime beyond a threshold, with an optional weekly or monthly cap.
109
140
  *
@@ -1 +1 @@
1
- {"version":3,"file":"accrual.d.ts","sourceRoot":"","sources":["../../src/policy/accrual.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accrual.d.ts","sourceRoot":"","sources":["../../src/policy/accrual.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAGnD;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa,GAAG,iBAAiB,CAAA;AAEvF,2FAA2F;AAC3F,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,SAAS,CAAA;AAEpD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,gBAAgB,CAAA;IAC3B,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAA;IACnB,yFAAyF;IACzF,aAAa,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACnE,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;;OAQG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB,iFAAiF;IACjF,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,CAMjE;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAOpF;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,CAMlE;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAA;IACb,EAAE,EAAE,OAAO,CAAA;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAA;IACjB,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,aAAa,CAAA;IACrB,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAA;IAChB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7B,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,GAAG,aAAa,CA8ChB;AA6HD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,kBAAkB;AAC1B,qEAAqE;AACrE,SAAS,EAAE,OAAO,GACjB;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAW/E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAYrG;AAID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,+CAA+C;IAC/C,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,GAAG;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAQxD"}
@@ -1,4 +1,4 @@
1
- import { datesBetween } from './calendar.js';
1
+ import { datesBetween, daysInMonth } from './calendar.js';
2
2
  /**
3
3
  * Completed years between two dates, by anniversary rather than by dividing days.
4
4
  *
@@ -43,6 +43,11 @@ export function completedMonths(from, to) {
43
43
  * `fte` scales it again — a half-time contract earns half. The two multiply rather than the larger
44
44
  * winning, because a half-time joiner on the 20th has earned a sixth of a month and both facts are
45
45
  * true at once.
46
+ *
47
+ * The **frequency decides what a period grants**, and each of the four answers a different
48
+ * question — see `grantForPeriod`. The job runs on the same schedule whichever is configured: an
49
+ * annual or anniversary policy simply grants nothing in the months that hold no grant date, so
50
+ * changing the frequency never means changing how often the job runs.
46
51
  */
47
52
  export function accrueForPeriod(opts) {
48
53
  const { policy, period, hiredOn, terminatedOn, fte } = opts;
@@ -60,25 +65,126 @@ export function accrueForPeriod(opts) {
60
65
  const employedDays = datesBetween(start, end).length;
61
66
  const unpaid = Math.min(opts.unpaidDays ?? 0, employedDays);
62
67
  const countedDays = Math.max(0, employedDays - unpaid);
63
- const proration = countedDays / periodDays;
64
68
  const years = completedYears(hiredOn, end);
65
69
  const entitlementDays = daysPerYearFor(policy, years);
66
- // How much of a *year* this period represents. Monthly is a twelfth; anything else is measured
67
- // from the period itself so a part-year run does not silently become a full one.
68
- const periodShareOfYear = policy.frequency === 'monthly' ? 1 / 12 : periodDays / 365;
69
- const raw = entitlementDays * policy.minutesPerDay * periodShareOfYear * proration * fte;
70
+ const grant = grantForPeriod({
71
+ policy,
72
+ period,
73
+ periodDays,
74
+ hiredOn,
75
+ employedFrom: start,
76
+ employedTo: end,
77
+ employedProration: countedDays / periodDays,
78
+ workedMinutes: opts.workedMinutes,
79
+ scheduledMinutes: opts.scheduledMinutes,
80
+ });
81
+ if (grant.skipped)
82
+ return { minutes: 0, proration: 0, reason: grant.skipped };
83
+ const { shareOfYear, proration } = grant;
84
+ const raw = entitlementDays * policy.minutesPerDay * shareOfYear * proration * fte;
70
85
  const minutes = roundTo(raw, policy.roundToMinutes ?? 0);
71
86
  const parts = [`${entitlementDays}d/yr`];
72
87
  if (years > 0 && policy.seniorityTiers?.length)
73
88
  parts.push(`${years}y service`);
74
- if (proration < 1)
75
- parts.push(`${Math.round(proration * 100)}% of period`);
89
+ parts.push(...grant.notes);
76
90
  if (fte !== 1)
77
91
  parts.push(`${fte} FTE`);
78
92
  if (unpaid > 0)
79
93
  parts.push(`${unpaid}d unpaid`);
80
94
  return { minutes, proration, reason: parts.join(' · ') };
81
95
  }
96
+ /**
97
+ * What one period grants, per frequency.
98
+ *
99
+ * Four frequencies were offered and one was implemented, so three of them were a setting an admin
100
+ * could save and nothing would obey. Each asks a different question:
101
+ *
102
+ * - **monthly** — a twelfth of the year, every period, prorated by the days they were employed.
103
+ * - **annual** — the whole year at once, on the first day of the entitlement year, or on the hire
104
+ * date for somebody who joined after it. A mid-year joiner gets the share of the year that is
105
+ * left, so the grant lands once and is right the first time.
106
+ * - **anniversary** — a whole year on each hire anniversary, earned in arrears. Nothing lands in
107
+ * the month somebody was *hired*: a hire date is not an anniversary, and granting there would
108
+ * pay a full year's entitlement to somebody with no service behind them.
109
+ * - **per_hour_worked** — the period's share of the year, scaled by hours actually worked against
110
+ * hours scheduled. That ratio replaces the employed-days proration rather than multiplying it:
111
+ * somebody who joined mid-month was scheduled for less of it too, and applying both counts the
112
+ * same absence twice.
113
+ *
114
+ * The two point grants take no employed-days proration at all — their share of the year is measured
115
+ * from the grant date, so prorating again would shrink the one period that holds the whole year.
116
+ */
117
+ function grantForPeriod(opts) {
118
+ const { policy, period, periodDays, hiredOn, employedFrom, employedTo, employedProration } = opts;
119
+ const pct = (fraction) => `${Math.round(fraction * 100)}%`;
120
+ switch (policy.frequency) {
121
+ case 'monthly':
122
+ return {
123
+ shareOfYear: 1 / 12,
124
+ proration: employedProration,
125
+ notes: employedProration < 1 ? [`${pct(employedProration)} of period`] : [],
126
+ };
127
+ case 'annual': {
128
+ const year = period.from.slice(0, 4);
129
+ const yearStart = `${year}-01-01`;
130
+ const yearEnd = `${year}-12-31`;
131
+ const grantOn = hiredOn > yearStart ? hiredOn : yearStart;
132
+ if (grantOn < period.from || grantOn > period.to)
133
+ return { shareOfYear: 0, proration: 0, notes: [], skipped: `the annual grant falls on ${grantOn}` };
134
+ if (grantOn > employedTo)
135
+ return { shareOfYear: 0, proration: 0, notes: [], skipped: 'not employed on the grant date' };
136
+ // Against the year's own length rather than 365, so a leap year does not quietly overpay.
137
+ const share = datesBetween(grantOn, yearEnd).length / datesBetween(yearStart, yearEnd).length;
138
+ return {
139
+ shareOfYear: share,
140
+ proration: 1,
141
+ notes: share < 1 ? [`${pct(share)} of the year, from ${grantOn}`] : ['full year'],
142
+ };
143
+ }
144
+ case 'anniversary': {
145
+ const on = anniversaryIn(hiredOn, period.from, period.to);
146
+ if (!on)
147
+ return { shareOfYear: 0, proration: 0, notes: [], skipped: 'no service anniversary in this period' };
148
+ if (completedYears(hiredOn, on) < 1)
149
+ return { shareOfYear: 0, proration: 0, notes: [], skipped: 'the first anniversary is a year away' };
150
+ if (on < employedFrom || on > employedTo)
151
+ return { shareOfYear: 0, proration: 0, notes: [], skipped: 'not employed on the anniversary' };
152
+ return { shareOfYear: 1, proration: 1, notes: [`anniversary on ${on}`] };
153
+ }
154
+ case 'per_hour_worked': {
155
+ const scheduled = opts.scheduledMinutes ?? 0;
156
+ if (scheduled <= 0)
157
+ return {
158
+ shareOfYear: 0,
159
+ proration: 0,
160
+ notes: [],
161
+ skipped: 'no scheduled hours in this period to accrue against',
162
+ };
163
+ const ratio = Math.max(0, opts.workedMinutes ?? 0) / scheduled;
164
+ return {
165
+ shareOfYear: periodDays / 365,
166
+ proration: ratio,
167
+ notes: [`${pct(ratio)} of scheduled hours worked`],
168
+ };
169
+ }
170
+ }
171
+ }
172
+ /**
173
+ * The hire anniversary that falls inside a period, if one does.
174
+ *
175
+ * A 29 February hire has an anniversary in every year and a 29 February in one year of four, so it
176
+ * is clamped to the 28th rather than skipped — otherwise three quarters of that person's
177
+ * anniversaries land on a date the calendar does not have and grant nothing at all.
178
+ */
179
+ function anniversaryIn(hiredOn, from, to) {
180
+ const [, month, day] = hiredOn.split('-').map(Number);
181
+ for (let year = Number(from.slice(0, 4)); year <= Number(to.slice(0, 4)); year++) {
182
+ const on = `${year}-${String(month).padStart(2, '0')}-${String(Math.min(day, daysInMonth(year, month))).padStart(2, '0')}`;
183
+ if (on >= from && on <= to)
184
+ return on;
185
+ }
186
+ return null;
187
+ }
82
188
  const roundTo = (value, step) => step > 0 ? Math.round(value / step) * step : Math.round(value);
83
189
  /**
84
190
  * What survives into the next entitlement year, and what lapses.
@@ -87,11 +193,20 @@ const roundTo = (value, step) => step > 0 ? Math.round(value / step) * step : Ma
87
193
  * the difference — a balance that silently shrinks at midnight on the 1st of January is the single
88
194
  * most disputed number in any leave system.
89
195
  */
90
- export function carryForward(balanceMinutes, policy) {
196
+ export function carryForward(balanceMinutes, policy,
197
+ /** First day of the entitlement year the leave is carried *into*. */
198
+ yearStart) {
91
199
  if (balanceMinutes <= 0)
92
- return { carriedMinutes: 0, expiredMinutes: 0 };
93
- const carried = Math.min(balanceMinutes, policy.maxMinutes);
94
- return { carriedMinutes: carried, expiredMinutes: balanceMinutes - carried };
200
+ return { carriedMinutes: 0, expiredMinutes: 0, expiresOn: null };
201
+ const cap = Math.round(policy.maxDays * policy.minutesPerDay);
202
+ const carried = Math.min(balanceMinutes, cap);
203
+ return {
204
+ carriedMinutes: carried,
205
+ expiredMinutes: balanceMinutes - carried,
206
+ // Nothing carried, nothing to lapse. The date is what the caller stamps on the `carry_in`
207
+ // entry, so a balance of zero carrying an expiry date would be a lapse nobody can point at.
208
+ expiresOn: carried > 0 ? carryExpiryDate(yearStart, policy.expiresAfterMonths) : null,
209
+ };
95
210
  }
96
211
  /**
97
212
  * The date carried leave lapses, if it does.
@@ -100,11 +215,11 @@ export function carryForward(balanceMinutes, policy) {
100
215
  * "three months to use it" means three months of the new year for everybody — not three months from
101
216
  * whenever the job happened to run.
102
217
  */
103
- export function carryExpiryDate(yearStart, policy) {
104
- if (policy.expiresAfterMonths === null)
218
+ export function carryExpiryDate(yearStart, expiresAfterMonths) {
219
+ if (expiresAfterMonths === null)
105
220
  return null;
106
221
  const [y, m, d] = yearStart.split('-').map(Number);
107
- let month = m + policy.expiresAfterMonths;
222
+ let month = m + expiresAfterMonths;
108
223
  let year = y;
109
224
  while (month > 12) {
110
225
  month -= 12;
@@ -115,6 +230,17 @@ export function carryExpiryDate(yearStart, policy) {
115
230
  return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
116
231
  }
117
232
  const isLeap = (y) => (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0;
233
+ /**
234
+ * Has carried leave lapsed by a date?
235
+ *
236
+ * The expiry date is the **first day it is no longer available**, so leave carried with three
237
+ * months to use it survives the whole of March and is gone on 1 April. Somebody booking on the last
238
+ * morning and the sweep that takes it away have to read the boundary the same way, so it is read
239
+ * here and nowhere else.
240
+ */
241
+ export function carryHasLapsed(on, expiresOn) {
242
+ return expiresOn !== null && on >= expiresOn;
243
+ }
118
244
  /**
119
245
  * Overtime beyond a threshold, with an optional weekly or monthly cap.
120
246
  *
@@ -1 +1 @@
1
- {"version":3,"file":"accrual.js","sourceRoot":"","sources":["../../src/policy/accrual.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accrual.js","sourceRoot":"","sources":["../../src/policy/accrual.ts"],"names":[],"mappings":"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"}
@@ -30,6 +30,22 @@ export interface RoundingPolicy {
30
30
  direction: 'nearest' | 'employee' | 'employer';
31
31
  }
32
32
  export declare const NO_ROUNDING: RoundingPolicy;
33
+ /**
34
+ * An overtime policy as a day sees it, already resolved.
35
+ *
36
+ * `computeDay` is pure and stays pure, so which policy applies to this person on this date — and
37
+ * how much of the cap the year has already used — are answered by the caller against the ladder and
38
+ * the sheet, and arrive here as numbers. Absent, every minute past the schedule counts, which is
39
+ * what a workspace with no overtime policy means.
40
+ */
41
+ export interface OvertimePolicy {
42
+ /** Minutes past the schedule before overtime starts counting. */
43
+ thresholdMinutes: number;
44
+ /** Cap for the containing period, in minutes. Null is uncapped. */
45
+ capMinutes: number | null;
46
+ /** Overtime already counted in that period, on days before this one. */
47
+ alreadyCountedMinutes: number;
48
+ }
33
49
  export type PunchDirection = 'in' | 'out' | 'break_start' | 'break_end';
34
50
  export interface PunchInput {
35
51
  /** The instant, server-stamped. Milliseconds since the epoch. */
@@ -42,6 +58,18 @@ export interface DayComputation {
42
58
  workedMinutes: number;
43
59
  breakMinutes: number;
44
60
  overtimeMinutes: number;
61
+ /**
62
+ * Hours worked past the schedule that the cap would not take.
63
+ *
64
+ * Reported rather than dropped: a jurisdiction capping overtime caps what may be *worked*, so
65
+ * these are hours somebody actually put in and a compliance report has to be able to sum them.
66
+ *
67
+ * **Null and zero say different things.** Null is no cap in force — nothing to exceed, and
68
+ * nothing a report should count as compliant. Zero is a cap in force that this day stayed inside.
69
+ * Only the policy separates them, so the distinction is drawn here rather than re-derived
70
+ * wherever the number is stored.
71
+ */
72
+ beyondCapMinutes: number | null;
45
73
  lateMinutes: number;
46
74
  earlyLeaveMinutes: number;
47
75
  status: 'present' | 'absent' | 'partial' | 'pending';
@@ -58,18 +86,94 @@ export interface DayComputation {
58
86
  */
59
87
  export declare const crossesMidnight: (shift: ShiftSpec) => boolean;
60
88
  /**
61
- * Which business day a punch belongs to.
89
+ * Whether a shift is already running, by business date — the fact a clock reading cannot supply.
90
+ *
91
+ * Both are read from punches already filed: a clock-in with no clock-out after it. Gathering them is
92
+ * the caller's job and deciding what they mean is this file's, the same split `computeDay` already
93
+ * makes with the punches themselves.
94
+ */
95
+ export interface OpenShifts {
96
+ /** A shift left open on the punch's own local date. */
97
+ onLocalDate: boolean;
98
+ /** A shift left open on the date before it — the night that may still be running. */
99
+ onPreviousDate: boolean;
100
+ /**
101
+ * The previous date already holds punches, open or closed.
102
+ *
103
+ * Distinct from `onPreviousDate`, and the difference is a day sheet nobody can explain. A night
104
+ * worked 22:00–05:30 and clocked out of is *closed*, so it is not open — but it is also not
105
+ * waiting for anybody, and an arrival at 05:50 that joined it rewrote a finished Friday from
106
+ * 450 minutes to 1060, with four punches and nine hours of overtime, from somebody turning up
107
+ * early for Saturday.
108
+ */
109
+ workedPreviousDate: boolean;
110
+ }
111
+ /** Nobody is mid-shift and nothing was worked yesterday, so every punch is an arrival. */
112
+ export declare const NOTHING_OPEN: OpenShifts;
113
+ /**
114
+ * What one business date's punches say about whether a shift, and a break, are still running.
115
+ *
116
+ * One reduction behind three questions that must never disagree: which shift the next punch joins,
117
+ * whether the transition it asks for is possible, and what the clock widget tells the person before
118
+ * they press anything. Rows have to arrive sorted by instant. `out` closes a break as well as a
119
+ * shift, because somebody who clocks out without ending their break has still stopped working.
120
+ */
121
+ export declare function openState(punches: Array<{
122
+ direction: string;
123
+ }>): {
124
+ clockedIn: boolean;
125
+ onBreak: boolean;
126
+ };
127
+ /**
128
+ * Which shift a punch belongs to, and the business date that follows from it.
129
+ *
130
+ * A punch in the morning between a night shift and a day shift has two readings and **the clock
131
+ * cannot separate them**: at 06:59 on a Saturday, somebody who worked the 22:00–06:00 night is
132
+ * leaving it, and somebody who did not is arriving early for the 08:00 morning. Three versions of
133
+ * this function drew a line through that window — at the night's scheduled end, at the morning's
134
+ * start, at the midpoint of the gap widened by `graceInMinutes` — and every one of them filed one of
135
+ * those two people on the wrong day, one minute either side of wherever the line had moved to. There
136
+ * is no line to draw. What separates the two readings is not in the instant.
137
+ *
138
+ * It is in the punches. A shift is **open** when a clock-in has been filed on a business date with
139
+ * nothing closing it, and at most one shift is open at a time, because a person is in one place. So:
62
140
  *
63
- * For a day shift, the local date. For a night shift, **the date the shift started**: somebody
64
- * clocking out at 06:00 on Tuesday finished Monday's shift, and putting those minutes on Tuesday
65
- * leaves Monday short and Tuesday long — which is how a month's total comes out right while every
66
- * individual day is wrong.
141
+ * 1. **A departure belongs to the shift it is leaving.** Where a shift is open the punch joins it,
142
+ * however far past the scheduled end it is made, because nothing else can close it. The most
143
+ * recent open one wins: that is the shift they are actually on.
144
+ * 2. **Everything else is an arrival**, and it opens the shift the clock says is running — the
145
+ * previous night while that night is still scheduled to run and the day's own shift has not
146
+ * started yet, otherwise the day it happened on.
67
147
  *
68
- * The zone is the person's, from their primary office. A punch on a business trip records the zone
69
- * it happened in for audit but is still attributed here, or a week abroad splits somebody's month
70
- * across two calendars.
148
+ * An open shift is a fact in the database rather than a guess about an instant, which is why this
149
+ * degrades correctly at both ends where a boundary could not: somebody who never clocked in last
150
+ * night has nothing open, so their early arrival is an arrival at any hour, and somebody who worked
151
+ * the night has something open, so their late departure is a departure however long they overran.
152
+ * No constant appears in either rule, so there is no minute left to get wrong.
153
+ *
154
+ * Rule (1) reaches exactly one calendar day back, and that is what stops a shift nobody ever closed
155
+ * claiming punches for ever: a day later the date in between holds no punches, nothing is open, and
156
+ * arrivals resume. Until then the person is *told* they are still clocked in, because
157
+ * `attendance.state` reads this same attribution from the same rows — so the action offered to them
158
+ * is the one that closes it, and no refusal arrives that the screen did not predict.
159
+ *
160
+ * One thing stays undecided, and it costs a date rather than a refusal. Where the night was NEVER
161
+ * WORKED — nothing open and nothing filed — a punch inside its scheduled span reads as a late
162
+ * arrival for it: at 05:59 that files a two-hour-early arrival for the morning on the night's date.
163
+ * Both ends of that shift still land together, since the clock-out follows the shift the clock-in
164
+ * opened, so nobody is turned away. The sheet is wrong about which day, and says somebody was very
165
+ * late for a shift they were in fact early for.
166
+ *
167
+ * It is left because nothing available at that instant settles it: at 05:59 a person with a night
168
+ * scheduled and nothing filed is either eleven minutes from the end of a shift they never started
169
+ * or two hours early for the next one, and only the clock-out — which has not happened — tells them
170
+ * apart. Deciding it on how much of the night is left would be a fourth constant, and three have
171
+ * been tried. A night already worked is a different question and is answered above.
71
172
  */
72
- export declare function businessDateFor(instantMs: number, timeZone: string, shift: ShiftSpec | null): IsoDate;
173
+ export declare function attributeToShift(instantMs: number, timeZone: string, shiftFor: (date: IsoDate) => ShiftSpec | null, open: OpenShifts): {
174
+ businessDate: IsoDate;
175
+ shift: ShiftSpec | null;
176
+ };
73
177
  /**
74
178
  * The scheduled span of a shift on a date — computed from instants, not from clock readings.
75
179
  *
@@ -92,6 +196,8 @@ export declare function computeDay(opts: {
92
196
  shift: ShiftSpec | null;
93
197
  punches: PunchInput[];
94
198
  rounding?: RoundingPolicy;
199
+ /** The resolved overtime policy. Absent, everything past the schedule is overtime. */
200
+ overtime?: OvertimePolicy;
95
201
  /** Approved leave or a holiday: not an absence, whatever the punches say. */
96
202
  excused?: boolean;
97
203
  }): DayComputation;
@@ -1 +1 @@
1
- {"version":3,"file":"working-time.d.ts","sourceRoot":"","sources":["../../src/policy/working-time.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAGnD;;;;;;GAMG;AAEH,wGAAwG;AACxG,MAAM,WAAW,SAAS;IACxB,cAAc;IACd,KAAK,EAAE,MAAM,CAAA;IACb,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAA;IACX,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAA;IACpB,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAA;IACtB,kEAAkE;IAClE,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;CAC/C;AAED,eAAO,MAAM,WAAW,EAAE,cAAyD,CAAA;AAEnF,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,KAAK,GAAG,aAAa,GAAG,WAAW,CAAA;AAEvE,MAAM,WAAW,UAAU;IACzB,iEAAiE;IACjE,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,cAAc,CAAA;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,OAAO,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAA;IACpD,2EAA2E;IAC3E,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,SAAS,KAAG,OAAyD,CAAA;AAO5G;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAWrG;AAwBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAK5F;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE;IAC/B,YAAY,EAAE,OAAO,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,cAAc,CA8GjB"}
1
+ {"version":3,"file":"working-time.d.ts","sourceRoot":"","sources":["../../src/policy/working-time.ts"],"names":[],"mappings":"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"}