@classytic/payroll 1.0.2 → 2.3.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.
Potentially problematic release.
This version of @classytic/payroll might be problematic. Click here for more details.
- package/README.md +2599 -574
- package/dist/calculators/index.d.ts +433 -0
- package/dist/calculators/index.js +283 -0
- package/dist/calculators/index.js.map +1 -0
- package/dist/core/index.d.ts +314 -0
- package/dist/core/index.js +1166 -0
- package/dist/core/index.js.map +1 -0
- package/dist/employee-identity-DXhgOgXE.d.ts +473 -0
- package/dist/employee.factory-BlZqhiCk.d.ts +189 -0
- package/dist/idempotency-Cw2CWicb.d.ts +52 -0
- package/dist/index.d.ts +902 -0
- package/dist/index.js +9108 -0
- package/dist/index.js.map +1 -0
- package/dist/jurisdiction/index.d.ts +660 -0
- package/dist/jurisdiction/index.js +533 -0
- package/dist/jurisdiction/index.js.map +1 -0
- package/dist/payroll.d.ts +429 -0
- package/dist/payroll.js +5192 -0
- package/dist/payroll.js.map +1 -0
- package/dist/schemas/index.d.ts +3262 -0
- package/dist/schemas/index.js +780 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/services/index.d.ts +582 -0
- package/dist/services/index.js +2172 -0
- package/dist/services/index.js.map +1 -0
- package/dist/shift-compliance/index.d.ts +1171 -0
- package/dist/shift-compliance/index.js +1479 -0
- package/dist/shift-compliance/index.js.map +1 -0
- package/dist/types-BN3K_Uhr.d.ts +1842 -0
- package/dist/utils/index.d.ts +893 -0
- package/dist/utils/index.js +1515 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +72 -37
- package/dist/types/config.d.ts +0 -162
- package/dist/types/core/compensation.manager.d.ts +0 -54
- package/dist/types/core/employment.manager.d.ts +0 -49
- package/dist/types/core/payroll.manager.d.ts +0 -60
- package/dist/types/enums.d.ts +0 -117
- package/dist/types/factories/compensation.factory.d.ts +0 -196
- package/dist/types/factories/employee.factory.d.ts +0 -149
- package/dist/types/factories/payroll.factory.d.ts +0 -319
- package/dist/types/hrm.orchestrator.d.ts +0 -47
- package/dist/types/index.d.ts +0 -20
- package/dist/types/init.d.ts +0 -30
- package/dist/types/models/payroll-record.model.d.ts +0 -3
- package/dist/types/plugins/employee.plugin.d.ts +0 -2
- package/dist/types/schemas/employment.schema.d.ts +0 -959
- package/dist/types/services/compensation.service.d.ts +0 -94
- package/dist/types/services/employee.service.d.ts +0 -28
- package/dist/types/services/payroll.service.d.ts +0 -30
- package/dist/types/utils/calculation.utils.d.ts +0 -26
- package/dist/types/utils/date.utils.d.ts +0 -35
- package/dist/types/utils/logger.d.ts +0 -12
- package/dist/types/utils/query-builders.d.ts +0 -83
- package/dist/types/utils/validation.utils.d.ts +0 -33
- package/payroll.d.ts +0 -241
- package/src/config.js +0 -177
- package/src/core/compensation.manager.js +0 -242
- package/src/core/employment.manager.js +0 -224
- package/src/core/payroll.manager.js +0 -499
- package/src/enums.js +0 -141
- package/src/factories/compensation.factory.js +0 -198
- package/src/factories/employee.factory.js +0 -173
- package/src/factories/payroll.factory.js +0 -413
- package/src/hrm.orchestrator.js +0 -139
- package/src/index.js +0 -172
- package/src/init.js +0 -62
- package/src/models/payroll-record.model.js +0 -126
- package/src/plugins/employee.plugin.js +0 -164
- package/src/schemas/employment.schema.js +0 -126
- package/src/services/compensation.service.js +0 -231
- package/src/services/employee.service.js +0 -162
- package/src/services/payroll.service.js +0 -213
- package/src/utils/calculation.utils.js +0 -91
- package/src/utils/date.utils.js +0 -120
- package/src/utils/logger.js +0 -36
- package/src/utils/query-builders.js +0 -185
- package/src/utils/validation.utils.js +0 -122
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { aF as LeaveType, aG as WorkingDaysOptions, aH as LeaveBalance, aI as LeaveSummaryResult, aJ as LeaveInitConfig, E as EmployeeDocument, O as ObjectIdLike, g as OperationContext } from './types-BN3K_Uhr.js';
|
|
2
|
+
import { Model, Types } from 'mongoose';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @classytic/payroll - Leave Utilities
|
|
6
|
+
*
|
|
7
|
+
* Pure, composable leave calculation functions
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Default leave allocations by type (days per year) */
|
|
11
|
+
declare const DEFAULT_LEAVE_ALLOCATIONS: Record<LeaveType, number>;
|
|
12
|
+
/** Default carry-over limits by type (days) */
|
|
13
|
+
declare const DEFAULT_CARRY_OVER: Record<LeaveType, number>;
|
|
14
|
+
/**
|
|
15
|
+
* Calculate working days between two dates
|
|
16
|
+
* Excludes weekends and optionally holidays
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // March 2024: Get working days for a week
|
|
20
|
+
* const days = calculateLeaveDays(
|
|
21
|
+
* new Date('2024-03-01'),
|
|
22
|
+
* new Date('2024-03-08'),
|
|
23
|
+
* { holidays: [new Date('2024-03-05')] }
|
|
24
|
+
* );
|
|
25
|
+
*/
|
|
26
|
+
declare function calculateLeaveDays(startDate: Date, endDate: Date, options?: WorkingDaysOptions): number;
|
|
27
|
+
/**
|
|
28
|
+
* Check if employee has sufficient leave balance
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* if (hasLeaveBalance(employee, 'annual', 5)) {
|
|
32
|
+
* // Can request 5 days annual leave
|
|
33
|
+
* }
|
|
34
|
+
*/
|
|
35
|
+
declare function hasLeaveBalance(employee: {
|
|
36
|
+
leaveBalances?: LeaveBalance[];
|
|
37
|
+
}, type: LeaveType, days: number, year?: number): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Get leave balance for a specific type
|
|
40
|
+
*/
|
|
41
|
+
declare function getLeaveBalance(employee: {
|
|
42
|
+
leaveBalances?: LeaveBalance[];
|
|
43
|
+
}, type: LeaveType, year?: number): LeaveBalance | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Get all leave balances for a year
|
|
46
|
+
*/
|
|
47
|
+
declare function getLeaveBalances(employee: {
|
|
48
|
+
leaveBalances?: LeaveBalance[];
|
|
49
|
+
}, year?: number): LeaveBalance[];
|
|
50
|
+
/**
|
|
51
|
+
* Calculate available days for a leave type
|
|
52
|
+
*/
|
|
53
|
+
declare function getAvailableDays(employee: {
|
|
54
|
+
leaveBalances?: LeaveBalance[];
|
|
55
|
+
}, type: LeaveType, year?: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Get comprehensive leave summary for an employee
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const summary = getLeaveSummary(employee, 2024);
|
|
61
|
+
* console.log(`Available: ${summary.totalAvailable} days`);
|
|
62
|
+
* console.log(`Annual: ${summary.byType.annual?.available || 0} days`);
|
|
63
|
+
*/
|
|
64
|
+
declare function getLeaveSummary(employee: {
|
|
65
|
+
leaveBalances?: LeaveBalance[];
|
|
66
|
+
}, year?: number): LeaveSummaryResult;
|
|
67
|
+
/**
|
|
68
|
+
* Initialize leave balances for a new employee
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // Full allocation for employee hired Jan 1st
|
|
72
|
+
* const balances = initializeLeaveBalances(new Date('2024-01-01'));
|
|
73
|
+
*
|
|
74
|
+
* // Pro-rated for mid-year hire
|
|
75
|
+
* const balances = initializeLeaveBalances(new Date('2024-07-01'), {
|
|
76
|
+
* proRateNewHires: true,
|
|
77
|
+
* });
|
|
78
|
+
*/
|
|
79
|
+
declare function initializeLeaveBalances(hireDate: Date, config?: LeaveInitConfig, year?: number): LeaveBalance[];
|
|
80
|
+
/**
|
|
81
|
+
* Calculate prorated allocation for mid-year hire
|
|
82
|
+
*/
|
|
83
|
+
declare function proRateAllocation(fullAllocation: number, hireDate: Date, fiscalYearStartMonth?: number, year?: number): number;
|
|
84
|
+
/**
|
|
85
|
+
* Calculate unpaid leave deduction for payroll
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const deduction = calculateUnpaidLeaveDeduction(100000, 5, 22);
|
|
89
|
+
* // Daily rate: 100000 / 22 = 4545
|
|
90
|
+
* // Deduction: 4545 * 5 = 22727
|
|
91
|
+
*/
|
|
92
|
+
declare function calculateUnpaidLeaveDeduction(baseSalary: number, unpaidDays: number, workingDaysInMonth: number): number;
|
|
93
|
+
/**
|
|
94
|
+
* Get total unpaid leave days from a list of leave requests
|
|
95
|
+
*/
|
|
96
|
+
declare function getUnpaidLeaveDays(leaveRequests: Array<{
|
|
97
|
+
type: LeaveType;
|
|
98
|
+
days: number;
|
|
99
|
+
status: string;
|
|
100
|
+
}>, status?: string): number;
|
|
101
|
+
/**
|
|
102
|
+
* Calculate carry-over balances for year-end
|
|
103
|
+
*
|
|
104
|
+
* Creates new year balances for ALL leave types from the current year.
|
|
105
|
+
* Types with carry-over limits get their unused balance carried forward.
|
|
106
|
+
* Types without carry-over (or 0 limit) start fresh with 0 carriedOver.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* // With default allocations - creates balances for all types
|
|
110
|
+
* const newBalances = calculateCarryOver(employee.leaveBalances, {
|
|
111
|
+
* annual: 5,
|
|
112
|
+
* compensatory: 3,
|
|
113
|
+
* });
|
|
114
|
+
* // Merge with existing (don't replace entirely)
|
|
115
|
+
* employee.leaveBalances.push(...newBalances);
|
|
116
|
+
*
|
|
117
|
+
* // With custom allocations (org-specific entitlements)
|
|
118
|
+
* const newBalances = calculateCarryOver(employee.leaveBalances, {
|
|
119
|
+
* annual: 5,
|
|
120
|
+
* compensatory: 3,
|
|
121
|
+
* }, {
|
|
122
|
+
* annual: 25, // Custom org policy
|
|
123
|
+
* sick: 15,
|
|
124
|
+
* });
|
|
125
|
+
*/
|
|
126
|
+
declare function calculateCarryOver(balances: LeaveBalance[], maxCarryOver?: Partial<Record<LeaveType, number>>, newYearAllocations?: Partial<Record<LeaveType, number>>): LeaveBalance[];
|
|
127
|
+
/**
|
|
128
|
+
* Add accrued leave to balances
|
|
129
|
+
*/
|
|
130
|
+
declare function accrueLeaveToBalance(balances: LeaveBalance[], type: LeaveType, amount: number, year?: number): LeaveBalance[];
|
|
131
|
+
declare const _default: {
|
|
132
|
+
DEFAULT_LEAVE_ALLOCATIONS: Record<LeaveType, number>;
|
|
133
|
+
DEFAULT_CARRY_OVER: Record<LeaveType, number>;
|
|
134
|
+
calculateLeaveDays: typeof calculateLeaveDays;
|
|
135
|
+
hasLeaveBalance: typeof hasLeaveBalance;
|
|
136
|
+
getLeaveBalance: typeof getLeaveBalance;
|
|
137
|
+
getLeaveBalances: typeof getLeaveBalances;
|
|
138
|
+
getAvailableDays: typeof getAvailableDays;
|
|
139
|
+
getLeaveSummary: typeof getLeaveSummary;
|
|
140
|
+
initializeLeaveBalances: typeof initializeLeaveBalances;
|
|
141
|
+
proRateAllocation: typeof proRateAllocation;
|
|
142
|
+
calculateUnpaidLeaveDeduction: typeof calculateUnpaidLeaveDeduction;
|
|
143
|
+
getUnpaidLeaveDays: typeof getUnpaidLeaveDays;
|
|
144
|
+
calculateCarryOver: typeof calculateCarryOver;
|
|
145
|
+
accrueLeaveToBalance: typeof accrueLeaveToBalance;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @classytic/payroll - Secure Employee Lookup
|
|
150
|
+
*
|
|
151
|
+
* Multi-tenant safe employee lookup utilities
|
|
152
|
+
* Enforces organizationId isolation on all queries
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Employee ID mode for explicit disambiguation
|
|
157
|
+
*
|
|
158
|
+
* Controls how the employeeId parameter is interpreted:
|
|
159
|
+
* - 'auto': Auto-detect via isValidObjectId() (default)
|
|
160
|
+
* - 'objectId': Force treat as MongoDB _id (ObjectId)
|
|
161
|
+
* - 'businessId': Force treat as business employeeId string
|
|
162
|
+
*
|
|
163
|
+
* @since v2.3.0
|
|
164
|
+
*/
|
|
165
|
+
type EmployeeIdMode = 'auto' | 'objectId' | 'businessId';
|
|
166
|
+
/**
|
|
167
|
+
* Lookup options for secure employee queries
|
|
168
|
+
*/
|
|
169
|
+
interface SecureEmployeeLookupOptions {
|
|
170
|
+
/**
|
|
171
|
+
* Organization ID (required for multi-tenant isolation)
|
|
172
|
+
* Can be omitted only in single-tenant mode with auto-inject
|
|
173
|
+
*/
|
|
174
|
+
organizationId?: ObjectIdLike;
|
|
175
|
+
/**
|
|
176
|
+
* Employee's Mongoose _id (ObjectId)
|
|
177
|
+
* Use this when you have the database ID
|
|
178
|
+
* Takes priority over employeeId if both are provided
|
|
179
|
+
*/
|
|
180
|
+
_id?: ObjectIdLike;
|
|
181
|
+
/**
|
|
182
|
+
* Employee identifier (supports both formats):
|
|
183
|
+
* - ObjectId: employee._id (MongoDB document ID)
|
|
184
|
+
* - String: "EMP-001" (business identifier)
|
|
185
|
+
*
|
|
186
|
+
* System auto-detects type by default:
|
|
187
|
+
* - If valid ObjectId → queries by _id field
|
|
188
|
+
* - If string → queries by employeeId field
|
|
189
|
+
*
|
|
190
|
+
* Use employeeIdType to override auto-detection if your business
|
|
191
|
+
* employeeIds look like ObjectIds (24 hex characters).
|
|
192
|
+
*
|
|
193
|
+
* Note: If _id parameter is also provided, _id takes priority
|
|
194
|
+
*/
|
|
195
|
+
employeeId?: ObjectIdLike | string;
|
|
196
|
+
/**
|
|
197
|
+
* Explicit mode hint for employeeId disambiguation
|
|
198
|
+
*
|
|
199
|
+
* - 'auto' (default): Auto-detect via isValidObjectId()
|
|
200
|
+
* - 'objectId': Force treat as MongoDB _id (ObjectId)
|
|
201
|
+
* - 'businessId': Force treat as business employeeId string
|
|
202
|
+
*
|
|
203
|
+
* Use 'businessId' if your employeeIds are 24-hex strings like
|
|
204
|
+
* "507f1f77bcf86cd799439011" to prevent ObjectId collision.
|
|
205
|
+
*
|
|
206
|
+
* @default 'auto'
|
|
207
|
+
* @since v2.3.0
|
|
208
|
+
*/
|
|
209
|
+
employeeIdMode?: EmployeeIdMode;
|
|
210
|
+
/**
|
|
211
|
+
* User ID reference (optional)
|
|
212
|
+
*/
|
|
213
|
+
userId?: ObjectIdLike;
|
|
214
|
+
/**
|
|
215
|
+
* Email address (optional)
|
|
216
|
+
*/
|
|
217
|
+
email?: string;
|
|
218
|
+
/**
|
|
219
|
+
* Mongoose session for transactions
|
|
220
|
+
*/
|
|
221
|
+
session?: any;
|
|
222
|
+
/**
|
|
223
|
+
* Fields to populate
|
|
224
|
+
*/
|
|
225
|
+
populate?: string | string[];
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Securely find an employee by various identifiers
|
|
229
|
+
* ALWAYS enforces organizationId for multi-tenant isolation
|
|
230
|
+
*
|
|
231
|
+
* @param model - Employee model
|
|
232
|
+
* @param options - Lookup options
|
|
233
|
+
* @returns Employee document or throws EmployeeNotFoundError
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* // By ObjectId _id
|
|
237
|
+
* const emp = await findEmployeeSecure(Employee, {
|
|
238
|
+
* _id: employee._id,
|
|
239
|
+
* organizationId: org._id
|
|
240
|
+
* });
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* // By string employeeId
|
|
244
|
+
* const emp = await findEmployeeSecure(Employee, {
|
|
245
|
+
* employeeId: "EMP-001",
|
|
246
|
+
* organizationId: org._id
|
|
247
|
+
* });
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* // By 24-hex business employeeId (force businessId mode)
|
|
251
|
+
* const emp = await findEmployeeSecure(Employee, {
|
|
252
|
+
* employeeId: "507f1f77bcf86cd799439011", // Looks like ObjectId!
|
|
253
|
+
* employeeIdMode: 'businessId', // Force treat as business ID
|
|
254
|
+
* organizationId: org._id
|
|
255
|
+
* });
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* // By userId
|
|
259
|
+
* const emp = await findEmployeeSecure(Employee, {
|
|
260
|
+
* userId: user._id,
|
|
261
|
+
* organizationId: org._id
|
|
262
|
+
* });
|
|
263
|
+
*/
|
|
264
|
+
declare function findEmployeeSecure<T extends EmployeeDocument>(model: Model<T>, options: SecureEmployeeLookupOptions): Promise<T>;
|
|
265
|
+
/**
|
|
266
|
+
* Check if an employee exists securely (with org isolation)
|
|
267
|
+
*
|
|
268
|
+
* @param model - Employee model
|
|
269
|
+
* @param options - Lookup options
|
|
270
|
+
* @returns true if employee exists, false otherwise
|
|
271
|
+
*/
|
|
272
|
+
declare function employeeExistsSecure<T extends EmployeeDocument>(model: Model<T>, options: SecureEmployeeLookupOptions): Promise<boolean>;
|
|
273
|
+
/**
|
|
274
|
+
* Find multiple employees securely (with org isolation)
|
|
275
|
+
*
|
|
276
|
+
* @param model - Employee model
|
|
277
|
+
* @param options - Query options
|
|
278
|
+
* @returns Array of employee documents
|
|
279
|
+
*/
|
|
280
|
+
declare function findEmployeesSecure<T extends EmployeeDocument>(model: Model<T>, options: {
|
|
281
|
+
organizationId: ObjectIdLike;
|
|
282
|
+
filter?: Record<string, any>;
|
|
283
|
+
session?: any;
|
|
284
|
+
limit?: number;
|
|
285
|
+
skip?: number;
|
|
286
|
+
sort?: Record<string, 1 | -1>;
|
|
287
|
+
}): Promise<T[]>;
|
|
288
|
+
/**
|
|
289
|
+
* Validate organizationId is provided (unless single-tenant with auto-inject)
|
|
290
|
+
*
|
|
291
|
+
* @param organizationId - Organization ID to validate
|
|
292
|
+
* @param operation - Operation name for error message
|
|
293
|
+
* @throws Error if organizationId is missing
|
|
294
|
+
*/
|
|
295
|
+
declare function requireOrganizationId(organizationId: ObjectIdLike | undefined, operation: string): void;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* @classytic/payroll - Organization Resolution Utility
|
|
299
|
+
*
|
|
300
|
+
* Smart organization ID resolution with priority chain:
|
|
301
|
+
* 1. Explicit parameter (highest priority)
|
|
302
|
+
* 2. Context.organizationId (from middleware/auth)
|
|
303
|
+
* 3. Single-tenant config (if autoInject enabled)
|
|
304
|
+
* 4. Error (if none found in multi-tenant mode)
|
|
305
|
+
*/
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Container-like interface for organization resolution
|
|
309
|
+
* Only requires the methods we need, allowing any generic Container type
|
|
310
|
+
*/
|
|
311
|
+
interface ContainerLike {
|
|
312
|
+
isSingleTenant(): boolean;
|
|
313
|
+
getSingleTenantConfig(): {
|
|
314
|
+
organizationId?: any;
|
|
315
|
+
autoInject?: boolean;
|
|
316
|
+
} | null;
|
|
317
|
+
getOrganizationId(): string | null;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Organization resolution parameters
|
|
321
|
+
*/
|
|
322
|
+
interface ResolveOrganizationIdParams {
|
|
323
|
+
/**
|
|
324
|
+
* Explicitly provided organizationId (highest priority)
|
|
325
|
+
*/
|
|
326
|
+
explicit?: ObjectIdLike;
|
|
327
|
+
/**
|
|
328
|
+
* Operation context with possible organizationId
|
|
329
|
+
*/
|
|
330
|
+
context?: OperationContext;
|
|
331
|
+
/**
|
|
332
|
+
* Container for single-tenant config access
|
|
333
|
+
* Accepts any Container with any generic types
|
|
334
|
+
*/
|
|
335
|
+
container?: ContainerLike;
|
|
336
|
+
/**
|
|
337
|
+
* Operation name for error messages
|
|
338
|
+
*/
|
|
339
|
+
operation?: string;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Smart organization ID resolution
|
|
343
|
+
*
|
|
344
|
+
* Priority Chain:
|
|
345
|
+
* 1. Explicit param (highest)
|
|
346
|
+
* 2. Context.organizationId (middleware/auth)
|
|
347
|
+
* 3. Single-tenant config (if autoInject enabled)
|
|
348
|
+
* 4. Error (if none found)
|
|
349
|
+
*
|
|
350
|
+
* @param params - Resolution parameters
|
|
351
|
+
* @returns Resolved ObjectId
|
|
352
|
+
* @throws Error if organizationId cannot be resolved
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* // Explicit param wins
|
|
356
|
+
* const orgId = resolveOrganizationId({
|
|
357
|
+
* explicit: org._id,
|
|
358
|
+
* context: { organizationId: other._id },
|
|
359
|
+
* operation: 'processSalary'
|
|
360
|
+
* });
|
|
361
|
+
* // Returns: org._id
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* // Context fallback
|
|
365
|
+
* const orgId = resolveOrganizationId({
|
|
366
|
+
* context: { organizationId: org._id },
|
|
367
|
+
* operation: 'processSalary'
|
|
368
|
+
* });
|
|
369
|
+
* // Returns: org._id from context
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* // Single-tenant auto-inject
|
|
373
|
+
* const orgId = resolveOrganizationId({
|
|
374
|
+
* container: singleTenantContainer,
|
|
375
|
+
* operation: 'processSalary'
|
|
376
|
+
* });
|
|
377
|
+
* // Returns: organizationId from container config
|
|
378
|
+
*/
|
|
379
|
+
declare function resolveOrganizationId(params: ResolveOrganizationIdParams): Types.ObjectId;
|
|
380
|
+
/**
|
|
381
|
+
* Validate that organizationId is present
|
|
382
|
+
*
|
|
383
|
+
* @param organizationId - Organization ID to validate
|
|
384
|
+
* @param operation - Operation name for error message
|
|
385
|
+
* @returns ObjectId if valid
|
|
386
|
+
* @throws Error if organizationId is missing or invalid
|
|
387
|
+
*/
|
|
388
|
+
declare function validateOrganizationId(organizationId: ObjectIdLike | undefined, operation: string): Types.ObjectId;
|
|
389
|
+
/**
|
|
390
|
+
* Try to resolve organizationId without throwing
|
|
391
|
+
*
|
|
392
|
+
* @param params - Resolution parameters
|
|
393
|
+
* @returns ObjectId if resolved, null otherwise
|
|
394
|
+
*/
|
|
395
|
+
declare function tryResolveOrganizationId(params: ResolveOrganizationIdParams): Types.ObjectId | null;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* @classytic/payroll - Employee Identity Helper
|
|
399
|
+
*
|
|
400
|
+
* Dual identity system for employee lookups:
|
|
401
|
+
* - MongoDB ObjectId (_id field)
|
|
402
|
+
* - Business string identifier (employeeId field like "EMP-001")
|
|
403
|
+
*
|
|
404
|
+
* Auto-detects identifier type and builds appropriate queries
|
|
405
|
+
*/
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Employee identifier type
|
|
409
|
+
*/
|
|
410
|
+
type EmployeeIdType = 'objectId' | 'string';
|
|
411
|
+
/**
|
|
412
|
+
* Employee query filter
|
|
413
|
+
*/
|
|
414
|
+
interface EmployeeQueryFilter {
|
|
415
|
+
_id?: Types.ObjectId;
|
|
416
|
+
employeeId?: string;
|
|
417
|
+
organizationId: Types.ObjectId;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Detect if employeeId is ObjectId or string
|
|
421
|
+
*
|
|
422
|
+
* @param employeeId - Employee identifier (ObjectId or string)
|
|
423
|
+
* @returns 'objectId' if valid ObjectId, 'string' otherwise
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* detectEmployeeIdType(employee._id)
|
|
427
|
+
* // Returns: 'objectId'
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* detectEmployeeIdType("EMP-001")
|
|
431
|
+
* // Returns: 'string'
|
|
432
|
+
*/
|
|
433
|
+
declare function detectEmployeeIdType(employeeId: ObjectIdLike | string): EmployeeIdType;
|
|
434
|
+
/**
|
|
435
|
+
* Normalize employee identifier to consistent format
|
|
436
|
+
*
|
|
437
|
+
* Converts ObjectIdLike to ObjectId, keeps strings as-is
|
|
438
|
+
*
|
|
439
|
+
* @param employeeId - Employee identifier
|
|
440
|
+
* @returns Normalized ObjectId or string
|
|
441
|
+
*/
|
|
442
|
+
declare function normalizeEmployeeId(employeeId: ObjectIdLike | string): Types.ObjectId | string;
|
|
443
|
+
/**
|
|
444
|
+
* Check if value is a string employee ID (not ObjectId)
|
|
445
|
+
*
|
|
446
|
+
* @param value - Value to check
|
|
447
|
+
* @returns true if string employeeId, false if ObjectId
|
|
448
|
+
*/
|
|
449
|
+
declare function isStringEmployeeId(value: unknown): value is string;
|
|
450
|
+
/**
|
|
451
|
+
* Check if value is an ObjectId employee identifier
|
|
452
|
+
*
|
|
453
|
+
* @param value - Value to check
|
|
454
|
+
* @returns true if ObjectId, false otherwise
|
|
455
|
+
*/
|
|
456
|
+
declare function isObjectIdEmployeeId(value: unknown): value is ObjectIdLike;
|
|
457
|
+
/**
|
|
458
|
+
* Format employee identifier for display
|
|
459
|
+
*
|
|
460
|
+
* @param employeeId - Employee identifier
|
|
461
|
+
* @returns Human-readable string
|
|
462
|
+
*
|
|
463
|
+
* @example
|
|
464
|
+
* formatEmployeeId(employee._id)
|
|
465
|
+
* // Returns: "_id=507f1f77bcf86cd799439011"
|
|
466
|
+
*
|
|
467
|
+
* @example
|
|
468
|
+
* formatEmployeeId("EMP-001")
|
|
469
|
+
* // Returns: "employeeId=EMP-001"
|
|
470
|
+
*/
|
|
471
|
+
declare function formatEmployeeId(employeeId: ObjectIdLike | string): string;
|
|
472
|
+
|
|
473
|
+
export { type EmployeeQueryFilter as A, type ContainerLike as C, DEFAULT_LEAVE_ALLOCATIONS as D, type EmployeeIdMode as E, type ResolveOrganizationIdParams as R, type SecureEmployeeLookupOptions as S, _default as _, DEFAULT_CARRY_OVER as a, getLeaveBalances as b, calculateLeaveDays as c, getAvailableDays as d, getLeaveSummary as e, calculateUnpaidLeaveDeduction as f, getLeaveBalance as g, hasLeaveBalance as h, initializeLeaveBalances as i, getUnpaidLeaveDays as j, calculateCarryOver as k, accrueLeaveToBalance as l, findEmployeeSecure as m, employeeExistsSecure as n, findEmployeesSecure as o, proRateAllocation as p, resolveOrganizationId as q, requireOrganizationId as r, detectEmployeeIdType as s, tryResolveOrganizationId as t, normalizeEmployeeId as u, validateOrganizationId as v, isStringEmployeeId as w, isObjectIdEmployeeId as x, formatEmployeeId as y, type EmployeeIdType as z };
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { O as ObjectIdLike, F as EmploymentType, I as Department, J as WorkSchedule, K as PaymentFrequency, N as Allowance, Q as Deduction, V as BankDetails, z as HRMConfig, X as Compensation, Y as TerminationReason } from './types-BN3K_Uhr.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @classytic/payroll - Employee Factory
|
|
5
|
+
*
|
|
6
|
+
* Clean object creation for employee documents
|
|
7
|
+
* Builder pattern for fluent API
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface CreateEmployeeParams {
|
|
11
|
+
userId?: ObjectIdLike;
|
|
12
|
+
organizationId: ObjectIdLike;
|
|
13
|
+
employment: {
|
|
14
|
+
employeeId?: string;
|
|
15
|
+
email?: string;
|
|
16
|
+
type?: EmploymentType;
|
|
17
|
+
department?: Department | string;
|
|
18
|
+
position: string;
|
|
19
|
+
hireDate?: Date;
|
|
20
|
+
probationMonths?: number;
|
|
21
|
+
workSchedule?: WorkSchedule;
|
|
22
|
+
};
|
|
23
|
+
compensation: {
|
|
24
|
+
baseAmount: number;
|
|
25
|
+
frequency?: PaymentFrequency;
|
|
26
|
+
currency?: string;
|
|
27
|
+
allowances?: Array<Partial<Allowance>>;
|
|
28
|
+
deductions?: Array<Partial<Deduction>>;
|
|
29
|
+
};
|
|
30
|
+
bankDetails?: BankDetails;
|
|
31
|
+
}
|
|
32
|
+
interface EmployeeData {
|
|
33
|
+
userId?: ObjectIdLike;
|
|
34
|
+
email?: string;
|
|
35
|
+
organizationId: ObjectIdLike;
|
|
36
|
+
employeeId: string;
|
|
37
|
+
employmentType: EmploymentType;
|
|
38
|
+
status: 'active';
|
|
39
|
+
department?: Department;
|
|
40
|
+
position: string;
|
|
41
|
+
hireDate: Date;
|
|
42
|
+
probationEndDate: Date | null;
|
|
43
|
+
compensation: Compensation;
|
|
44
|
+
workSchedule: WorkSchedule;
|
|
45
|
+
bankDetails: BankDetails;
|
|
46
|
+
payrollStats: {
|
|
47
|
+
totalPaid: number;
|
|
48
|
+
paymentsThisYear: number;
|
|
49
|
+
averageMonthly: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
interface TerminationData {
|
|
53
|
+
terminatedAt: Date;
|
|
54
|
+
terminationReason: TerminationReason;
|
|
55
|
+
terminationNotes?: string;
|
|
56
|
+
terminatedBy: {
|
|
57
|
+
userId?: ObjectIdLike;
|
|
58
|
+
name?: string;
|
|
59
|
+
role?: string;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
declare class EmployeeFactory {
|
|
63
|
+
/**
|
|
64
|
+
* Create employee data object
|
|
65
|
+
*/
|
|
66
|
+
static create(params: CreateEmployeeParams, config?: HRMConfig): EmployeeData;
|
|
67
|
+
/**
|
|
68
|
+
* Create compensation object
|
|
69
|
+
*/
|
|
70
|
+
static createCompensation(params: {
|
|
71
|
+
baseAmount: number;
|
|
72
|
+
frequency?: PaymentFrequency;
|
|
73
|
+
currency?: string;
|
|
74
|
+
allowances?: Array<Partial<Allowance>>;
|
|
75
|
+
deductions?: Array<Partial<Deduction>>;
|
|
76
|
+
}, config?: HRMConfig): Compensation;
|
|
77
|
+
/**
|
|
78
|
+
* Create allowance object
|
|
79
|
+
*/
|
|
80
|
+
static createAllowance(params: {
|
|
81
|
+
type: Allowance['type'];
|
|
82
|
+
amount: number;
|
|
83
|
+
name?: string;
|
|
84
|
+
isPercentage?: boolean;
|
|
85
|
+
taxable?: boolean;
|
|
86
|
+
recurring?: boolean;
|
|
87
|
+
}): Allowance;
|
|
88
|
+
/**
|
|
89
|
+
* Create deduction object
|
|
90
|
+
*/
|
|
91
|
+
static createDeduction(params: {
|
|
92
|
+
type: Deduction['type'];
|
|
93
|
+
amount: number;
|
|
94
|
+
name?: string;
|
|
95
|
+
isPercentage?: boolean;
|
|
96
|
+
auto?: boolean;
|
|
97
|
+
recurring?: boolean;
|
|
98
|
+
description?: string;
|
|
99
|
+
}): Deduction;
|
|
100
|
+
/**
|
|
101
|
+
* Default work schedule
|
|
102
|
+
*/
|
|
103
|
+
static defaultWorkSchedule(): WorkSchedule;
|
|
104
|
+
/**
|
|
105
|
+
* Create termination data
|
|
106
|
+
*/
|
|
107
|
+
static createTermination(params: {
|
|
108
|
+
reason: TerminationReason;
|
|
109
|
+
date?: Date;
|
|
110
|
+
notes?: string;
|
|
111
|
+
context?: {
|
|
112
|
+
userId?: ObjectIdLike;
|
|
113
|
+
userName?: string;
|
|
114
|
+
userRole?: string;
|
|
115
|
+
};
|
|
116
|
+
}): TerminationData;
|
|
117
|
+
}
|
|
118
|
+
declare class EmployeeBuilder {
|
|
119
|
+
private data;
|
|
120
|
+
/**
|
|
121
|
+
* Set user ID
|
|
122
|
+
*/
|
|
123
|
+
forUser(userId: ObjectIdLike): this;
|
|
124
|
+
/**
|
|
125
|
+
* Set organization ID
|
|
126
|
+
*/
|
|
127
|
+
inOrganization(organizationId: ObjectIdLike): this;
|
|
128
|
+
/**
|
|
129
|
+
* Set employee ID
|
|
130
|
+
*/
|
|
131
|
+
withEmployeeId(employeeId: string): this;
|
|
132
|
+
/**
|
|
133
|
+
* Set department
|
|
134
|
+
*/
|
|
135
|
+
inDepartment(department: Department): this;
|
|
136
|
+
/**
|
|
137
|
+
* Set position
|
|
138
|
+
*/
|
|
139
|
+
asPosition(position: string): this;
|
|
140
|
+
/**
|
|
141
|
+
* Set employment type
|
|
142
|
+
*/
|
|
143
|
+
withEmploymentType(type: EmploymentType): this;
|
|
144
|
+
/**
|
|
145
|
+
* Set hire date
|
|
146
|
+
*/
|
|
147
|
+
hiredOn(date: Date): this;
|
|
148
|
+
/**
|
|
149
|
+
* Set probation period
|
|
150
|
+
*/
|
|
151
|
+
withProbation(months: number): this;
|
|
152
|
+
/**
|
|
153
|
+
* Set work schedule
|
|
154
|
+
*/
|
|
155
|
+
withSchedule(schedule: WorkSchedule): this;
|
|
156
|
+
/**
|
|
157
|
+
* Set base salary
|
|
158
|
+
*/
|
|
159
|
+
withBaseSalary(amount: number, frequency?: PaymentFrequency, currency?: string): this;
|
|
160
|
+
/**
|
|
161
|
+
* Add allowance
|
|
162
|
+
*/
|
|
163
|
+
addAllowance(type: Allowance['type'], amount: number, options?: {
|
|
164
|
+
taxable?: boolean;
|
|
165
|
+
recurring?: boolean;
|
|
166
|
+
}): this;
|
|
167
|
+
/**
|
|
168
|
+
* Add deduction
|
|
169
|
+
*/
|
|
170
|
+
addDeduction(type: Deduction['type'], amount: number, options?: {
|
|
171
|
+
auto?: boolean;
|
|
172
|
+
recurring?: boolean;
|
|
173
|
+
description?: string;
|
|
174
|
+
}): this;
|
|
175
|
+
/**
|
|
176
|
+
* Set bank details
|
|
177
|
+
*/
|
|
178
|
+
withBankDetails(bankDetails: BankDetails): this;
|
|
179
|
+
/**
|
|
180
|
+
* Build employee data
|
|
181
|
+
*/
|
|
182
|
+
build(config?: HRMConfig): EmployeeData;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create new employee builder
|
|
186
|
+
*/
|
|
187
|
+
declare function createEmployee(): EmployeeBuilder;
|
|
188
|
+
|
|
189
|
+
export { type CreateEmployeeParams as C, EmployeeFactory as E, type TerminationData as T, EmployeeBuilder as a, type EmployeeData as b, createEmployee as c };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { O as ObjectIdLike } from './types-BN3K_Uhr.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Idempotency Manager
|
|
5
|
+
* Ensures operations are not duplicated when called with the same key
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface IdempotentResult<T = any> {
|
|
9
|
+
value: T;
|
|
10
|
+
cached: boolean;
|
|
11
|
+
createdAt: Date;
|
|
12
|
+
}
|
|
13
|
+
declare class IdempotencyManager {
|
|
14
|
+
private cache;
|
|
15
|
+
constructor(options?: {
|
|
16
|
+
max?: number;
|
|
17
|
+
ttl?: number;
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Check if key exists and return cached result
|
|
21
|
+
*/
|
|
22
|
+
get<T>(key: string): IdempotentResult<T> | null;
|
|
23
|
+
/**
|
|
24
|
+
* Store result for idempotency key
|
|
25
|
+
*/
|
|
26
|
+
set<T>(key: string, value: T): void;
|
|
27
|
+
/**
|
|
28
|
+
* Execute function with idempotency protection
|
|
29
|
+
*/
|
|
30
|
+
execute<T>(key: string, fn: () => Promise<T>): Promise<IdempotentResult<T>>;
|
|
31
|
+
/**
|
|
32
|
+
* Clear a specific key
|
|
33
|
+
*/
|
|
34
|
+
delete(key: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Clear all keys
|
|
37
|
+
*/
|
|
38
|
+
clear(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Get cache stats
|
|
41
|
+
*/
|
|
42
|
+
stats(): {
|
|
43
|
+
size: number;
|
|
44
|
+
max: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Generate idempotency key for payroll operations
|
|
49
|
+
*/
|
|
50
|
+
declare function generatePayrollIdempotencyKey(organizationId: ObjectIdLike, employeeId: ObjectIdLike, month: number, year: number): string;
|
|
51
|
+
|
|
52
|
+
export { IdempotencyManager as I, type IdempotentResult as a, generatePayrollIdempotencyKey as g };
|