@classytic/payroll 1.0.2 โ†’ 2.0.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.
Files changed (68) hide show
  1. package/README.md +168 -489
  2. package/dist/core/index.d.ts +480 -0
  3. package/dist/core/index.js +971 -0
  4. package/dist/core/index.js.map +1 -0
  5. package/dist/index-CTjHlCzz.d.ts +721 -0
  6. package/dist/index.d.ts +967 -0
  7. package/dist/index.js +4352 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/payroll.d.ts +233 -0
  10. package/dist/payroll.js +2103 -0
  11. package/dist/payroll.js.map +1 -0
  12. package/dist/plugin-D9mOr3_d.d.ts +333 -0
  13. package/dist/schemas/index.d.ts +2869 -0
  14. package/dist/schemas/index.js +440 -0
  15. package/dist/schemas/index.js.map +1 -0
  16. package/dist/services/index.d.ts +3 -0
  17. package/dist/services/index.js +1696 -0
  18. package/dist/services/index.js.map +1 -0
  19. package/dist/types-BSYyX2KJ.d.ts +671 -0
  20. package/dist/utils/index.d.ts +873 -0
  21. package/dist/utils/index.js +1046 -0
  22. package/dist/utils/index.js.map +1 -0
  23. package/package.json +54 -37
  24. package/dist/types/config.d.ts +0 -162
  25. package/dist/types/core/compensation.manager.d.ts +0 -54
  26. package/dist/types/core/employment.manager.d.ts +0 -49
  27. package/dist/types/core/payroll.manager.d.ts +0 -60
  28. package/dist/types/enums.d.ts +0 -117
  29. package/dist/types/factories/compensation.factory.d.ts +0 -196
  30. package/dist/types/factories/employee.factory.d.ts +0 -149
  31. package/dist/types/factories/payroll.factory.d.ts +0 -319
  32. package/dist/types/hrm.orchestrator.d.ts +0 -47
  33. package/dist/types/index.d.ts +0 -20
  34. package/dist/types/init.d.ts +0 -30
  35. package/dist/types/models/payroll-record.model.d.ts +0 -3
  36. package/dist/types/plugins/employee.plugin.d.ts +0 -2
  37. package/dist/types/schemas/employment.schema.d.ts +0 -959
  38. package/dist/types/services/compensation.service.d.ts +0 -94
  39. package/dist/types/services/employee.service.d.ts +0 -28
  40. package/dist/types/services/payroll.service.d.ts +0 -30
  41. package/dist/types/utils/calculation.utils.d.ts +0 -26
  42. package/dist/types/utils/date.utils.d.ts +0 -35
  43. package/dist/types/utils/logger.d.ts +0 -12
  44. package/dist/types/utils/query-builders.d.ts +0 -83
  45. package/dist/types/utils/validation.utils.d.ts +0 -33
  46. package/payroll.d.ts +0 -241
  47. package/src/config.js +0 -177
  48. package/src/core/compensation.manager.js +0 -242
  49. package/src/core/employment.manager.js +0 -224
  50. package/src/core/payroll.manager.js +0 -499
  51. package/src/enums.js +0 -141
  52. package/src/factories/compensation.factory.js +0 -198
  53. package/src/factories/employee.factory.js +0 -173
  54. package/src/factories/payroll.factory.js +0 -413
  55. package/src/hrm.orchestrator.js +0 -139
  56. package/src/index.js +0 -172
  57. package/src/init.js +0 -62
  58. package/src/models/payroll-record.model.js +0 -126
  59. package/src/plugins/employee.plugin.js +0 -164
  60. package/src/schemas/employment.schema.js +0 -126
  61. package/src/services/compensation.service.js +0 -231
  62. package/src/services/employee.service.js +0 -162
  63. package/src/services/payroll.service.js +0 -213
  64. package/src/utils/calculation.utils.js +0 -91
  65. package/src/utils/date.utils.js +0 -120
  66. package/src/utils/logger.js +0 -36
  67. package/src/utils/query-builders.js +0 -185
  68. package/src/utils/validation.utils.js +0 -122
