@kernhq/module-hr 0.17.1 → 0.18.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/index.d.ts +1 -0
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +1 -0
- package/dist/contract/index.js.map +1 -1
- package/dist/contract/permissions.d.ts +8 -0
- package/dist/contract/permissions.d.ts.map +1 -1
- package/dist/contract/permissions.js +25 -0
- package/dist/contract/permissions.js.map +1 -1
- package/dist/contract/reports.d.ts +501 -0
- package/dist/contract/reports.d.ts.map +1 -0
- package/dist/contract/reports.js +318 -0
- package/dist/contract/reports.js.map +1 -0
- package/dist/contract/router.d.ts +420 -0
- package/dist/contract/router.d.ts.map +1 -1
- package/dist/contract/router.js +97 -0
- package/dist/contract/router.js.map +1 -1
- package/dist/server/router.d.ts +486 -0
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +437 -17
- package/dist/server/router.js.map +1 -1
- package/dist/server/services/reports.d.ts +319 -0
- package/dist/server/services/reports.d.ts.map +1 -0
- package/dist/server/services/reports.js +627 -0
- package/dist/server/services/reports.js.map +1 -0
- package/package.json +1 -1
- package/src/contract/index.ts +1 -0
- package/src/contract/permissions.ts +27 -0
- package/src/contract/reports.ts +363 -0
- package/src/contract/router.ts +110 -0
|
@@ -5910,6 +5910,426 @@ export declare const hrContract: {
|
|
|
5910
5910
|
* nobody by default and ships in the same change as these — see `privacy.ts` for why there is one
|
|
5911
5911
|
* key rather than four, and why none of this is a capability.
|
|
5912
5912
|
*/
|
|
5913
|
+
/**
|
|
5914
|
+
* Four aggregates, and one rule that decides all four: **a report may not answer a question its
|
|
5915
|
+
* row-level procedure would refuse, and may not narrow below what that procedure already
|
|
5916
|
+
* returns.**
|
|
5917
|
+
*
|
|
5918
|
+
* So each of these costs `hr.report.view` *and* the key that already guards the rows it sums —
|
|
5919
|
+
* `hr.attendance.view_team`, which is what reading a whole office's day sheets costs on
|
|
5920
|
+
* `attendance.days.list`, or `hr.leave.view_team`, which is what reading somebody else's balance
|
|
5921
|
+
* costs on `leave.balance.get`. A reader holding neither gets nothing: not a one-row self-report,
|
|
5922
|
+
* because a reports menu that quietly collapses to your own attendance is a menu entry that lies
|
|
5923
|
+
* about what it is, and your own attendance is already the attendance page.
|
|
5924
|
+
*
|
|
5925
|
+
* The population is **not** intersected with `HrAccessService.visiblePersonIds`. That service
|
|
5926
|
+
* narrows *fields* rather than rows — it withholds `personalEmail`, `phone`, `hiredOn` and
|
|
5927
|
+
* `terminatedOn`, none of which any report reads — and intersecting on it would produce the worst
|
|
5928
|
+
* outcome available here: two managers reading different totals under the same title, with
|
|
5929
|
+
* nothing on the page to say so.
|
|
5930
|
+
*/
|
|
5931
|
+
reports: {
|
|
5932
|
+
/**
|
|
5933
|
+
* Scheduled against worked, per person, over a range.
|
|
5934
|
+
*
|
|
5935
|
+
* Built from `attendance_days` and never from `punches`: punches are raw and append-only, a
|
|
5936
|
+
* voided punch survives beside its correction, and summing them double-counts every fix. The
|
|
5937
|
+
* day sheet is the projection those punches produce.
|
|
5938
|
+
*/
|
|
5939
|
+
attendance: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
5940
|
+
workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
|
|
5941
|
+
from: z.ZodISODate;
|
|
5942
|
+
to: z.ZodISODate;
|
|
5943
|
+
by: z.ZodDefault<z.ZodEnum<{
|
|
5944
|
+
office: "office";
|
|
5945
|
+
legal_entity: "legal_entity";
|
|
5946
|
+
workspace: "workspace";
|
|
5947
|
+
}>>;
|
|
5948
|
+
sliceId: z.ZodOptional<z.ZodUUID>;
|
|
5949
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
5950
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
5951
|
+
header: z.ZodObject<{
|
|
5952
|
+
from: z.ZodISODate;
|
|
5953
|
+
to: z.ZodISODate;
|
|
5954
|
+
slice: z.ZodObject<{
|
|
5955
|
+
by: z.ZodEnum<{
|
|
5956
|
+
office: "office";
|
|
5957
|
+
legal_entity: "legal_entity";
|
|
5958
|
+
workspace: "workspace";
|
|
5959
|
+
}>;
|
|
5960
|
+
id: z.ZodNullable<z.ZodUUID>;
|
|
5961
|
+
name: z.ZodNullable<z.ZodString>;
|
|
5962
|
+
}, z.core.$strip>;
|
|
5963
|
+
scope: z.ZodObject<{
|
|
5964
|
+
permissions: z.ZodArray<z.ZodString>;
|
|
5965
|
+
askedAt: z.ZodLiteral<"workspace">;
|
|
5966
|
+
}, z.core.$strip>;
|
|
5967
|
+
population: z.ZodNumber;
|
|
5968
|
+
counted: z.ZodNumber;
|
|
5969
|
+
attribution: z.ZodEnum<{
|
|
5970
|
+
each_day: "each_day";
|
|
5971
|
+
as_of_date: "as_of_date";
|
|
5972
|
+
not_applicable: "not_applicable";
|
|
5973
|
+
}>;
|
|
5974
|
+
attributionOn: z.ZodNullable<z.ZodISODate>;
|
|
5975
|
+
truncated: z.ZodBoolean;
|
|
5976
|
+
}, z.core.$strip>;
|
|
5977
|
+
finality: z.ZodObject<{
|
|
5978
|
+
lockedDays: z.ZodNumber;
|
|
5979
|
+
openDays: z.ZodNumber;
|
|
5980
|
+
final: z.ZodBoolean;
|
|
5981
|
+
firstOpenDay: z.ZodNullable<z.ZodISODate>;
|
|
5982
|
+
lastLockedDay: z.ZodNullable<z.ZodISODate>;
|
|
5983
|
+
}, z.core.$strip>;
|
|
5984
|
+
totals: z.ZodObject<{
|
|
5985
|
+
scheduledMinutes: z.ZodNumber;
|
|
5986
|
+
workedMinutes: z.ZodNumber;
|
|
5987
|
+
breakMinutes: z.ZodNumber;
|
|
5988
|
+
lateMinutes: z.ZodNumber;
|
|
5989
|
+
earlyLeaveMinutes: z.ZodNumber;
|
|
5990
|
+
days: z.ZodNumber;
|
|
5991
|
+
workedRatio: z.ZodNullable<z.ZodNumber>;
|
|
5992
|
+
noScheduleDays: z.ZodNumber;
|
|
5993
|
+
unknownScheduleDays: z.ZodNumber;
|
|
5994
|
+
}, z.core.$strip>;
|
|
5995
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
5996
|
+
personId: z.ZodUUID;
|
|
5997
|
+
displayName: z.ZodString;
|
|
5998
|
+
days: z.ZodNumber;
|
|
5999
|
+
scheduledMinutes: z.ZodNumber;
|
|
6000
|
+
workedMinutes: z.ZodNumber;
|
|
6001
|
+
breakMinutes: z.ZodNumber;
|
|
6002
|
+
lateMinutes: z.ZodNumber;
|
|
6003
|
+
earlyLeaveMinutes: z.ZodNumber;
|
|
6004
|
+
workedRatio: z.ZodNullable<z.ZodNumber>;
|
|
6005
|
+
noScheduleDays: z.ZodNumber;
|
|
6006
|
+
unknownScheduleDays: z.ZodNumber;
|
|
6007
|
+
}, z.core.$strip>>;
|
|
6008
|
+
}, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
|
|
6009
|
+
BAD_REQUEST: {
|
|
6010
|
+
data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
6011
|
+
};
|
|
6012
|
+
UNAUTHORIZED: {};
|
|
6013
|
+
FORBIDDEN: {
|
|
6014
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6015
|
+
permission: z.ZodOptional<z.ZodString>;
|
|
6016
|
+
}, z.core.$strip>>;
|
|
6017
|
+
};
|
|
6018
|
+
NOT_FOUND: {};
|
|
6019
|
+
CONFLICT: {
|
|
6020
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6021
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
6022
|
+
}, z.core.$strip>>;
|
|
6023
|
+
};
|
|
6024
|
+
RATE_LIMITED: {};
|
|
6025
|
+
MODULE_DISABLED: {
|
|
6026
|
+
data: z.ZodObject<{
|
|
6027
|
+
module: z.ZodString;
|
|
6028
|
+
}, z.core.$strip>;
|
|
6029
|
+
};
|
|
6030
|
+
}>, Record<never, never>>;
|
|
6031
|
+
/**
|
|
6032
|
+
* Overtime, and how much of it an annual ceiling would not take.
|
|
6033
|
+
*
|
|
6034
|
+
* `beyondCapMinutes` is null where no ceiling was in force — summed as a nullable column rather
|
|
6035
|
+
* than coalesced, so "no ceiling applied to these days" and "a ceiling applied and nothing
|
|
6036
|
+
* passed it" stay different answers. No projection: there is no "at this rate you will pass the
|
|
6037
|
+
* ceiling in November", because that needs a policy that may not exist.
|
|
6038
|
+
*/
|
|
6039
|
+
overtime: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
6040
|
+
workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
|
|
6041
|
+
from: z.ZodISODate;
|
|
6042
|
+
to: z.ZodISODate;
|
|
6043
|
+
by: z.ZodDefault<z.ZodEnum<{
|
|
6044
|
+
office: "office";
|
|
6045
|
+
legal_entity: "legal_entity";
|
|
6046
|
+
workspace: "workspace";
|
|
6047
|
+
}>>;
|
|
6048
|
+
sliceId: z.ZodOptional<z.ZodUUID>;
|
|
6049
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
6050
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
6051
|
+
header: z.ZodObject<{
|
|
6052
|
+
from: z.ZodISODate;
|
|
6053
|
+
to: z.ZodISODate;
|
|
6054
|
+
slice: z.ZodObject<{
|
|
6055
|
+
by: z.ZodEnum<{
|
|
6056
|
+
office: "office";
|
|
6057
|
+
legal_entity: "legal_entity";
|
|
6058
|
+
workspace: "workspace";
|
|
6059
|
+
}>;
|
|
6060
|
+
id: z.ZodNullable<z.ZodUUID>;
|
|
6061
|
+
name: z.ZodNullable<z.ZodString>;
|
|
6062
|
+
}, z.core.$strip>;
|
|
6063
|
+
scope: z.ZodObject<{
|
|
6064
|
+
permissions: z.ZodArray<z.ZodString>;
|
|
6065
|
+
askedAt: z.ZodLiteral<"workspace">;
|
|
6066
|
+
}, z.core.$strip>;
|
|
6067
|
+
population: z.ZodNumber;
|
|
6068
|
+
counted: z.ZodNumber;
|
|
6069
|
+
attribution: z.ZodEnum<{
|
|
6070
|
+
each_day: "each_day";
|
|
6071
|
+
as_of_date: "as_of_date";
|
|
6072
|
+
not_applicable: "not_applicable";
|
|
6073
|
+
}>;
|
|
6074
|
+
attributionOn: z.ZodNullable<z.ZodISODate>;
|
|
6075
|
+
truncated: z.ZodBoolean;
|
|
6076
|
+
}, z.core.$strip>;
|
|
6077
|
+
finality: z.ZodObject<{
|
|
6078
|
+
lockedDays: z.ZodNumber;
|
|
6079
|
+
openDays: z.ZodNumber;
|
|
6080
|
+
final: z.ZodBoolean;
|
|
6081
|
+
firstOpenDay: z.ZodNullable<z.ZodISODate>;
|
|
6082
|
+
lastLockedDay: z.ZodNullable<z.ZodISODate>;
|
|
6083
|
+
}, z.core.$strip>;
|
|
6084
|
+
totals: z.ZodObject<{
|
|
6085
|
+
overtimeMinutes: z.ZodNumber;
|
|
6086
|
+
beyondCapMinutes: z.ZodNullable<z.ZodNumber>;
|
|
6087
|
+
days: z.ZodNumber;
|
|
6088
|
+
cappedDays: z.ZodNumber;
|
|
6089
|
+
uncappedDays: z.ZodNumber;
|
|
6090
|
+
}, z.core.$strip>;
|
|
6091
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
6092
|
+
personId: z.ZodUUID;
|
|
6093
|
+
displayName: z.ZodString;
|
|
6094
|
+
days: z.ZodNumber;
|
|
6095
|
+
overtimeMinutes: z.ZodNumber;
|
|
6096
|
+
beyondCapMinutes: z.ZodNullable<z.ZodNumber>;
|
|
6097
|
+
cappedDays: z.ZodNumber;
|
|
6098
|
+
uncappedDays: z.ZodNumber;
|
|
6099
|
+
}, z.core.$strip>>;
|
|
6100
|
+
}, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
|
|
6101
|
+
BAD_REQUEST: {
|
|
6102
|
+
data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
6103
|
+
};
|
|
6104
|
+
UNAUTHORIZED: {};
|
|
6105
|
+
FORBIDDEN: {
|
|
6106
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6107
|
+
permission: z.ZodOptional<z.ZodString>;
|
|
6108
|
+
}, z.core.$strip>>;
|
|
6109
|
+
};
|
|
6110
|
+
NOT_FOUND: {};
|
|
6111
|
+
CONFLICT: {
|
|
6112
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6113
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
6114
|
+
}, z.core.$strip>>;
|
|
6115
|
+
};
|
|
6116
|
+
RATE_LIMITED: {};
|
|
6117
|
+
MODULE_DISABLED: {
|
|
6118
|
+
data: z.ZodObject<{
|
|
6119
|
+
module: z.ZodString;
|
|
6120
|
+
}, z.core.$strip>;
|
|
6121
|
+
};
|
|
6122
|
+
}>, Record<never, never>>;
|
|
6123
|
+
/**
|
|
6124
|
+
* Expected working days, minus days worked, minus approved leave.
|
|
6125
|
+
*
|
|
6126
|
+
* **Never `status = 'absent'`.** `attendance_days` has a row only where somebody punched — no
|
|
6127
|
+
* writer creates one for a day nobody clocked in on — so counting absent rows reports near-zero
|
|
6128
|
+
* absence everywhere and looks entirely healthy while doing it. The denominator comes from the
|
|
6129
|
+
* calendar instead, and a person the module cannot build one for lands in a named row rather
|
|
6130
|
+
* than being counted as present.
|
|
6131
|
+
*
|
|
6132
|
+
* Held to `MAX_SLICED_REPORT_DAYS` whether it is sliced or not: every person's expectation is
|
|
6133
|
+
* their office's calendar on each day, which is a ladder walk per day.
|
|
6134
|
+
*/
|
|
6135
|
+
absence: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
6136
|
+
workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
|
|
6137
|
+
from: z.ZodISODate;
|
|
6138
|
+
to: z.ZodISODate;
|
|
6139
|
+
by: z.ZodDefault<z.ZodEnum<{
|
|
6140
|
+
office: "office";
|
|
6141
|
+
legal_entity: "legal_entity";
|
|
6142
|
+
workspace: "workspace";
|
|
6143
|
+
}>>;
|
|
6144
|
+
sliceId: z.ZodOptional<z.ZodUUID>;
|
|
6145
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
6146
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
6147
|
+
header: z.ZodObject<{
|
|
6148
|
+
from: z.ZodISODate;
|
|
6149
|
+
to: z.ZodISODate;
|
|
6150
|
+
slice: z.ZodObject<{
|
|
6151
|
+
by: z.ZodEnum<{
|
|
6152
|
+
office: "office";
|
|
6153
|
+
legal_entity: "legal_entity";
|
|
6154
|
+
workspace: "workspace";
|
|
6155
|
+
}>;
|
|
6156
|
+
id: z.ZodNullable<z.ZodUUID>;
|
|
6157
|
+
name: z.ZodNullable<z.ZodString>;
|
|
6158
|
+
}, z.core.$strip>;
|
|
6159
|
+
scope: z.ZodObject<{
|
|
6160
|
+
permissions: z.ZodArray<z.ZodString>;
|
|
6161
|
+
askedAt: z.ZodLiteral<"workspace">;
|
|
6162
|
+
}, z.core.$strip>;
|
|
6163
|
+
population: z.ZodNumber;
|
|
6164
|
+
counted: z.ZodNumber;
|
|
6165
|
+
attribution: z.ZodEnum<{
|
|
6166
|
+
each_day: "each_day";
|
|
6167
|
+
as_of_date: "as_of_date";
|
|
6168
|
+
not_applicable: "not_applicable";
|
|
6169
|
+
}>;
|
|
6170
|
+
attributionOn: z.ZodNullable<z.ZodISODate>;
|
|
6171
|
+
truncated: z.ZodBoolean;
|
|
6172
|
+
}, z.core.$strip>;
|
|
6173
|
+
finality: z.ZodObject<{
|
|
6174
|
+
lockedDays: z.ZodNumber;
|
|
6175
|
+
openDays: z.ZodNumber;
|
|
6176
|
+
final: z.ZodBoolean;
|
|
6177
|
+
firstOpenDay: z.ZodNullable<z.ZodISODate>;
|
|
6178
|
+
lastLockedDay: z.ZodNullable<z.ZodISODate>;
|
|
6179
|
+
}, z.core.$strip>;
|
|
6180
|
+
leaveCounted: z.ZodBoolean;
|
|
6181
|
+
totals: z.ZodObject<{
|
|
6182
|
+
measured: z.ZodNumber;
|
|
6183
|
+
expectedDays: z.ZodNumber;
|
|
6184
|
+
workedDays: z.ZodNumber;
|
|
6185
|
+
leaveDays: z.ZodNullable<z.ZodNumber>;
|
|
6186
|
+
absentDays: z.ZodNumber;
|
|
6187
|
+
absenceRate: z.ZodNullable<z.ZodNumber>;
|
|
6188
|
+
}, z.core.$strip>;
|
|
6189
|
+
excluded: z.ZodObject<{
|
|
6190
|
+
noSchedule: z.ZodNumber;
|
|
6191
|
+
noCalendar: z.ZodNumber;
|
|
6192
|
+
}, z.core.$strip>;
|
|
6193
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
6194
|
+
personId: z.ZodUUID;
|
|
6195
|
+
displayName: z.ZodString;
|
|
6196
|
+
basis: z.ZodEnum<{
|
|
6197
|
+
calendar: "calendar";
|
|
6198
|
+
no_calendar: "no_calendar";
|
|
6199
|
+
no_schedule: "no_schedule";
|
|
6200
|
+
}>;
|
|
6201
|
+
expectedDays: z.ZodNullable<z.ZodNumber>;
|
|
6202
|
+
workedDays: z.ZodNullable<z.ZodNumber>;
|
|
6203
|
+
leaveDays: z.ZodNullable<z.ZodNumber>;
|
|
6204
|
+
absentDays: z.ZodNullable<z.ZodNumber>;
|
|
6205
|
+
absenceRate: z.ZodNullable<z.ZodNumber>;
|
|
6206
|
+
}, z.core.$strip>>;
|
|
6207
|
+
}, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
|
|
6208
|
+
BAD_REQUEST: {
|
|
6209
|
+
data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
6210
|
+
};
|
|
6211
|
+
UNAUTHORIZED: {};
|
|
6212
|
+
FORBIDDEN: {
|
|
6213
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6214
|
+
permission: z.ZodOptional<z.ZodString>;
|
|
6215
|
+
}, z.core.$strip>>;
|
|
6216
|
+
};
|
|
6217
|
+
NOT_FOUND: {};
|
|
6218
|
+
CONFLICT: {
|
|
6219
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6220
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
6221
|
+
}, z.core.$strip>>;
|
|
6222
|
+
};
|
|
6223
|
+
RATE_LIMITED: {};
|
|
6224
|
+
MODULE_DISABLED: {
|
|
6225
|
+
data: z.ZodObject<{
|
|
6226
|
+
module: z.ZodString;
|
|
6227
|
+
}, z.core.$strip>;
|
|
6228
|
+
};
|
|
6229
|
+
}>, Record<never, never>>;
|
|
6230
|
+
/**
|
|
6231
|
+
* Every balance in the population, per leave type, for one entitlement year.
|
|
6232
|
+
*
|
|
6233
|
+
* A balance is a position rather than a per-day quantity, so it is attributed as of one date —
|
|
6234
|
+
* `asOf`, defaulting to today — and the response says so. Summed from `leave_ledger`, never
|
|
6235
|
+
* from `leave_balance_cursor`: the cursor exists to be locked, and a cache that is also the
|
|
6236
|
+
* source of truth is one that eventually disagrees with it.
|
|
6237
|
+
*/
|
|
6238
|
+
leaveBalance: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
6239
|
+
workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
|
|
6240
|
+
periodYear: z.ZodOptional<z.ZodNumber>;
|
|
6241
|
+
asOf: z.ZodOptional<z.ZodISODate>;
|
|
6242
|
+
by: z.ZodDefault<z.ZodEnum<{
|
|
6243
|
+
office: "office";
|
|
6244
|
+
legal_entity: "legal_entity";
|
|
6245
|
+
workspace: "workspace";
|
|
6246
|
+
}>>;
|
|
6247
|
+
sliceId: z.ZodOptional<z.ZodUUID>;
|
|
6248
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
6249
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
6250
|
+
header: z.ZodObject<{
|
|
6251
|
+
from: z.ZodISODate;
|
|
6252
|
+
to: z.ZodISODate;
|
|
6253
|
+
slice: z.ZodObject<{
|
|
6254
|
+
by: z.ZodEnum<{
|
|
6255
|
+
office: "office";
|
|
6256
|
+
legal_entity: "legal_entity";
|
|
6257
|
+
workspace: "workspace";
|
|
6258
|
+
}>;
|
|
6259
|
+
id: z.ZodNullable<z.ZodUUID>;
|
|
6260
|
+
name: z.ZodNullable<z.ZodString>;
|
|
6261
|
+
}, z.core.$strip>;
|
|
6262
|
+
scope: z.ZodObject<{
|
|
6263
|
+
permissions: z.ZodArray<z.ZodString>;
|
|
6264
|
+
askedAt: z.ZodLiteral<"workspace">;
|
|
6265
|
+
}, z.core.$strip>;
|
|
6266
|
+
population: z.ZodNumber;
|
|
6267
|
+
counted: z.ZodNumber;
|
|
6268
|
+
attribution: z.ZodEnum<{
|
|
6269
|
+
each_day: "each_day";
|
|
6270
|
+
as_of_date: "as_of_date";
|
|
6271
|
+
not_applicable: "not_applicable";
|
|
6272
|
+
}>;
|
|
6273
|
+
attributionOn: z.ZodNullable<z.ZodISODate>;
|
|
6274
|
+
truncated: z.ZodBoolean;
|
|
6275
|
+
}, z.core.$strip>;
|
|
6276
|
+
periodYear: z.ZodNumber;
|
|
6277
|
+
dayLengthMinutes: z.ZodNumber;
|
|
6278
|
+
totals: z.ZodArray<z.ZodObject<{
|
|
6279
|
+
leaveTypeId: z.ZodUUID;
|
|
6280
|
+
leaveTypeName: z.ZodString;
|
|
6281
|
+
unit: z.ZodEnum<{
|
|
6282
|
+
half_day: "half_day";
|
|
6283
|
+
day: "day";
|
|
6284
|
+
hour: "hour";
|
|
6285
|
+
}>;
|
|
6286
|
+
people: z.ZodNumber;
|
|
6287
|
+
balanceMinutes: z.ZodNumber;
|
|
6288
|
+
bookedMinutes: z.ZodNumber;
|
|
6289
|
+
pendingMinutes: z.ZodNumber;
|
|
6290
|
+
availableMinutes: z.ZodNumber;
|
|
6291
|
+
}, z.core.$strip>>;
|
|
6292
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
6293
|
+
personId: z.ZodUUID;
|
|
6294
|
+
displayName: z.ZodString;
|
|
6295
|
+
leaveTypeId: z.ZodUUID;
|
|
6296
|
+
leaveTypeName: z.ZodString;
|
|
6297
|
+
unit: z.ZodEnum<{
|
|
6298
|
+
half_day: "half_day";
|
|
6299
|
+
day: "day";
|
|
6300
|
+
hour: "hour";
|
|
6301
|
+
}>;
|
|
6302
|
+
balanceMinutes: z.ZodNumber;
|
|
6303
|
+
bookedMinutes: z.ZodNumber;
|
|
6304
|
+
pendingMinutes: z.ZodNumber;
|
|
6305
|
+
availableMinutes: z.ZodNumber;
|
|
6306
|
+
balance: z.ZodNumber;
|
|
6307
|
+
available: z.ZodNumber;
|
|
6308
|
+
}, z.core.$strip>>;
|
|
6309
|
+
}, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
|
|
6310
|
+
BAD_REQUEST: {
|
|
6311
|
+
data: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
6312
|
+
};
|
|
6313
|
+
UNAUTHORIZED: {};
|
|
6314
|
+
FORBIDDEN: {
|
|
6315
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6316
|
+
permission: z.ZodOptional<z.ZodString>;
|
|
6317
|
+
}, z.core.$strip>>;
|
|
6318
|
+
};
|
|
6319
|
+
NOT_FOUND: {};
|
|
6320
|
+
CONFLICT: {
|
|
6321
|
+
data: z.ZodOptional<z.ZodObject<{
|
|
6322
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
6323
|
+
}, z.core.$strip>>;
|
|
6324
|
+
};
|
|
6325
|
+
RATE_LIMITED: {};
|
|
6326
|
+
MODULE_DISABLED: {
|
|
6327
|
+
data: z.ZodObject<{
|
|
6328
|
+
module: z.ZodString;
|
|
6329
|
+
}, z.core.$strip>;
|
|
6330
|
+
};
|
|
6331
|
+
}>, Record<never, never>>;
|
|
6332
|
+
};
|
|
5913
6333
|
privacy: {
|
|
5914
6334
|
/**
|
|
5915
6335
|
* Everything HR holds about one person, in one response.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/contract/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/contract/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAkGvB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4BnB;;;;;;WAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAqCH,0FAA0F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyD1F;;;;;WAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAkDD,6EAA6E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAkG/E,0FAA0F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyB1F;;;;;;WAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA6GD;;;eAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAiCH;;;;;;eAMG;;;;;;;;;;;;;;;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"}
|
package/dist/contract/router.js
CHANGED
|
@@ -6,9 +6,25 @@ import { DayPart, LeaveBalance, LeaveLedgerEntry, LeaveRequest, LeaveSimulation,
|
|
|
6
6
|
import { Calendar, CalendarDayKind, CostCenter, CountryCode, CustomFieldDef, Employment, EmploymentType, IsoDate, LegalEntity, Office, OfficeAssignment, OfficeKind, OrgUnit, Person, PersonDocument, PersonResolution, PersonSensitive, PersonStatus, Position, RegionCode, ResolvedCalendarDay, TimeZone, WorkingWeek, } from './models.js';
|
|
7
7
|
import { AccrualPreview, Period, Policy, PolicyAssignment, PolicyKind, PolicySubjectKind, ResolvedPolicy, } from './policies.js';
|
|
8
8
|
import { ErasureReport, HrRetention, RetentionSettings, SensitiveAccess, SubjectAccessBundle, } from './privacy.js';
|
|
9
|
+
import { AbsenceReport, AttendanceSummaryReport, LeaveBalanceReport, OvertimeReport, ReportSliceBy, } from './reports.js';
|
|
9
10
|
const ws = z.object({ workspaceId: WorkspaceId });
|
|
10
11
|
const t = ['hr'];
|
|
11
12
|
const ok = z.object({ ok: z.literal(true) });
|
|
13
|
+
/**
|
|
14
|
+
* What every report takes: a range, a slice and how many rows to draw.
|
|
15
|
+
*
|
|
16
|
+
* `limit` bounds the rows, never the figures — `totals` and `population` are computed over everyone
|
|
17
|
+
* the slice covers and `truncated` says when the rows are the top of a longer list. A headline that
|
|
18
|
+
* silently described only the first page would be the exact defect these reports exist to avoid.
|
|
19
|
+
*/
|
|
20
|
+
const reportInput = ws.extend({
|
|
21
|
+
from: IsoDate,
|
|
22
|
+
to: IsoDate,
|
|
23
|
+
by: ReportSliceBy.default('workspace'),
|
|
24
|
+
/** Required by `office` and `legal_entity`, ignored by `workspace`. */
|
|
25
|
+
sliceId: z.uuid().optional(),
|
|
26
|
+
limit: z.number().int().min(1).max(1000).default(100),
|
|
27
|
+
});
|
|
12
28
|
export const hrContract = {
|
|
13
29
|
// ---------------------------------------------------------------- people
|
|
14
30
|
people: {
|
|
@@ -1066,6 +1082,87 @@ export const hrContract = {
|
|
|
1066
1082
|
* nobody by default and ships in the same change as these — see `privacy.ts` for why there is one
|
|
1067
1083
|
* key rather than four, and why none of this is a capability.
|
|
1068
1084
|
*/
|
|
1085
|
+
// ---------------------------------------------------------------- reports
|
|
1086
|
+
/**
|
|
1087
|
+
* Four aggregates, and one rule that decides all four: **a report may not answer a question its
|
|
1088
|
+
* row-level procedure would refuse, and may not narrow below what that procedure already
|
|
1089
|
+
* returns.**
|
|
1090
|
+
*
|
|
1091
|
+
* So each of these costs `hr.report.view` *and* the key that already guards the rows it sums —
|
|
1092
|
+
* `hr.attendance.view_team`, which is what reading a whole office's day sheets costs on
|
|
1093
|
+
* `attendance.days.list`, or `hr.leave.view_team`, which is what reading somebody else's balance
|
|
1094
|
+
* costs on `leave.balance.get`. A reader holding neither gets nothing: not a one-row self-report,
|
|
1095
|
+
* because a reports menu that quietly collapses to your own attendance is a menu entry that lies
|
|
1096
|
+
* about what it is, and your own attendance is already the attendance page.
|
|
1097
|
+
*
|
|
1098
|
+
* The population is **not** intersected with `HrAccessService.visiblePersonIds`. That service
|
|
1099
|
+
* narrows *fields* rather than rows — it withholds `personalEmail`, `phone`, `hiredOn` and
|
|
1100
|
+
* `terminatedOn`, none of which any report reads — and intersecting on it would produce the worst
|
|
1101
|
+
* outcome available here: two managers reading different totals under the same title, with
|
|
1102
|
+
* nothing on the page to say so.
|
|
1103
|
+
*/
|
|
1104
|
+
reports: {
|
|
1105
|
+
/**
|
|
1106
|
+
* Scheduled against worked, per person, over a range.
|
|
1107
|
+
*
|
|
1108
|
+
* Built from `attendance_days` and never from `punches`: punches are raw and append-only, a
|
|
1109
|
+
* voided punch survives beside its correction, and summing them double-counts every fix. The
|
|
1110
|
+
* day sheet is the projection those punches produce.
|
|
1111
|
+
*/
|
|
1112
|
+
attendance: baseContract
|
|
1113
|
+
.route({ method: 'GET', path: '/reports/attendance', tags: t })
|
|
1114
|
+
.input(reportInput)
|
|
1115
|
+
.output(AttendanceSummaryReport),
|
|
1116
|
+
/**
|
|
1117
|
+
* Overtime, and how much of it an annual ceiling would not take.
|
|
1118
|
+
*
|
|
1119
|
+
* `beyondCapMinutes` is null where no ceiling was in force — summed as a nullable column rather
|
|
1120
|
+
* than coalesced, so "no ceiling applied to these days" and "a ceiling applied and nothing
|
|
1121
|
+
* passed it" stay different answers. No projection: there is no "at this rate you will pass the
|
|
1122
|
+
* ceiling in November", because that needs a policy that may not exist.
|
|
1123
|
+
*/
|
|
1124
|
+
overtime: baseContract
|
|
1125
|
+
.route({ method: 'GET', path: '/reports/overtime', tags: t })
|
|
1126
|
+
.input(reportInput)
|
|
1127
|
+
.output(OvertimeReport),
|
|
1128
|
+
/**
|
|
1129
|
+
* Expected working days, minus days worked, minus approved leave.
|
|
1130
|
+
*
|
|
1131
|
+
* **Never `status = 'absent'`.** `attendance_days` has a row only where somebody punched — no
|
|
1132
|
+
* writer creates one for a day nobody clocked in on — so counting absent rows reports near-zero
|
|
1133
|
+
* absence everywhere and looks entirely healthy while doing it. The denominator comes from the
|
|
1134
|
+
* calendar instead, and a person the module cannot build one for lands in a named row rather
|
|
1135
|
+
* than being counted as present.
|
|
1136
|
+
*
|
|
1137
|
+
* Held to `MAX_SLICED_REPORT_DAYS` whether it is sliced or not: every person's expectation is
|
|
1138
|
+
* their office's calendar on each day, which is a ladder walk per day.
|
|
1139
|
+
*/
|
|
1140
|
+
absence: baseContract
|
|
1141
|
+
.route({ method: 'GET', path: '/reports/absence', tags: t })
|
|
1142
|
+
.input(reportInput)
|
|
1143
|
+
.output(AbsenceReport),
|
|
1144
|
+
/**
|
|
1145
|
+
* Every balance in the population, per leave type, for one entitlement year.
|
|
1146
|
+
*
|
|
1147
|
+
* A balance is a position rather than a per-day quantity, so it is attributed as of one date —
|
|
1148
|
+
* `asOf`, defaulting to today — and the response says so. Summed from `leave_ledger`, never
|
|
1149
|
+
* from `leave_balance_cursor`: the cursor exists to be locked, and a cache that is also the
|
|
1150
|
+
* source of truth is one that eventually disagrees with it.
|
|
1151
|
+
*/
|
|
1152
|
+
leaveBalance: baseContract
|
|
1153
|
+
.route({ method: 'GET', path: '/reports/leave-balance', tags: t })
|
|
1154
|
+
.input(ws.extend({
|
|
1155
|
+
/** Defaults to the year `asOf` falls in. */
|
|
1156
|
+
periodYear: z.number().int().min(1970).max(2200).optional(),
|
|
1157
|
+
/** Which day decides who is in the slice. Defaults to today. */
|
|
1158
|
+
asOf: IsoDate.optional(),
|
|
1159
|
+
by: ReportSliceBy.default('workspace'),
|
|
1160
|
+
sliceId: z.uuid().optional(),
|
|
1161
|
+
limit: z.number().int().min(1).max(1000).default(100),
|
|
1162
|
+
}))
|
|
1163
|
+
.output(LeaveBalanceReport),
|
|
1164
|
+
},
|
|
1165
|
+
// ---------------------------------------------------------------- privacy
|
|
1069
1166
|
privacy: {
|
|
1070
1167
|
/**
|
|
1071
1168
|
* Everything HR holds about one person, in one response.
|