@classytic/payroll 1.0.1 → 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.

@@ -0,0 +1,94 @@
1
+ export class CompensationService {
2
+ constructor(EmployeeModel: any);
3
+ EmployeeModel: any;
4
+ getEmployeeCompensation(employeeId: any): Promise<any>;
5
+ calculateBreakdown(employeeId: any): Promise<{
6
+ baseAmount: any;
7
+ allowances: any;
8
+ deductions: any;
9
+ grossAmount: any;
10
+ netAmount: number;
11
+ }>;
12
+ updateBaseAmount(employeeId: any, newAmount: any, effectiveFrom: any): Promise<{
13
+ baseAmount: any;
14
+ allowances: any;
15
+ deductions: any;
16
+ grossAmount: any;
17
+ netAmount: number;
18
+ }>;
19
+ applyIncrement(employeeId: any, { percentage, amount, effectiveFrom }: {
20
+ percentage: any;
21
+ amount: any;
22
+ effectiveFrom: any;
23
+ }): Promise<{
24
+ baseAmount: any;
25
+ allowances: any;
26
+ deductions: any;
27
+ grossAmount: any;
28
+ netAmount: number;
29
+ }>;
30
+ addAllowance(employeeId: any, allowance: any): Promise<{
31
+ baseAmount: any;
32
+ allowances: any;
33
+ deductions: any;
34
+ grossAmount: any;
35
+ netAmount: number;
36
+ }>;
37
+ removeAllowance(employeeId: any, allowanceType: any): Promise<{
38
+ baseAmount: any;
39
+ allowances: any;
40
+ deductions: any;
41
+ grossAmount: any;
42
+ netAmount: number;
43
+ }>;
44
+ addDeduction(employeeId: any, deduction: any): Promise<{
45
+ baseAmount: any;
46
+ allowances: any;
47
+ deductions: any;
48
+ grossAmount: any;
49
+ netAmount: number;
50
+ }>;
51
+ removeDeduction(employeeId: any, deductionType: any): Promise<{
52
+ baseAmount: any;
53
+ allowances: any;
54
+ deductions: any;
55
+ grossAmount: any;
56
+ netAmount: number;
57
+ }>;
58
+ setStandardCompensation(employeeId: any, baseAmount: any): Promise<{
59
+ baseAmount: any;
60
+ allowances: any;
61
+ deductions: any;
62
+ grossAmount: any;
63
+ netAmount: number;
64
+ }>;
65
+ compareCompensation(employeeId1: any, employeeId2: any): Promise<{
66
+ employee1: {
67
+ baseAmount: any;
68
+ allowances: any;
69
+ deductions: any;
70
+ grossAmount: any;
71
+ netAmount: number;
72
+ };
73
+ employee2: {
74
+ baseAmount: any;
75
+ allowances: any;
76
+ deductions: any;
77
+ grossAmount: any;
78
+ netAmount: number;
79
+ };
80
+ difference: {
81
+ base: number;
82
+ gross: number;
83
+ net: number;
84
+ };
85
+ ratio: {
86
+ base: number;
87
+ gross: number;
88
+ net: number;
89
+ };
90
+ }>;
91
+ getDepartmentCompensationStats(organizationId: any, department: any): Promise<any>;
92
+ getOrganizationCompensationStats(organizationId: any): Promise<any>;
93
+ }
94
+ export function createCompensationService(EmployeeModel: any): CompensationService;
@@ -0,0 +1,28 @@
1
+ export class EmployeeService {
2
+ constructor(EmployeeModel: any);
3
+ EmployeeModel: any;
4
+ findById(employeeId: any): Promise<any>;
5
+ findByUserId(userId: any, organizationId: any): Promise<any>;
6
+ findActive(organizationId: any, options?: {}): Promise<any>;
7
+ findEmployed(organizationId: any, options?: {}): Promise<any>;
8
+ findByDepartment(organizationId: any, department: any): Promise<any>;
9
+ findEligibleForPayroll(organizationId: any, month: any, year: any): Promise<any>;
10
+ create(data: any): Promise<any>;
11
+ updateStatus(employeeId: any, status: any, context?: {}): Promise<any>;
12
+ terminate(employeeId: any, reason: any, context?: {}): Promise<any>;
13
+ updateCompensation(employeeId: any, compensation: any): Promise<any>;
14
+ getEmployeeStats(organizationId: any): Promise<{
15
+ total: any;
16
+ active: any;
17
+ employed: any;
18
+ canReceiveSalary: any;
19
+ byStatus: any;
20
+ byDepartment: any;
21
+ }>;
22
+ groupByStatus(employees: any): any;
23
+ groupByDepartment(employees: any): any;
24
+ isActive(employee: any): boolean;
25
+ isEmployed(employee: any): boolean;
26
+ canReceiveSalary(employee: any): boolean;
27
+ }
28
+ export function createEmployeeService(EmployeeModel: any): EmployeeService;
@@ -0,0 +1,30 @@
1
+ export class PayrollService {
2
+ constructor(PayrollModel: any, EmployeeService: any);
3
+ PayrollModel: any;
4
+ EmployeeService: any;
5
+ findById(payrollId: any): Promise<any>;
6
+ findByEmployee(employeeId: any, organizationId: any, options?: {}): Promise<any>;
7
+ findForPeriod(organizationId: any, month: any, year: any): Promise<any>;
8
+ findPending(organizationId: any, month: any, year: any): Promise<any>;
9
+ create(data: any): Promise<any>;
10
+ generateForEmployee(employeeId: any, organizationId: any, month: any, year: any): Promise<any>;
11
+ generateBatch(organizationId: any, month: any, year: any): Promise<{
12
+ success: boolean;
13
+ generated: number;
14
+ message: string;
15
+ payrolls?: undefined;
16
+ } | {
17
+ success: boolean;
18
+ generated: any;
19
+ payrolls: any;
20
+ message?: undefined;
21
+ }>;
22
+ markAsPaid(payrollId: any, paymentDetails?: {}): Promise<any>;
23
+ markAsProcessed(payrollId: any): Promise<any>;
24
+ calculatePeriodSummary(organizationId: any, month: any, year: any): Promise<any>;
25
+ getEmployeePayrollHistory(employeeId: any, organizationId: any, limit?: number): Promise<any>;
26
+ findByEmployeeAndPeriod(employeeId: any, organizationId: any, month: any, year: any): Promise<any>;
27
+ groupByStatus(payrolls: any): any;
28
+ getOverviewStats(organizationId: any): Promise<any>;
29
+ }
30
+ export function createPayrollService(PayrollModel: any, EmployeeService: any): PayrollService;
@@ -0,0 +1,26 @@
1
+ export function sum(items: any, key: any): any;
2
+ export function sumBy(key: any): (items: any) => any;
3
+ export function sumAllowances(items: any): any;
4
+ export function sumDeductions(items: any): any;
5
+ export function calculateGross(base: any, allowances: any): any;
6
+ export function calculateNet(gross: any, deductions: any): number;
7
+ export function calculateTotalCompensation(base: any, allowances: any, deductions: any): {
8
+ gross: any;
9
+ net: number;
10
+ deductions: any;
11
+ };
12
+ export function applyTaxBracket(amount: any, brackets: any): number;
13
+ export function calculateTax(amount: any, brackets: any): {
14
+ gross: any;
15
+ tax: number;
16
+ net: number;
17
+ };
18
+ export function proRateAmount(amount: any, workedDays: any, totalDays: any): number;
19
+ export function calculatePercentage(value: any, total: any): number;
20
+ export function applyPercentage(amount: any, percentage: any): number;
21
+ export function composeDeductions(...deductionFns: any[]): (amount: any) => any;
22
+ export function composeSalaryPipeline(base: any, operations: any): any;
23
+ export function createAllowanceCalculator(allowances: any): (base: any) => any;
24
+ export function createDeductionCalculator(deductions: any): (gross: any) => any;
25
+ export function pipe(...fns: any[]): (value: any) => any;
26
+ export function compose(...fns: any[]): (value: any) => any;
@@ -0,0 +1,35 @@
1
+ export function addDays(date: any, days: any): Date;
2
+ export function addMonths(date: any, months: any): Date;
3
+ export function addYears(date: any, years: any): Date;
4
+ export function startOfMonth(date: any): Date;
5
+ export function endOfMonth(date: any): Date;
6
+ export function startOfYear(date: any): Date;
7
+ export function endOfYear(date: any): Date;
8
+ export function isWeekday(date: any): boolean;
9
+ export function isWeekend(date: any): boolean;
10
+ export function getPayPeriod(month: any, year: any): {
11
+ month: any;
12
+ year: any;
13
+ startDate: Date;
14
+ endDate: Date;
15
+ };
16
+ export function getCurrentPeriod(date?: Date): {
17
+ year: number;
18
+ month: number;
19
+ };
20
+ export function calculateProbationEnd(hireDate: any, probationMonths: any): Date;
21
+ export function formatDateForDB(date: any): string;
22
+ export function parseDBDate(dateString: any): Date;
23
+ export function diffInDays(start: any, end: any): number;
24
+ export function diffInMonths(start: any, end: any): number;
25
+ export function daysBetween(start: any, end: any): number;
26
+ export function monthsBetween(start: any, end: any): number;
27
+ export function isDateInRange(date: any, start: any, end: any): boolean;
28
+ export function formatPeriod({ month, year }: {
29
+ month: any;
30
+ year: any;
31
+ }): string;
32
+ export function parsePeriod(periodString: any): {
33
+ month: any;
34
+ year: any;
35
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Set custom logger implementation
3
+ * @param {Object} customLogger - Logger instance with info, warn, error, debug methods
4
+ */
5
+ export function setLogger(customLogger: any): void;
6
+ export namespace logger {
7
+ function info(...args: any[]): void;
8
+ function warn(...args: any[]): void;
9
+ function error(...args: any[]): void;
10
+ function debug(...args: any[]): void;
11
+ }
12
+ export default logger;
@@ -0,0 +1,83 @@
1
+ export function toObjectId(id: any): mongoose.Types.ObjectId;
2
+ export class QueryBuilder {
3
+ constructor(initialQuery?: {});
4
+ query: {};
5
+ where(field: any, value: any): this;
6
+ whereIn(field: any, values: any): this;
7
+ whereNotIn(field: any, values: any): this;
8
+ whereGte(field: any, value: any): this;
9
+ whereLte(field: any, value: any): this;
10
+ whereBetween(field: any, start: any, end: any): this;
11
+ whereExists(field: any): this;
12
+ whereNotExists(field: any): this;
13
+ build(): {};
14
+ }
15
+ export function createQueryBuilder(initialQuery: any): QueryBuilder;
16
+ export class EmployeeQueryBuilder extends QueryBuilder {
17
+ forOrganization(organizationId: any): this;
18
+ forUser(userId: any): this;
19
+ withStatus(...statuses: any[]): this;
20
+ active(): this;
21
+ employed(): this;
22
+ inDepartment(department: any): this;
23
+ inPosition(position: any): this;
24
+ withEmploymentType(type: any): this;
25
+ hiredAfter(date: any): this;
26
+ hiredBefore(date: any): this;
27
+ }
28
+ export class PayrollQueryBuilder extends QueryBuilder {
29
+ forOrganization(organizationId: any): this;
30
+ forEmployee(employeeId: any): this;
31
+ forPeriod(month: any, year: any): this;
32
+ withStatus(...statuses: any[]): this;
33
+ paid(): this;
34
+ pending(): this;
35
+ inDateRange(start: any, end: any): this;
36
+ }
37
+ export function employee(): EmployeeQueryBuilder;
38
+ export function payroll(): PayrollQueryBuilder;
39
+ export function buildEmployeeQuery({ organizationId, userId, statuses }: {
40
+ organizationId: any;
41
+ userId: any;
42
+ statuses: any;
43
+ }): {};
44
+ export function buildPayrollQuery({ employeeId, period, statuses }: {
45
+ employeeId: any;
46
+ period: any;
47
+ statuses: any;
48
+ }): {};
49
+ export function buildAggregationPipeline(...stages: any[]): any[];
50
+ export function matchStage(query: any): {
51
+ $match: any;
52
+ };
53
+ export function groupStage(groupBy: any, aggregations: any): {
54
+ $group: any;
55
+ };
56
+ export function sortStage(sortBy: any): {
57
+ $sort: any;
58
+ };
59
+ export function limitStage(limit: any): {
60
+ $limit: any;
61
+ };
62
+ export function projectStage(fields: any): {
63
+ $project: any;
64
+ };
65
+ export function lookupStage({ from, localField, foreignField, as }: {
66
+ from: any;
67
+ localField: any;
68
+ foreignField: any;
69
+ as: any;
70
+ }): {
71
+ $lookup: {
72
+ from: any;
73
+ localField: any;
74
+ foreignField: any;
75
+ as: any;
76
+ };
77
+ };
78
+ export function unwindStage(path: any, options?: {}): {
79
+ $unwind: {
80
+ path: any;
81
+ };
82
+ };
83
+ import mongoose from 'mongoose';
@@ -0,0 +1,33 @@
1
+ export function isActive(employee: any): boolean;
2
+ export function isOnLeave(employee: any): boolean;
3
+ export function isSuspended(employee: any): boolean;
4
+ export function isTerminated(employee: any): boolean;
5
+ export function isEmployed(employee: any): boolean;
6
+ export function canReceiveSalary(employee: any): boolean;
7
+ export function canUpdateEmployment(employee: any): boolean;
8
+ export function isInProbation(employee: any, now?: Date): boolean;
9
+ export function hasCompletedProbation(employee: any, now?: Date): boolean;
10
+ export function hasCompensation(employee: any): boolean;
11
+ export function isEligibleForBonus(employee: any, requiredMonths?: number): boolean;
12
+ export function isValidCompensation(compensation: any): any;
13
+ export function isValidBankDetails(bankDetails: any): any;
14
+ export function hasRequiredFields(obj: any, fields: any): any;
15
+ export function createValidator(validationFns: any): (data: any) => {
16
+ isValid: boolean;
17
+ errors: {
18
+ field: string;
19
+ message: any;
20
+ }[];
21
+ };
22
+ export function required(fieldName: any): (value: any) => string | true;
23
+ export function min(minValue: any, fieldName: any): (value: any) => string | true;
24
+ export function max(maxValue: any, fieldName: any): (value: any) => string | true;
25
+ export function inRange(minValue: any, maxValue: any, fieldName: any): (value: any) => string | true;
26
+ export function oneOf(allowedValues: any, fieldName: any): (value: any) => string | true;
27
+ export function compose(...validators: any[]): (value: any, data: any) => any;
28
+ export function isPositive(fieldName: any): (value: any) => string | true;
29
+ export function isValidStatus(value: any): boolean;
30
+ export function isValidEmploymentType(value: any): boolean;
31
+ export function minValue(minValue: any, fieldName: any): (value: any) => string | true;
32
+ export function maxValue(maxValue: any, fieldName: any): (value: any) => string | true;
33
+ export function isInRange(minValue: any, maxValue: any, fieldName: any): (value: any) => string | true;
package/package.json CHANGED
@@ -1,21 +1,34 @@
1
1
  {
2
2
  "name": "@classytic/payroll",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Modern HRM and payroll management library for Node.js applications",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
- "types": "./payroll.d.ts",
7
+ "types": "./dist/types/index.d.ts",
8
8
  "exports": {
9
- ".": "./src/index.js",
10
- "./init": "./src/init.js",
11
- "./service": "./src/service.js",
12
- "./adapters/*": "./src/adapters/*.js",
13
- "./events/*": "./src/events/*.js",
14
- "./workflows/*": "./src/workflows/*.js",
15
- "./schemas/*": "./src/schemas/*.js"
9
+ ".": {
10
+ "types": "./dist/types/index.d.ts",
11
+ "import": "./src/index.js"
12
+ },
13
+ "./init": {
14
+ "types": "./dist/types/init.d.ts",
15
+ "import": "./src/init.js"
16
+ },
17
+ "./service": {
18
+ "types": "./dist/types/service.d.ts",
19
+ "import": "./src/service.js"
20
+ },
21
+ "./schemas/*": {
22
+ "types": "./dist/types/schemas/*.d.ts",
23
+ "import": "./src/schemas/*.js"
24
+ }
16
25
  },
17
26
  "files": [
18
27
  "src/**/*.js",
28
+ "!src/**/*.test.js",
29
+ "!src/**/*.spec.js",
30
+ "!src/**/__tests__/**",
31
+ "dist/types/",
19
32
  "payroll.d.ts",
20
33
  "README.md",
21
34
  "LICENSE"
@@ -42,20 +55,26 @@
42
55
  },
43
56
  "homepage": "https://github.com/classytic/payroll#readme",
44
57
  "peerDependencies": {
45
- "mongoose": "^8.0.0"
58
+ "mongoose": "^8.0.0 || ^9.0.0"
46
59
  },
47
60
  "devDependencies": {
48
- "mongoose": "^8.8.1",
61
+ "mongoose": "^9.0.0",
49
62
  "mongoose-aggregate-paginate-v2": "^1.1.4",
50
- "mongoose-paginate-v2": "^1.9.0"
63
+ "mongoose-paginate-v2": "^1.9.0",
64
+ "@types/node": "^22.8.7",
65
+ "typescript": "^5.6.3"
51
66
  },
52
67
  "engines": {
53
68
  "node": ">=18.0.0"
54
69
  },
55
70
  "scripts": {
71
+ "types": "tsc --project tsconfig.types.json",
72
+ "build": "npm run types",
73
+ "prepublishOnly": "npm run build",
56
74
  "example:basic": "node test/examples/basic-usage.js",
57
75
  "example:mongoose": "node test/examples/with-mongoose.js",
58
76
  "example:workflow": "node test/examples/full-workflow.js",
59
- "test": "npm run example:basic && npm run example:mongoose && npm run example:workflow"
77
+ "test:v9": "node test/employee-plugin-v9.test.js",
78
+ "test": "npm run example:basic && npm run example:mongoose && npm run example:workflow && npm run test:v9"
60
79
  }
61
80
  }
@@ -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
- * Batch Payroll Factory - Process multiple employees
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) => ({