package/README.md CHANGED
@@ -1,574 +1,253 @@
1
- # ๐ŸŽฏ HRM Library - Human Resource Management
1
+ # @classytic/payroll
2
2
 
3
- Modern, flexible, production-ready HRM system following Stripe/Passport.js architecture patterns.
3
+ Enterprise-grade payroll for Mongoose. Simple, powerful, production-ready.
4
4
 
5
- ## ๐ŸŒŸ Key Features
5
+ [![npm version](https://badge.fury.io/js/@classytic%2Fpayroll.svg)](https://www.npmjs.com/package/@classytic/payroll)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
8
 
7
- ### Multi-Tenant Support
8
- - Same user can be employee in multiple organizations
9
- - Complete data isolation per tenant
10
- - Re-hiring support with full employment history
9
+ ## Why This Package?
11
10
 
12
- ### Smart Payroll
13
- - **Pro-rated calculations** (mid-month hires)
14
- - **Attendance integration** (unpaid leave auto-deduction)
15
- - **Automatic deductions** (loans, advances, tax)
16
- - **Bulk payroll processing**
17
- - **Transaction integration** (seamless with existing system)
11
+ - ๐ŸŽฏ **One clear way to do things** - No confusion, no multiple paths
12
+ - โšก **Attendance built-in** - Uses `@classytic/clockin` natively
13
+ - ๐Ÿข **Multi-tenant & Single-tenant** - Both supported out of the box
14
+ - ๐Ÿ’ฐ **Smart calculations** - Pro-rating, tax, deductions, all automatic
15
+ - ๐Ÿงช **Pure functions** - Test easily, preview without DB
16
+ - ๐Ÿ”’ **Transaction-safe** - Atomic operations, no partial writes
17
+ - ๐Ÿ“ฆ **Zero config** - Works immediately with smart defaults
18
18
 
19
- ### Data Retention
20
- - **Auto-deletion**: PayrollRecords expire after 2 years (MongoDB TTL)
21
- - **Export before deletion**: Required export for compliance
22
- - **Configurable retention**: Adjust via `HRM_CONFIG`
19
+ ## Installation
23
20
 
24
- ### Flexible Architecture
25
- - **Reusable schemas**: Merge with your custom fields
26
- - **Plugin system**: Adds methods, virtuals, indexes
27
- - **Clean DSL**: `hrm.hire()`, `hrm.processSalary()`, `hrm.terminate()`
28
- - **Dependency injection**: Models injected at bootstrap
29
-
30
- ## ๐Ÿ“ Structure
31
-
32
- ```
33
- lib/hrm/
34
- โ”œโ”€โ”€ index.js # Public exports
35
- โ”œโ”€โ”€ init.js # Bootstrap initialization
36
- โ”œโ”€โ”€ hrm.orchestrator.js # Clean API (Stripe-like)
37
- โ”œโ”€โ”€ enums.js # Single source of truth
38
- โ”œโ”€โ”€ config.js # Configurable settings
39
- โ”‚
40
- โ”œโ”€โ”€ models/
41
- โ”‚ โ””โ”€โ”€ payroll-record.model.js # Universal payroll ledger
42
- โ”‚
43
- โ”œโ”€โ”€ schemas/
44
- โ”‚ โ””โ”€โ”€ employment.schema.js # Reusable mongoose schemas
45
- โ”‚
46
- โ”œโ”€โ”€ plugins/
47
- โ”‚ โ””โ”€โ”€ employee.plugin.js # Mongoose plugin (methods/virtuals)
48
- โ”‚
49
- โ”œโ”€โ”€ core/ # Domain business logic
50
- โ”‚ โ”œโ”€โ”€ employment.manager.js # Hire/terminate operations
51
- โ”‚ โ”œโ”€โ”€ compensation.manager.js # Salary/allowance operations
52
- โ”‚ โ””โ”€โ”€ payroll.manager.js # Payroll processing
53
- โ”‚
54
- โ”œโ”€โ”€ factories/ # Clean object creation
55
- โ”‚ โ”œโ”€โ”€ employee.factory.js # Employee creation with defaults
56
- โ”‚ โ”œโ”€โ”€ payroll.factory.js # Payroll generation
57
- โ”‚ โ””โ”€โ”€ compensation.factory.js # Compensation breakdown
58
- โ”‚
59
- โ”œโ”€โ”€ services/ # High-level operations
60
- โ”‚ โ”œโ”€โ”€ employee.service.js # Employee CRUD + queries
61
- โ”‚ โ”œโ”€โ”€ payroll.service.js # Batch payroll processing
62
- โ”‚ โ””โ”€โ”€ compensation.service.js # Compensation calculations
63
- โ”‚
64
- โ””โ”€โ”€ utils/ # Pure, reusable functions
65
- โ”œโ”€โ”€ date.utils.js # Date calculations
66
- โ”œโ”€โ”€ calculation.utils.js # Salary calculations
67
- โ”œโ”€โ”€ validation.utils.js # Validators
68
- โ””โ”€โ”€ query-builders.js # Fluent query API
21
+ ```bash
22
+ npm install @classytic/payroll @classytic/clockin mongoose
69
23
  ```
70
24
 
71
- ## ๐Ÿš€ Quick Start
25
+ ## Quick Start (3 steps)
72
26
 
73
- ### 1. Create Your Employee Model
27
+ ### 1. Create Models
74
28
 
75
- ```javascript
76
- // modules/employee/employee.model.js
29
+ ```typescript
77
30
  import mongoose from 'mongoose';
78
- import { employmentFields, employeePlugin } from '#lib/hrm/index.js';
31
+ import { createAttendanceSchema } from '@classytic/clockin/schemas';
32
+ import { employeeSchema, employeePlugin, payrollRecordSchema, createHolidaySchema } from '@classytic/payroll';
79
33
 
80
- const employeeSchema = new mongoose.Schema({
81
- // Core HRM fields (required)
82
- ...employmentFields,
34
+ // Attendance (from ClockIn - required for payroll)
35
+ const Attendance = mongoose.model('Attendance', createAttendanceSchema());
83
36
 
84
- // Your custom fields
85
- certifications: [{ name: String, issuedDate: Date }],
86
- specializations: [String],
87
- emergencyContact: { name: String, phone: String },
88
- // ... any other fields you need
89
- });
90
-
91
- // Apply HRM plugin (adds methods, virtuals, indexes)
37
+ // Employee (with payroll plugin)
92
38
  employeeSchema.plugin(employeePlugin);
39
+ const Employee = mongoose.model('Employee', employeeSchema);
40
+
41
+ // PayrollRecord
42
+ const PayrollRecord = mongoose.model('PayrollRecord', payrollRecordSchema);
93
43
 
94
- export default mongoose.model('Employee', employeeSchema);
44
+ // Transaction (your own model)
45
+ const Transaction = mongoose.model('Transaction', transactionSchema);
46
+
47
+ // Holiday (optional - use our schema or your own)
48
+ const Holiday = mongoose.model('Holiday', createHolidaySchema());
95
49
  ```
96
50
 
97
- ### 2. Bootstrap Integration
51
+ ### 2. Initialize
98
52
 
99
- ```javascript
100
- // bootstrap/hrm.js
101
- import { initializeHRM } from '#lib/hrm/index.js';
102
- import Employee from '../modules/employee/employee.model.js';
103
- import PayrollRecord from '#lib/hrm/models/payroll-record.model.js';
104
- import Transaction from '../modules/transaction/transaction.model.js';
105
- import Attendance from '#lib/attendance/models/attendance.model.js';
53
+ ```typescript
54
+ import { createPayrollInstance } from '@classytic/payroll';
106
55
 
107
- export async function loadHRM() {
108
- initializeHRM({
56
+ const payroll = createPayrollInstance()
57
+ .withModels({
109
58
  EmployeeModel: Employee,
110
59
  PayrollRecordModel: PayrollRecord,
111
60
  TransactionModel: Transaction,
112
- AttendanceModel: Attendance, // Optional
113
- });
114
- }
61
+ AttendanceModel: Attendance,
62
+ })
63
+ .build();
115
64
  ```
116
65
 
117
- ### 3. Use the HRM API
118
-
119
- ```javascript
120
- import { hrm } from '#lib/hrm/index.js';
66
+ ### 3. Use It
121
67
 
68
+ ```typescript
122
69
  // Hire employee
123
- const employee = await hrm.hire({
124
- organizationId,
125
- userId,
70
+ const employee = await payroll.hire({
71
+ userId: user._id,
72
+ organizationId: org._id,
126
73
  employment: {
127
- employeeId: 'EMP-001',
74
+ position: 'Software Engineer',
75
+ department: 'engineering',
128
76
  type: 'full_time',
129
- department: 'training',
130
- position: 'Senior Trainer',
131
- hireDate: new Date(),
132
77
  },
133
78
  compensation: {
134
- baseAmount: 50000,
135
- frequency: 'monthly',
79
+ baseAmount: 100000,
80
+ currency: 'USD',
136
81
  allowances: [
137
- { type: 'housing', amount: 10000 },
138
- { type: 'transport', amount: 5000 }
139
- ]
140
- },
141
- bankDetails: {
142
- accountName: 'John Doe',
143
- accountNumber: '1234567890',
144
- bankName: 'Example Bank'
82
+ { type: 'housing', amount: 20000, taxable: true },
83
+ ],
145
84
  },
146
- context: { userId: hrManagerId }
147
85
  });
148
86
 
149
- // Process salary (creates Transaction automatically)
150
- const result = await hrm.processSalary({
87
+ // Process monthly payroll (automatic attendance deductions)
88
+ const result = await payroll.processSalary({
151
89
  employeeId: employee._id,
152
- month: 11,
153
- year: 2025,
154
- paymentDate: new Date(),
155
- paymentMethod: 'bank',
156
- context: { userId: hrManagerId }
90
+ month: 3,
91
+ year: 2024,
157
92
  });
158
93
 
159
- // Bulk payroll (all active employees)
160
- const results = await hrm.processBulkPayroll({
161
- organizationId,
162
- month: 11,
163
- year: 2025,
164
- context: { userId: hrManagerId }
165
- });
94
+ console.log(result.payrollRecord.breakdown);
95
+ // {
96
+ // baseSalary: 100000,
97
+ // allowances: 20000,
98
+ // deductions: 9090, // โ† Attendance deduction
99
+ // tax: 2500,
100
+ // gross: 120000,
101
+ // net: 108410
102
+ // }
166
103
  ```
167
104
 
105
+ ## Single-Tenant Setup
168
106
 
169
- ## ๐ŸŽจ Complete API Reference
170
-
171
- ### Employment Lifecycle
172
-
173
- ```javascript
174
- // Hire
175
- await hrm.hire({ organizationId, userId, employment, compensation, bankDetails, context });
176
-
177
- // Update employment details
178
- await hrm.updateEmployment({ employeeId, updates: { department: 'management' }, context });
179
-
180
- // Terminate
181
- await hrm.terminate({ employeeId, terminationDate, reason: 'resignation', notes, context });
107
+ Building a single-organization HRM? No `organizationId` needed:
182
108
 
183
- // Re-hire (same employee, new stint)
184
- await hrm.reHire({ employeeId, hireDate, position, compensation, context });
109
+ ```typescript
110
+ const payroll = createPayrollInstance()
111
+ .withModels({ EmployeeModel, PayrollRecordModel, TransactionModel, AttendanceModel })
112
+ .forSingleTenant() // โ† That's it!
113
+ .build();
185
114
 
186
- // List employees
187
- await hrm.listEmployees({
188
- organizationId,
189
- filters: { status: 'active', department: 'training', minSalary: 40000 },
190
- pagination: { page: 1, limit: 20 }
115
+ // No organizationId anywhere
116
+ const employee = await payroll.hire({
117
+ userId: user._id,
118
+ employment: { position: 'Manager', type: 'full_time' },
119
+ compensation: { baseAmount: 150000, currency: 'USD' },
191
120
  });
192
-
193
- // Get single employee
194
- await hrm.getEmployee({ employeeId, populateUser: true });
195
121
  ```
196
122
 
197
- ### Compensation Management
123
+ ## Attendance (ClockIn)
198
124
 
199
- ```javascript
200
- // Update salary
201
- await hrm.updateSalary({
202
- employeeId,
203
- compensation: { baseAmount: 60000 },
204
- effectiveFrom: new Date(),
205
- context
206
- });
125
+ Attendance is **native**, not an add-on:
207
126
 
208
- // Add allowance
209
- await hrm.addAllowance({
210
- employeeId,
211
- type: 'meal',
212
- amount: 3000,
213
- taxable: true,
214
- recurring: true,
215
- context
216
- });
127
+ ```typescript
128
+ import { ClockIn } from '@classytic/clockin';
129
+ import { getAttendance } from '@classytic/payroll';
217
130
 
218
- // Remove allowance
219
- await hrm.removeAllowance({ employeeId, type: 'meal', context });
131
+ // Initialize ClockIn
132
+ const clockin = ClockIn.create()
133
+ .withModels({ Attendance, Membership: Employee })
134
+ .build();
220
135
 
221
- // Add deduction
222
- await hrm.addDeduction({
223
- employeeId,
224
- type: 'loan',
225
- amount: 5000,
226
- auto: true, // Auto-deduct from salary
227
- description: 'Personal loan repayment',
228
- context
136
+ // Employees check in
137
+ await clockin.checkIn.record({
138
+ member: employee,
139
+ targetModel: 'Employee',
140
+ data: { method: 'qr_code' },
229
141
  });
230
142
 
231
- // Remove deduction
232
- await hrm.removeDeduction({ employeeId, type: 'loan', context });
143
+ // Payroll automatically uses attendance
144
+ const attendance = await getAttendance(Attendance, {
145
+ organizationId: org._id,
146
+ employeeId: employee._id,
147
+ month: 3,
148
+ year: 2024,
149
+ expectedDays: 22,
150
+ });
233
151
 
234
- // Update bank details
235
- await hrm.updateBankDetails({
236
- employeeId,
237
- bankDetails: { accountNumber: '9876543210', bankName: 'New Bank' },
238
- context
152
+ await payroll.processSalary({
153
+ employeeId: employee._id,
154
+ month: 3,
155
+ year: 2024,
156
+ attendance, // โ† Deductions automatically applied
239
157
  });
240
158
  ```
241
159
 
242
- ### Payroll Processing
160
+ ## Holidays
243
161
 
244
- ```javascript
245
- // Process single salary
246
- await hrm.processSalary({
247
- employeeId,
248
- month: 11,
249
- year: 2025,
250
- paymentDate: new Date(),
251
- paymentMethod: 'bank',
252
- context
253
- });
162
+ Simple approach - one way:
254
163
 
255
- // Bulk payroll
256
- await hrm.processBulkPayroll({
257
- organizationId,
258
- month: 11,
259
- year: 2025,
260
- employeeIds: [], // Empty = all active employees
261
- paymentDate: new Date(),
262
- paymentMethod: 'bank',
263
- context
264
- });
164
+ ```typescript
165
+ import { getHolidays } from '@classytic/payroll';
265
166
 
266
- // Payroll history
267
- await hrm.payrollHistory({
268
- employeeId,
269
- organizationId,
270
- month: 11,
271
- year: 2025,
272
- status: 'paid',
273
- pagination: { page: 1, limit: 20 }
167
+ // Add sudden off day
168
+ await Holiday.create({
169
+ organizationId: org._id,
170
+ date: new Date('2024-03-17'),
171
+ name: 'Emergency closure',
172
+ type: 'company',
173
+ paid: true,
274
174
  });
275
175
 
276
- // Payroll summary
277
- await hrm.payrollSummary({
278
- organizationId,
279
- month: 11,
280
- year: 2025
176
+ // Get holidays when processing
177
+ const holidays = await getHolidays(Holiday, {
178
+ organizationId: org._id,
179
+ startDate: new Date('2024-03-01'),
180
+ endDate: new Date('2024-03-31'),
281
181
  });
282
182
 
283
- // Export payroll data (before auto-deletion)
284
- const records = await hrm.exportPayroll({
285
- organizationId,
286
- startDate: new Date('2023-01-01'),
287
- endDate: new Date('2023-12-31'),
288
- format: 'json'
183
+ // Pass to payroll
184
+ await payroll.processSalary({
185
+ employeeId,
186
+ month: 3,
187
+ year: 2024,
188
+ options: { holidays },
289
189
  });
290
190
  ```
291
191
 
292
- ## ๐Ÿ“Š Data Models
293
-
294
- ### Employee (Your Model + HRM Fields)
295
-
296
- ```javascript
297
- {
298
- // Identity & tenant
299
- userId: ObjectId, // Links to User
300
- organizationId: ObjectId, // Multi-tenant isolation
301
- employeeId: "EMP-001", // Custom ID (unique per org)
302
-
303
- // Employment
304
- employmentType: "full_time", // full_time, part_time, contract, intern
305
- status: "active", // active, on_leave, suspended, terminated
306
- department: "training",
307
- position: "Senior Trainer",
308
-
309
- // Dates
310
- hireDate: Date,
311
- terminationDate: Date,
312
- probationEndDate: Date,
313
-
314
- // Employment history (re-hiring support)
315
- employmentHistory: [{
316
- hireDate: Date,
317
- terminationDate: Date,
318
- reason: String,
319
- finalSalary: Number
320
- }],
321
-
322
- // Compensation
323
- compensation: {
324
- baseAmount: 50000,
325
- frequency: "monthly",
326
- currency: "BDT",
327
-
328
- allowances: [
329
- { type: "housing", amount: 10000, taxable: true },
330
- { type: "transport", amount: 5000, taxable: false }
331
- ],
332
-
333
- deductions: [
334
- { type: "loan", amount: 2000, auto: true }
335
- ],
192
+ ## Logging
336
193
 
337
- grossSalary: 65000, // Auto-calculated
338
- netSalary: 63000, // Auto-calculated
339
- },
194
+ Control logging in production:
340
195
 
341
- // Bank details
342
- bankDetails: {
343
- accountName: String,
344
- accountNumber: String,
345
- bankName: String
346
- },
347
-
348
- // Payroll stats (pre-calculated)
349
- payrollStats: {
350
- totalPaid: 500000,
351
- lastPaymentDate: Date,
352
- nextPaymentDate: Date,
353
- paymentsThisYear: 10,
354
- averageMonthly: 50000
355
- },
196
+ ```typescript
197
+ import { disableLogging, enableLogging } from '@classytic/payroll/utils';
356
198
 
357
- // YOUR CUSTOM FIELDS
358
- certifications: [...],
359
- specializations: [...],
360
- emergencyContact: {...}
199
+ // Disable in production
200
+ if (process.env.NODE_ENV === 'production') {
201
+ disableLogging();
361
202
  }
362
- ```
363
-
364
- ### PayrollRecord (Universal Ledger)
365
-
366
- ```javascript
367
- {
368
- organizationId: ObjectId,
369
- employeeId: ObjectId,
370
- userId: ObjectId,
371
-
372
- period: {
373
- month: 11,
374
- year: 2025,
375
- startDate: Date,
376
- endDate: Date,
377
- payDate: Date
378
- },
379
-
380
- breakdown: {
381
- baseAmount: 50000,
382
- allowances: [...],
383
- deductions: [...],
384
- grossSalary: 65000,
385
- netSalary: 63000,
386
-
387
- // Smart calculations
388
- workingDays: 30,
389
- actualDays: 25, // If joined mid-month
390
- proRatedAmount: 41667, // Pro-rated salary
391
- attendanceDeduction: 0, // From attendance integration
392
- overtimeAmount: 0,
393
- bonusAmount: 0
394
- },
395
-
396
- transactionId: ObjectId, // Links to Transaction
397
- status: "paid",
398
- paidAt: Date,
399
-
400
- // Export tracking
401
- exported: false, // Must export before TTL deletion
402
- exportedAt: Date
403
- }
404
- ```
405
-
406
- ## โš™๏ธ Configuration
407
-
408
- ```javascript
409
- // lib/hrm/config.js
410
- export const HRM_CONFIG = {
411
- dataRetention: {
412
- payrollRecordsTTL: 63072000, // 2 years in seconds
413
- exportWarningDays: 30, // Warn before deletion
414
- archiveBeforeDeletion: true,
415
- },
416
-
417
- payroll: {
418
- defaultCurrency: 'BDT',
419
- allowProRating: true, // Mid-month hire calculations
420
- attendanceIntegration: true, // Unpaid leave deductions
421
- autoDeductions: true, // Auto-deduct loans/advances
422
- },
423
203
 
424
- employment: {
425
- defaultProbationMonths: 3,
426
- allowReHiring: true, // Re-hire terminated employees
427
- trackEmploymentHistory: true,
204
+ // Or use custom logger
205
+ payroll.initialize({
206
+ ...models,
207
+ logger: {
208
+ info: (msg, meta) => pino.info(meta, msg),
209
+ error: (msg, meta) => pino.error(meta, msg),
210
+ warn: (msg, meta) => pino.warn(meta, msg),
211
+ debug: (msg, meta) => pino.debug(meta, msg),
428
212
  },
429
-
430
- validation: {
431
- requireBankDetails: false,
432
- allowMultiTenantEmployees: true, // Same user in multiple orgs
433
- },
434
- };
435
- ```
436
-
437
- ## ๐Ÿ”‘ Key Concepts
438
-
439
- ### Multi-Tenant Architecture
440
-
441
- Same user can work at multiple gyms:
442
- ```javascript
443
- // User "john@example.com" (userId: 123)
444
- // Works at Gym A
445
- { userId: 123, organizationId: "gymA", employeeId: "EMP-001", status: "active" }
446
-
447
- // Also works at Gym B
448
- { userId: 123, organizationId: "gymB", employeeId: "STAFF-05", status: "active" }
449
- ```
450
-
451
- Indexes ensure uniqueness:
452
- - `{ userId: 1, organizationId: 1 }` unique
453
- - `{ organizationId: 1, employeeId: 1 }` unique
454
-
455
- ### Re-Hiring Flow
456
-
457
- ```javascript
458
- // Employee leaves
459
- await hrm.terminate({
460
- employeeId,
461
- reason: 'resignation',
462
- terminationDate: new Date()
463
- });
464
- // status: 'terminated', data preserved
465
-
466
- // Employee comes back
467
- await hrm.reHire({
468
- employeeId,
469
- hireDate: new Date(),
470
- position: 'Manager', // Optional: new position
471
- compensation: { baseAmount: 60000 } // Optional: new salary
472
213
  });
473
- // status: 'active', previous stint added to employmentHistory[]
474
214
  ```
475
215
 
476
- ### Smart Payroll Calculations
216
+ ## API
477
217
 
478
- **Pro-Rating (Mid-Month Hire)**:
479
- ```javascript
480
- // Employee hired on Nov 15
481
- // Working days: 15 out of 30
482
- // Base salary: 60,000
483
- // Pro-rated: 60,000 ร— (15/30) = 30,000
484
- ```
485
-
486
- **Attendance Integration**:
487
- ```javascript
488
- // Monthly salary: 60,000
489
- // Working days: 30
490
- // Attended days: 25
491
- // Absent days: 5
492
- // Daily rate: 60,000 / 30 = 2,000
493
- // Deduction: 5 ร— 2,000 = 10,000
494
- // Final: 60,000 - 10,000 = 50,000
495
- ```
218
+ ```typescript
219
+ // Employee lifecycle
220
+ payroll.hire({ ... })
221
+ payroll.updateEmployment({ ... })
222
+ payroll.terminate({ ... })
223
+ payroll.reHire({ ... })
496
224
 
497
- **Auto Deductions**:
498
- ```javascript
499
- compensation: {
500
- baseAmount: 60000,
501
- allowances: [{ type: 'housing', amount: 10000 }],
502
- deductions: [
503
- { type: 'loan', amount: 5000, auto: true }, // Auto-deduct
504
- { type: 'tax', amount: 3000, auto: true }
505
- ],
506
- grossSalary: 70000,
507
- netSalary: 62000 // 70000 - 5000 - 3000
508
- }
509
- ```
225
+ // Compensation
226
+ payroll.updateSalary({ ... })
227
+ payroll.addAllowance({ ... })
228
+ payroll.addDeduction({ ... })
510
229
 
511
- ### Transaction Integration
512
-
513
- Every salary payment creates a Transaction:
514
- ```javascript
515
- {
516
- organizationId,
517
- type: 'expense',
518
- category: 'salary',
519
- amount: 63000,
520
- method: 'bank',
521
- status: 'completed',
522
- referenceId: employeeId,
523
- referenceModel: 'Employee',
524
- metadata: {
525
- employeeId: 'EMP-001',
526
- payrollRecordId: ObjectId(...),
527
- period: { month: 11, year: 2025 },
528
- breakdown: { ... }
529
- }
530
- }
531
- ```
230
+ // Payroll processing
231
+ payroll.processSalary({ ... })
232
+ payroll.processBulkPayroll({ ... })
233
+ payroll.payrollHistory({ ... })
234
+ payroll.payrollSummary({ ... })
532
235
 
533
- ### Data Retention & Export
534
-
535
- PayrollRecords auto-delete after 2 years:
536
- ```javascript
537
- // TTL index on PayrollRecord
538
- payrollRecordSchema.index(
539
- { createdAt: 1 },
540
- {
541
- expireAfterSeconds: 63072000, // 2 years
542
- partialFilterExpression: { exported: true } // Only if exported
543
- }
544
- );
545
-
546
- // Export before deletion
547
- const records = await hrm.exportPayroll({
548
- organizationId,
549
- startDate: new Date('2023-01-01'),
550
- endDate: new Date('2023-12-31')
551
- });
552
- // Marks records as exported, making them eligible for deletion
236
+ // Pure functions (for previews/testing)
237
+ import { calculateSalaryBreakdown, countWorkingDays, calculateTax } from '@classytic/payroll/core';
553
238
  ```
554
239
 
555
- ## ๐ŸŽฏ Design Philosophy
240
+ ## Documentation
556
241
 
557
- - **Stripe/Passport.js inspired**: Clean DSL, dependency injection, reusable components
558
- - **Lightweight**: Not a complex ERP, gym-focused features only
559
- - **Multi-tenant**: Same user can work at multiple organizations
560
- - **Smart defaults**: Pro-rating, attendance integration, automatic calculations
561
- - **Production-ready**: Transaction integration, data retention, comprehensive error handling
242
+ - **[HRM Guide](./docs/HRM_GUIDE.md)** - Complete guide to building HRM
243
+ - **[Single Tenant](./docs/SINGLE_TENANT.md)** - Single-organization setup
244
+ - **[Integration](./docs/INTEGRATION.md)** - Fastify, Express plugins
245
+ - **[Development](./docs/DEVELOPMENT.md)** - Contributing
562
246
 
563
- ## โœ… Next Steps
247
+ ## Related Packages
564
248
 
565
- 1. Test bootstrap initialization
566
- 2. Create Fastify routes in `modules/employee/`
567
- 3. Add API handlers
568
- 4. Migrate existing staff from organization module
569
- 5. Deploy and monitor
249
+ - **[@classytic/clockin](https://npmjs.com/package/@classytic/clockin)** - Attendance management (required peer dependency)
570
250
 
571
- ---
251
+ ## License
572
252
 
573
- **Built with โค๏ธ following world-class architecture patterns**
574
- **Ready for multi-tenant gym management**
253
+ MIT ยฉ [Sadman Chowdhury](https://github.com/classytic)