@classytic/payroll 1.0.0 → 1.0.2
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/dist/types/config.d.ts +162 -0
- package/dist/types/core/compensation.manager.d.ts +54 -0
- package/dist/types/core/employment.manager.d.ts +49 -0
- package/dist/types/core/payroll.manager.d.ts +60 -0
- package/dist/types/enums.d.ts +117 -0
- package/dist/types/factories/compensation.factory.d.ts +196 -0
- package/dist/types/factories/employee.factory.d.ts +149 -0
- package/dist/types/factories/payroll.factory.d.ts +319 -0
- package/dist/types/hrm.orchestrator.d.ts +47 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/init.d.ts +30 -0
- package/dist/types/models/payroll-record.model.d.ts +3 -0
- package/dist/types/plugins/employee.plugin.d.ts +2 -0
- package/dist/types/schemas/employment.schema.d.ts +959 -0
- package/dist/types/services/compensation.service.d.ts +94 -0
- package/dist/types/services/employee.service.d.ts +28 -0
- package/dist/types/services/payroll.service.d.ts +30 -0
- package/dist/types/utils/calculation.utils.d.ts +26 -0
- package/dist/types/utils/date.utils.d.ts +35 -0
- package/dist/types/utils/logger.d.ts +12 -0
- package/dist/types/utils/query-builders.d.ts +83 -0
- package/dist/types/utils/validation.utils.d.ts +33 -0
- package/package.json +34 -13
- package/payroll.d.ts +241 -0
- package/src/factories/payroll.factory.js +167 -1
- package/src/init.js +21 -0
- package/src/plugins/employee.plugin.js +9 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Payroll Factory - Beautiful Salary Calculation & Record Creation
|
|
3
3
|
* Clean, testable, immutable payroll object creation
|
|
4
|
+
*
|
|
5
|
+
* Compatible with Mongoose v8 and v9
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
import {
|
|
@@ -12,7 +14,66 @@ import {
|
|
|
12
14
|
|
|
13
15
|
import { getPayPeriod } from '../utils/date.utils.js';
|
|
14
16
|
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {Object} AllowanceInput
|
|
19
|
+
* @property {string} type - Type of allowance
|
|
20
|
+
* @property {string} [name] - Display name for the allowance
|
|
21
|
+
* @property {number} value - Allowance value (amount or percentage)
|
|
22
|
+
* @property {boolean} [isPercentage=false] - Whether value is a percentage
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {Object} DeductionInput
|
|
27
|
+
* @property {string} type - Type of deduction
|
|
28
|
+
* @property {string} [name] - Display name for the deduction
|
|
29
|
+
* @property {number} value - Deduction value (amount or percentage)
|
|
30
|
+
* @property {boolean} [isPercentage=false] - Whether value is a percentage
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {Object} PeriodInput
|
|
35
|
+
* @property {number} [month] - Month (1-12)
|
|
36
|
+
* @property {number} [year] - Year
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {Object} PayrollMetadata
|
|
41
|
+
* @property {string} [currency='BDT'] - Currency code
|
|
42
|
+
* @property {string} [paymentMethod] - Payment method
|
|
43
|
+
* @property {string} [notes] - Additional notes
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef {Object} PayrollRecord
|
|
48
|
+
* @property {string} employeeId - Employee identifier
|
|
49
|
+
* @property {string} organizationId - Organization identifier
|
|
50
|
+
* @property {Object} period - Pay period information
|
|
51
|
+
* @property {Object} breakdown - Salary breakdown
|
|
52
|
+
* @property {number} breakdown.baseAmount - Base salary amount
|
|
53
|
+
* @property {Array} breakdown.allowances - Calculated allowances
|
|
54
|
+
* @property {Array} breakdown.deductions - Calculated deductions
|
|
55
|
+
* @property {number} breakdown.grossSalary - Gross salary
|
|
56
|
+
* @property {number} breakdown.netSalary - Net salary after deductions
|
|
57
|
+
* @property {string} status - Payroll status ('pending', 'processed', 'paid')
|
|
58
|
+
* @property {Date|null} processedAt - When payroll was processed
|
|
59
|
+
* @property {Date|null} paidAt - When payment was made
|
|
60
|
+
* @property {PayrollMetadata} metadata - Additional metadata
|
|
61
|
+
*/
|
|
62
|
+
|
|
15
63
|
export class PayrollFactory {
|
|
64
|
+
/**
|
|
65
|
+
* Create a new payroll record
|
|
66
|
+
*
|
|
67
|
+
* @param {Object} params - Payroll parameters
|
|
68
|
+
* @param {string} params.employeeId - Employee ID
|
|
69
|
+
* @param {string} params.organizationId - Organization ID
|
|
70
|
+
* @param {number} params.baseAmount - Base salary amount
|
|
71
|
+
* @param {AllowanceInput[]} [params.allowances=[]] - Allowances array
|
|
72
|
+
* @param {DeductionInput[]} [params.deductions=[]] - Deductions array
|
|
73
|
+
* @param {PeriodInput} [params.period={}] - Pay period
|
|
74
|
+
* @param {PayrollMetadata} [params.metadata={}] - Additional metadata
|
|
75
|
+
* @returns {PayrollRecord} Payroll record object
|
|
76
|
+
*/
|
|
16
77
|
static create({
|
|
17
78
|
employeeId,
|
|
18
79
|
organizationId,
|
|
@@ -50,6 +111,14 @@ export class PayrollFactory {
|
|
|
50
111
|
};
|
|
51
112
|
}
|
|
52
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Create a pay period object
|
|
116
|
+
*
|
|
117
|
+
* @param {PeriodInput} [params={}] - Period parameters
|
|
118
|
+
* @param {number} [params.month] - Month (defaults to current month)
|
|
119
|
+
* @param {number} [params.year] - Year (defaults to current year)
|
|
120
|
+
* @returns {Object} Pay period object with startDate, endDate, etc.
|
|
121
|
+
*/
|
|
53
122
|
static createPeriod({ month, year } = {}) {
|
|
54
123
|
const now = new Date();
|
|
55
124
|
return getPayPeriod(
|
|
@@ -58,6 +127,13 @@ export class PayrollFactory {
|
|
|
58
127
|
);
|
|
59
128
|
}
|
|
60
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Calculate allowances from base amount and allowance inputs
|
|
132
|
+
*
|
|
133
|
+
* @param {number} baseAmount - Base salary amount
|
|
134
|
+
* @param {AllowanceInput[]} allowances - Array of allowances
|
|
135
|
+
* @returns {Array} Calculated allowances with amounts
|
|
136
|
+
*/
|
|
61
137
|
static calculateAllowances(baseAmount, allowances) {
|
|
62
138
|
return allowances.map((allowance) => {
|
|
63
139
|
const amount = allowance.isPercentage
|
|
@@ -74,6 +150,13 @@ export class PayrollFactory {
|
|
|
74
150
|
});
|
|
75
151
|
}
|
|
76
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Calculate deductions from base amount and deduction inputs
|
|
155
|
+
*
|
|
156
|
+
* @param {number} baseAmount - Base salary amount
|
|
157
|
+
* @param {DeductionInput[]} deductions - Array of deductions
|
|
158
|
+
* @returns {Array} Calculated deductions with amounts
|
|
159
|
+
*/
|
|
77
160
|
static calculateDeductions(baseAmount, deductions) {
|
|
78
161
|
return deductions.map((deduction) => {
|
|
79
162
|
const amount = deduction.isPercentage
|
|
@@ -90,6 +173,16 @@ export class PayrollFactory {
|
|
|
90
173
|
});
|
|
91
174
|
}
|
|
92
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Create a bonus object
|
|
178
|
+
*
|
|
179
|
+
* @param {Object} params - Bonus parameters
|
|
180
|
+
* @param {string} params.type - Bonus type
|
|
181
|
+
* @param {number} params.amount - Bonus amount
|
|
182
|
+
* @param {string} params.reason - Reason for bonus
|
|
183
|
+
* @param {string} params.approvedBy - User who approved the bonus
|
|
184
|
+
* @returns {Object} Bonus object
|
|
185
|
+
*/
|
|
93
186
|
static createBonus({ type, amount, reason, approvedBy }) {
|
|
94
187
|
return {
|
|
95
188
|
type,
|
|
@@ -100,6 +193,16 @@ export class PayrollFactory {
|
|
|
100
193
|
};
|
|
101
194
|
}
|
|
102
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Create a deduction object
|
|
198
|
+
*
|
|
199
|
+
* @param {Object} params - Deduction parameters
|
|
200
|
+
* @param {string} params.type - Deduction type
|
|
201
|
+
* @param {number} params.amount - Deduction amount
|
|
202
|
+
* @param {string} params.reason - Reason for deduction
|
|
203
|
+
* @param {string} params.appliedBy - User who applied the deduction
|
|
204
|
+
* @returns {Object} Deduction object
|
|
205
|
+
*/
|
|
103
206
|
static createDeduction({ type, amount, reason, appliedBy }) {
|
|
104
207
|
return {
|
|
105
208
|
type,
|
|
@@ -110,6 +213,16 @@ export class PayrollFactory {
|
|
|
110
213
|
};
|
|
111
214
|
}
|
|
112
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Mark a payroll record as paid (immutable - returns new object)
|
|
218
|
+
*
|
|
219
|
+
* @param {PayrollRecord} payroll - Payroll record to mark as paid
|
|
220
|
+
* @param {Object} [params={}] - Payment details
|
|
221
|
+
* @param {Date} [params.paidAt] - Payment date (defaults to now)
|
|
222
|
+
* @param {string} [params.transactionId] - Transaction ID
|
|
223
|
+
* @param {string} [params.paymentMethod] - Payment method
|
|
224
|
+
* @returns {PayrollRecord} New payroll record marked as paid
|
|
225
|
+
*/
|
|
113
226
|
static markAsPaid(payroll, { paidAt = new Date(), transactionId, paymentMethod } = {}) {
|
|
114
227
|
return {
|
|
115
228
|
...payroll,
|
|
@@ -124,6 +237,14 @@ export class PayrollFactory {
|
|
|
124
237
|
};
|
|
125
238
|
}
|
|
126
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Mark a payroll record as processed (immutable - returns new object)
|
|
242
|
+
*
|
|
243
|
+
* @param {PayrollRecord} payroll - Payroll record to mark as processed
|
|
244
|
+
* @param {Object} [params={}] - Processing details
|
|
245
|
+
* @param {Date} [params.processedAt] - Processing date (defaults to now)
|
|
246
|
+
* @returns {PayrollRecord} New payroll record marked as processed
|
|
247
|
+
*/
|
|
127
248
|
static markAsProcessed(payroll, { processedAt = new Date() } = {}) {
|
|
128
249
|
return {
|
|
129
250
|
...payroll,
|
|
@@ -133,6 +254,18 @@ export class PayrollFactory {
|
|
|
133
254
|
}
|
|
134
255
|
}
|
|
135
256
|
|
|
257
|
+
/**
|
|
258
|
+
* PayrollBuilder - Fluent builder pattern for creating payroll records
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* const payroll = createPayroll()
|
|
262
|
+
* .forEmployee('emp-123')
|
|
263
|
+
* .inOrganization('org-456')
|
|
264
|
+
* .withBaseAmount(50000)
|
|
265
|
+
* .addAllowance('housing', 10000)
|
|
266
|
+
* .addDeduction('tax', 15, true)
|
|
267
|
+
* .build();
|
|
268
|
+
*/
|
|
136
269
|
export class PayrollBuilder {
|
|
137
270
|
constructor() {
|
|
138
271
|
this.data = {
|
|
@@ -203,12 +336,34 @@ export class PayrollBuilder {
|
|
|
203
336
|
}
|
|
204
337
|
}
|
|
205
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Create a new PayrollBuilder instance
|
|
341
|
+
*
|
|
342
|
+
* @returns {PayrollBuilder} New builder instance
|
|
343
|
+
*/
|
|
206
344
|
export const createPayroll = () => new PayrollBuilder();
|
|
207
345
|
|
|
208
346
|
/**
|
|
209
|
-
*
|
|
347
|
+
* BatchPayrollFactory - Process payroll for multiple employees at once
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* const payrolls = BatchPayrollFactory.createBatch(employees, {
|
|
351
|
+
* month: 1,
|
|
352
|
+
* year: 2025,
|
|
353
|
+
* organizationId: 'org-123'
|
|
354
|
+
* });
|
|
210
355
|
*/
|
|
211
356
|
export class BatchPayrollFactory {
|
|
357
|
+
/**
|
|
358
|
+
* Create payroll records for multiple employees
|
|
359
|
+
*
|
|
360
|
+
* @param {Array} employees - Array of employee objects
|
|
361
|
+
* @param {Object} params - Batch parameters
|
|
362
|
+
* @param {number} params.month - Month for payroll
|
|
363
|
+
* @param {number} params.year - Year for payroll
|
|
364
|
+
* @param {string} params.organizationId - Organization ID
|
|
365
|
+
* @returns {PayrollRecord[]} Array of payroll records
|
|
366
|
+
*/
|
|
212
367
|
static createBatch(employees, { month, year, organizationId }) {
|
|
213
368
|
return employees.map((employee) =>
|
|
214
369
|
PayrollFactory.create({
|
|
@@ -222,6 +377,17 @@ export class BatchPayrollFactory {
|
|
|
222
377
|
);
|
|
223
378
|
}
|
|
224
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Calculate total payroll amounts across multiple records
|
|
382
|
+
*
|
|
383
|
+
* @param {PayrollRecord[]} payrolls - Array of payroll records
|
|
384
|
+
* @returns {Object} Totals summary
|
|
385
|
+
* @returns {number} return.count - Total number of payrolls
|
|
386
|
+
* @returns {number} return.totalGross - Sum of gross salaries
|
|
387
|
+
* @returns {number} return.totalNet - Sum of net salaries
|
|
388
|
+
* @returns {number} return.totalAllowances - Sum of all allowances
|
|
389
|
+
* @returns {number} return.totalDeductions - Sum of all deductions
|
|
390
|
+
*/
|
|
225
391
|
static calculateTotalPayroll(payrolls) {
|
|
226
392
|
return payrolls.reduce(
|
|
227
393
|
(totals, payroll) => ({
|
package/src/init.js
CHANGED
|
@@ -3,6 +3,27 @@ import logger, { setLogger } from './utils/logger.js';
|
|
|
3
3
|
|
|
4
4
|
let initialized = false;
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Initialize HRM/Payroll framework
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} options - Initialization options
|
|
10
|
+
* @param {Model} options.EmployeeModel - Employee model (required)
|
|
11
|
+
* @param {Model} options.PayrollRecordModel - Payroll record model (required)
|
|
12
|
+
* @param {Model} options.TransactionModel - Transaction model (required)
|
|
13
|
+
* @param {Model} options.AttendanceModel - Optional attendance model for integration
|
|
14
|
+
* @param {Object} options.logger - Optional custom logger
|
|
15
|
+
*
|
|
16
|
+
* @example Multi-Tenant (default)
|
|
17
|
+
* initializeHRM({
|
|
18
|
+
* EmployeeModel,
|
|
19
|
+
* PayrollRecordModel,
|
|
20
|
+
* TransactionModel
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* @example Single-Tenant
|
|
24
|
+
* // For single-tenant apps, add organizationId with default value in your Employee schema:
|
|
25
|
+
* // organizationId: { type: ObjectId, required: true, default: () => FIXED_ORG_ID }
|
|
26
|
+
*/
|
|
6
27
|
export function initializeHRM({ EmployeeModel, PayrollRecordModel, TransactionModel, AttendanceModel = null, logger: customLogger }) {
|
|
7
28
|
// Allow users to inject their own logger
|
|
8
29
|
if (customLogger) {
|
|
@@ -136,11 +136,18 @@ export function employeePlugin(schema, options = {}) {
|
|
|
136
136
|
});
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Pre-save hook to automatically update salary calculations
|
|
141
|
+
* when compensation is modified.
|
|
142
|
+
*
|
|
143
|
+
* Mongoose v9 compatible - uses async function without next callback
|
|
144
|
+
* - Use throw instead of next(err) for errors
|
|
145
|
+
* - Use return instead of return next()
|
|
146
|
+
*/
|
|
147
|
+
schema.pre('save', async function() {
|
|
140
148
|
if (this.isModified('compensation')) {
|
|
141
149
|
this.updateSalaryCalculations();
|
|
142
150
|
}
|
|
143
|
-
next();
|
|
144
151
|
});
|
|
145
152
|
|
|
146
153
|
schema.index({ organizationId: 1, employeeId: 1 }, { unique: true });
|