formula-parser-payroll 2.1.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 (58) hide show
  1. package/README.md +202 -0
  2. package/dist/database/database-connector.d.ts +60 -0
  3. package/dist/database/database-connector.d.ts.map +1 -0
  4. package/dist/database/database-connector.js +9 -0
  5. package/dist/database/database-connector.js.map +1 -0
  6. package/dist/database/helpers.d.ts +44 -0
  7. package/dist/database/helpers.d.ts.map +1 -0
  8. package/dist/database/helpers.js +120 -0
  9. package/dist/database/helpers.js.map +1 -0
  10. package/dist/database/index.d.ts +11 -0
  11. package/dist/database/index.d.ts.map +1 -0
  12. package/dist/database/index.js +29 -0
  13. package/dist/database/index.js.map +1 -0
  14. package/dist/database/payroll-formula.service.d.ts +118 -0
  15. package/dist/database/payroll-formula.service.d.ts.map +1 -0
  16. package/dist/database/payroll-formula.service.js +794 -0
  17. package/dist/database/payroll-formula.service.js.map +1 -0
  18. package/dist/database/types.d.ts +117 -0
  19. package/dist/database/types.d.ts.map +1 -0
  20. package/dist/database/types.js +9 -0
  21. package/dist/database/types.js.map +1 -0
  22. package/dist/formula-engine.d.ts +18 -0
  23. package/dist/formula-engine.d.ts.map +1 -0
  24. package/dist/formula-engine.js +356 -0
  25. package/dist/formula-engine.js.map +1 -0
  26. package/dist/formula-parser.d.ts +60 -0
  27. package/dist/formula-parser.d.ts.map +1 -0
  28. package/dist/formula-parser.js +366 -0
  29. package/dist/formula-parser.js.map +1 -0
  30. package/dist/index.d.ts +13 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +44 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/nestjs/database-connector.d.ts +60 -0
  35. package/dist/nestjs/database-connector.d.ts.map +1 -0
  36. package/dist/nestjs/database-connector.js +9 -0
  37. package/dist/nestjs/database-connector.js.map +1 -0
  38. package/dist/nestjs/helpers.d.ts +44 -0
  39. package/dist/nestjs/helpers.d.ts.map +1 -0
  40. package/dist/nestjs/helpers.js +120 -0
  41. package/dist/nestjs/helpers.js.map +1 -0
  42. package/dist/nestjs/index.d.ts +11 -0
  43. package/dist/nestjs/index.d.ts.map +1 -0
  44. package/dist/nestjs/index.js +29 -0
  45. package/dist/nestjs/index.js.map +1 -0
  46. package/dist/nestjs/payroll-formula.service.d.ts +91 -0
  47. package/dist/nestjs/payroll-formula.service.d.ts.map +1 -0
  48. package/dist/nestjs/payroll-formula.service.js +640 -0
  49. package/dist/nestjs/payroll-formula.service.js.map +1 -0
  50. package/dist/nestjs/types.d.ts +117 -0
  51. package/dist/nestjs/types.d.ts.map +1 -0
  52. package/dist/nestjs/types.js +9 -0
  53. package/dist/nestjs/types.js.map +1 -0
  54. package/dist/types.d.ts +168 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +9 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +39 -0
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # payroll-formula-parser
2
+
3
+ > A lightweight, high-performance payroll formula parser. Parse and evaluate payroll formulas with employee data variables.
4
+
5
+ ## 📦 Installation
6
+
7
+ ```bash
8
+ npm install payroll-formula-parser
9
+ ```
10
+
11
+ ## 🚀 Quick Start
12
+
13
+ ### Basic Usage
14
+
15
+ ```typescript
16
+ import { PayrollFormulaService } from 'payroll-formula-parser';
17
+
18
+ const service = new PayrollFormulaService(n7);
19
+
20
+ // Parse formula for a single employee
21
+ const result = await service.parseByEmpId({
22
+ formula: 'SALARY * 0.1 + AL_001',
23
+ empId: 'EMP001',
24
+ auth: {
25
+ conn: mysqlConnection, // Your database connection
26
+ connFin: mysqlConnection, // Financial DB connection
27
+ userData: {
28
+ companyId: '1',
29
+ companyCode: 'COMP001',
30
+ taxCountry: 'ID'
31
+ }
32
+ }
33
+ });
34
+
35
+ console.log(result.hasil); // Formula result
36
+ ```
37
+
38
+ ### Processing Multiple Employees
39
+
40
+ ```typescript
41
+ // Process multiple employees in parallel (with automatic chunking)
42
+ const results = await service.parseByEmpId({
43
+ formula: 'SALARY * 0.1 + AL_001',
44
+ listEmpId: ['EMP001', 'EMP002', 'EMP003', ...], // Can handle thousands!
45
+ auth: authContext
46
+ });
47
+
48
+ // Results: { EMP001: 5000, EMP002: 6000, EMP003: 5500, ... }
49
+ ```
50
+
51
+ ### Formula Validation
52
+
53
+ ```typescript
54
+ // Validate formula syntax before execution
55
+ const validation = await service.formulaValidityCheck({
56
+ formula: 'IF(GRADE = "A", SALARY * 1.2, SALARY)',
57
+ auth: authContext
58
+ });
59
+
60
+ console.log(validation.result); // 'success' or error message
61
+ ```
62
+
63
+ ## 📚 Supported Formula Syntax
64
+
65
+ ### Variables
66
+
67
+ - **Employee Data**: `SALARY`, `GRADE`, `POSITION`, `DEPARTMENT`, `COSTCENTER`, etc.
68
+ - **Payroll Components**: `AL_001`, `DE_002`, `NE_003` (Allowances, Deductions, Net Earnings)
69
+ - **Custom Fields**: `CUSTOMFIELD1` through `CUSTOMFIELD10`
70
+ - **Dates**: `JOINDATE`, `STARTDATE`, `ENDDATE`, `BIRTHDATE`, etc.
71
+
72
+ ### Functions
73
+
74
+ #### Logical Functions
75
+ - `IF(condition, true_value, false_value)`
76
+ - `AND(condition1, condition2, ...)`
77
+ - `OR(condition1, condition2, ...)`
78
+ - `NOT(condition)`
79
+
80
+ #### Math Functions
81
+ - `ROUND(number, decimals)`
82
+ - `ROUNDUP(number, decimals)`
83
+ - `ROUNDDOWN(number, decimals)`
84
+ - `TRUNC(number)`
85
+ - `MIN(value1, value2, ...)`
86
+ - `MAX(value1, value2, ...)`
87
+ - `MOD(number, divisor)`
88
+
89
+ #### Date Functions
90
+ - `TODAY()` - Current date
91
+ - `DATETIME_NOW()` - Current datetime
92
+ - `DATE(year, month, day)`
93
+ - `YEAR(date)`, `MONTH(date)`, `DAY(date)`
94
+ - `DATEDIFF(date1, date2, unit)`
95
+ - `DATEADD(date, number, unit)`
96
+ - `DAYSINMONTH(date)`
97
+ - `DAYOFWEEK(date)`
98
+ - `LENGTHOFSERVICE(startDate, endDate, unit)`
99
+
100
+ #### String Functions
101
+ - `CONCATENATE(str1, str2, ...)`
102
+ - `CONCATENATESKIPNULL(str1, str2, ...)`
103
+ - `FINDLIST(value, list, delimiter)`
104
+
105
+ #### Other Functions
106
+ - `ISNUMERIC(value)`
107
+ - `ISDATE(value)`
108
+ - `CHILDDEPENDENTS` - Count of child dependents
109
+
110
+ ### Example Formulas
111
+
112
+ ```typescript
113
+ // Conditional bonus based on grade
114
+ 'IF(GRADE = "A", SALARY * 0.2, SALARY * 0.1)'
115
+
116
+ // Complex calculation with multiple conditions
117
+ 'IF(AND(GRADE = "A", LENGTHOFSERVICE(JOINDATE, TODAY(), "Y") > 5), SALARY * 1.5, SALARY)'
118
+
119
+ // Date-based calculation
120
+ 'IF(DATEDIFF(TODAY(), JOINDATE, "M") > 12, AL_001 * 1.1, AL_001)'
121
+
122
+ // Rounding
123
+ 'ROUND(SALARY * 0.15, 2)'
124
+ ```
125
+
126
+ ## ⚡ Performance Optimizations
127
+
128
+ ### Automatic Chunking
129
+ When processing large employee lists, the service automatically chunks them into batches of 50 to prevent memory overflow while maintaining parallel processing speed.
130
+
131
+ ```typescript
132
+ // Processes 1000 employees in 20 chunks of 50 (parallel within each chunk)
133
+ const results = await service.parseByEmpId({
134
+ formula: 'SALARY * 0.1',
135
+ listEmpId: [...1000employees], // Automatically chunked!
136
+ auth: authContext
137
+ });
138
+ ```
139
+
140
+ ### Smart Component Detection
141
+ Only fetches payroll components that are actually used in the formula:
142
+
143
+ ```typescript
144
+ // Formula: 'AL_001 + AL_002'
145
+ // ✅ Only fetches AL_001 and AL_002 from database
146
+ // ❌ Doesn't fetch all 100+ components
147
+ ```
148
+
149
+ ### Chunked Decryption
150
+ Decrypts employee component values in batches of 20 to balance speed and resource usage.
151
+
152
+ ### Caching
153
+ - **Reserved words cache**: 5-minute TTL
154
+ - **Component list cache**: 5-minute TTL
155
+ - Clear cache manually: `service.clearCache()` or `service.clearCacheForCompany(companyId, taxCountry)`
156
+
157
+ ## 📖 API Reference
158
+
159
+ ### `PayrollFormulaService`
160
+
161
+ #### `parseByEmpId(input: ParseByEmpIdInput)`
162
+
163
+ Parse formula for one or multiple employees.
164
+
165
+ **Parameters:**
166
+ - `formula` (string): The formula to parse
167
+ - `empId` (string, optional): Single employee ID
168
+ - `listEmpId` (string[], optional): Multiple employee IDs
169
+ - `auth` (AuthContext): Authentication and database context
170
+
171
+ **Returns:**
172
+ - Single employee: `FormulaParseResultLegacy` with `hasil` and `message`
173
+ - Multiple employees: `Record<empId, result>`
174
+
175
+ #### `formulaValidityCheck(input: { formula: string; auth: AuthContext })`
176
+
177
+ Validate formula syntax.
178
+
179
+ **Returns:**
180
+ - `{ result: 'success' }` or throws error with details
181
+
182
+ #### `clearCache()`
183
+
184
+ Clear all caches.
185
+
186
+ #### `clearCacheForCompany(companyId: string, taxCountry: string)`
187
+
188
+ Clear cache for specific company.
189
+
190
+ ## 🏗️ Architecture
191
+
192
+ ```
193
+ src/
194
+ ├── formula-engine.ts # Core formula parser (hot-formula-parser wrapper)
195
+ ├── formula-parser.ts # Variable processing logic
196
+ ├── types.ts # Type definitions
197
+ └── database/
198
+ ├── payroll-formula.service.ts # Main service with optimizations
199
+ ├── database-connector.ts # Database interface
200
+ ├── helpers.ts # Utility functions
201
+ └── types.ts # Database-specific types
202
+ ```
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Database Connector Interface
3
+ *
4
+ * Generic database connector that can work with any database client
5
+ * (MySQL2, TypeORM, Knex, Sequelize, etc.)
6
+ */
7
+ /**
8
+ * Generic database connection interface
9
+ * Any database client that implements this interface can be used
10
+ */
11
+ export interface IDatabaseConnection {
12
+ /**
13
+ * Execute a raw SQL query with optional parameters
14
+ * @param sql SQL query string with placeholders (?)
15
+ * @param params Query parameters
16
+ * @returns Promise with query results
17
+ */
18
+ query<T = any>(sql: string, params?: any[]): Promise<T[]>;
19
+ }
20
+ /**
21
+ * Configuration for database connections
22
+ */
23
+ export interface DatabaseConfig {
24
+ /** Main database connection (for employee/organization data) */
25
+ mainConnection: IDatabaseConnection;
26
+ /** Finance database connection (for payroll/component data) */
27
+ financeConnection: IDatabaseConnection;
28
+ }
29
+ /**
30
+ * Company and user context for queries
31
+ */
32
+ export interface CompanyContext {
33
+ /** Company ID */
34
+ companyId: string | number;
35
+ /** Company Code */
36
+ companyCode: string;
37
+ /** Tax Country Code (ID, TH, MY, PH) */
38
+ taxCountry: 'ID' | 'TH' | 'MY' | 'PH';
39
+ }
40
+ /**
41
+ * Encryption configuration for decrypting component values
42
+ */
43
+ export interface EncryptionConfig {
44
+ /** P Number for decryption function */
45
+ pNumber: string;
46
+ /** L Number for decryption function */
47
+ lNumber: string;
48
+ }
49
+ /**
50
+ * Complete context for formula parsing with database
51
+ */
52
+ export interface FormulaContext {
53
+ /** Database connections */
54
+ database: DatabaseConfig;
55
+ /** Company and user context */
56
+ company: CompanyContext;
57
+ /** Encryption config (optional - needed only if components are encrypted) */
58
+ encryption?: EncryptionConfig;
59
+ }
60
+ //# sourceMappingURL=database-connector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-connector.d.ts","sourceRoot":"","sources":["../../src/database/database-connector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,cAAc,EAAE,mBAAmB,CAAC;IAEpC,+DAA+D;IAC/D,iBAAiB,EAAE,mBAAmB,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,iBAAiB;IACjB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAE3B,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,wCAAwC;IACxC,UAAU,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAEhB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,2BAA2B;IAC3B,QAAQ,EAAE,cAAc,CAAC;IAEzB,+BAA+B;IAC/B,OAAO,EAAE,cAAc,CAAC;IAExB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Database Connector Interface
4
+ *
5
+ * Generic database connector that can work with any database client
6
+ * (MySQL2, TypeORM, Knex, Sequelize, etc.)
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ //# sourceMappingURL=database-connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-connector.js","sourceRoot":"","sources":["../../src/database/database-connector.ts"],"names":[],"mappings":";AAAA;;;;;GAKG"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * NestJS Module Helpers for Payroll Formula Parser
3
+ *
4
+ * Helper functions for database operations and data processing.
5
+ */
6
+ import { AuthContext, FormulaContext } from './types';
7
+ /**
8
+ * Get currency code based on tax country
9
+ */
10
+ export declare function getCurrencyCode(taxCountry: string): string;
11
+ /**
12
+ * Decrypt a value using database function
13
+ */
14
+ export declare function decryptValue(value: string, auth: AuthContext, empId: string): Promise<number>;
15
+ /**
16
+ * Check if position-related data is needed
17
+ */
18
+ export declare function needsPositionData(words: Set<string>): boolean;
19
+ /**
20
+ * Check if cost center data is needed
21
+ */
22
+ export declare function needsCostCenterData(words: Set<string>): boolean;
23
+ /**
24
+ * Check if grade data is needed
25
+ */
26
+ export declare function needsGradeData(words: Set<string>): boolean;
27
+ /**
28
+ * Check if work location data is needed
29
+ */
30
+ export declare function needsWorkLocationData(words: Set<string>): boolean;
31
+ /**
32
+ * Check if custom field data is needed
33
+ */
34
+ export declare function needsCustomFieldData(words: Set<string>): boolean;
35
+ /**
36
+ * Format name for formula with proper case handling
37
+ */
38
+ export declare function formatNameForFormula(name: string, formula: string): string;
39
+ /**
40
+ * Convert legacy AuthContext to new FormulaContext
41
+ * This helps with backward compatibility
42
+ */
43
+ export declare function convertAuthToFormulaContext(auth: AuthContext): FormulaContext;
44
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/database/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAoB,cAAc,EAAE,MAAM,SAAS,CAAC;AAExE;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAejB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAK7D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAE/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAEjE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAKhE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAc1E;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,WAAW,GAAG,cAAc,CAgB7E"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ /**
3
+ * NestJS Module Helpers for Payroll Formula Parser
4
+ *
5
+ * Helper functions for database operations and data processing.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.getCurrencyCode = getCurrencyCode;
9
+ exports.decryptValue = decryptValue;
10
+ exports.needsPositionData = needsPositionData;
11
+ exports.needsCostCenterData = needsCostCenterData;
12
+ exports.needsGradeData = needsGradeData;
13
+ exports.needsWorkLocationData = needsWorkLocationData;
14
+ exports.needsCustomFieldData = needsCustomFieldData;
15
+ exports.formatNameForFormula = formatNameForFormula;
16
+ exports.convertAuthToFormulaContext = convertAuthToFormulaContext;
17
+ /**
18
+ * Get currency code based on tax country
19
+ */
20
+ function getCurrencyCode(taxCountry) {
21
+ switch (taxCountry) {
22
+ case 'TH': return 'THB';
23
+ case 'PH': return 'PHP';
24
+ case 'MY': return 'MYR';
25
+ default: return 'IDR';
26
+ }
27
+ }
28
+ /**
29
+ * Decrypt a value using database function
30
+ */
31
+ async function decryptValue(value, auth, empId) {
32
+ try {
33
+ const q = `SELECT SF2356896('${value}',
34
+ '${auth.accessToken.confParse.PNUMBER}',
35
+ '${auth.accessToken.confParse.LNUMBER}',
36
+ '${empId}') AS result`;
37
+ const result = await auth.connFin.query(q);
38
+ if (result.length > 0) {
39
+ return result[0].result;
40
+ }
41
+ return 0;
42
+ }
43
+ catch (error) {
44
+ return 0;
45
+ }
46
+ }
47
+ /**
48
+ * Check if position-related data is needed
49
+ */
50
+ function needsPositionData(words) {
51
+ return words.has('DEPTNAME') ||
52
+ words.has('POSITIONNAME') ||
53
+ words.has('POSITIONCODE') ||
54
+ words.has('DEPTCODE');
55
+ }
56
+ /**
57
+ * Check if cost center data is needed
58
+ */
59
+ function needsCostCenterData(words) {
60
+ return words.has('COSTCENTER') || words.has('COSTCENTERCODE');
61
+ }
62
+ /**
63
+ * Check if grade data is needed
64
+ */
65
+ function needsGradeData(words) {
66
+ return words.has('GRADE') || words.has('GRDCODE');
67
+ }
68
+ /**
69
+ * Check if work location data is needed
70
+ */
71
+ function needsWorkLocationData(words) {
72
+ return words.has('WORKLOCATION') || words.has('WORKLOCATIONCODE');
73
+ }
74
+ /**
75
+ * Check if custom field data is needed
76
+ */
77
+ function needsCustomFieldData(words) {
78
+ for (let i = 1; i <= 10; i++) {
79
+ if (words.has(`CUSTOMFIELD${i}`))
80
+ return true;
81
+ }
82
+ return false;
83
+ }
84
+ /**
85
+ * Format name for formula with proper case handling
86
+ */
87
+ function formatNameForFormula(name, formula) {
88
+ if (!name)
89
+ return '""';
90
+ const upperName = name.replace(/ /g, '').toUpperCase();
91
+ const normalName = name;
92
+ const hasUpperInFormula = formula.includes(`"${upperName}"`) ||
93
+ formula.includes(`'${upperName}'`);
94
+ if (hasUpperInFormula) {
95
+ return `"${upperName}"`;
96
+ }
97
+ return `"${normalName}"`;
98
+ }
99
+ /**
100
+ * Convert legacy AuthContext to new FormulaContext
101
+ * This helps with backward compatibility
102
+ */
103
+ function convertAuthToFormulaContext(auth) {
104
+ return {
105
+ database: {
106
+ mainConnection: auth.conn,
107
+ financeConnection: auth.connFin,
108
+ },
109
+ company: {
110
+ companyId: auth.userData.companyId,
111
+ companyCode: auth.userData.companyCode || auth.userData.currentCompanyCode || '',
112
+ taxCountry: (auth.userData.taxCountry || 'ID'),
113
+ },
114
+ encryption: auth.accessToken?.confParse ? {
115
+ pNumber: auth.accessToken.confParse.PNUMBER,
116
+ lNumber: auth.accessToken.confParse.LNUMBER,
117
+ } : undefined,
118
+ };
119
+ }
120
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/database/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * NestJS Module for Payroll Formula Parser
3
+ *
4
+ * This module provides database-integrated formula parsing.
5
+ * Works with any database client that implements the IDatabaseConnection interface.
6
+ */
7
+ export * from './database-connector';
8
+ export * from './types';
9
+ export * from './helpers';
10
+ export { PayrollFormulaService } from './payroll-formula.service';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/database/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,sBAAsB,CAAC;AACrC,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * NestJS Module for Payroll Formula Parser
4
+ *
5
+ * This module provides database-integrated formula parsing.
6
+ * Works with any database client that implements the IDatabaseConnection interface.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.PayrollFormulaService = void 0;
24
+ __exportStar(require("./database-connector"), exports);
25
+ __exportStar(require("./types"), exports);
26
+ __exportStar(require("./helpers"), exports);
27
+ var payroll_formula_service_1 = require("./payroll-formula.service");
28
+ Object.defineProperty(exports, "PayrollFormulaService", { enumerable: true, get: function () { return payroll_formula_service_1.PayrollFormulaService; } });
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/database/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;AAEH,uDAAqC;AACrC,0CAAwB;AACxB,4CAA0B;AAC1B,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * NestJS Payroll Formula Parser Service
3
+ *
4
+ * This service provides database-integrated formula parsing.
5
+ * It fetches employee data and component values from the database
6
+ * and then uses the core formula parser.
7
+ */
8
+ import { AuthContext, ParseByEmpIdInput, FormulaParseResultLegacy } from './types';
9
+ /**
10
+ * Payroll Formula Parser Service
11
+ *
12
+ * Use this service when you need to parse formulas with just formula and empId.
13
+ * This service handles fetching employee data and component values from the database.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const service = new PayrollFormulaService();
18
+ * const result = await service.parseByEmpId({
19
+ * formula: 'SALARY * 0.1 + AL_001',
20
+ * empId: 'EMP001',
21
+ * auth: authContext,
22
+ * });
23
+ * console.log(result.result);
24
+ * ```
25
+ */
26
+ export declare class PayrollFormulaService {
27
+ private reservedWordsCache;
28
+ private componentListCache;
29
+ private readonly CACHE_TTL;
30
+ private readonly CHUNK_SIZE;
31
+ /**
32
+ * Parse formula by employee ID(s)
33
+ * This method fetches all required data from database and evaluates the formula
34
+ *
35
+ * When listEmpId is provided: returns Record<empId, hasil>
36
+ * When empId is provided: returns FormulaParseResultLegacy
37
+ */
38
+ parseByEmpId(input: ParseByEmpIdInput): Promise<FormulaParseResultLegacy | Record<string, number | string | boolean>>;
39
+ /**
40
+ * Check if a formula is valid
41
+ * This ports the logic from payroll-server's formulaValidtyCheck
42
+ */
43
+ formulaValidityCheck(input: {
44
+ formula: string;
45
+ auth: AuthContext;
46
+ }): Promise<{
47
+ result: string;
48
+ }>;
49
+ /**
50
+ * Clear all caches (useful for testing or when data is updated)
51
+ */
52
+ clearCache(): void;
53
+ /**
54
+ * Clear cache for specific company
55
+ */
56
+ clearCacheForCompany(companyId: string, taxCountry: string): void;
57
+ /**
58
+ * Parse formula for a single employee
59
+ * Internal method used by parseByEmpId
60
+ */
61
+ private parseForSingleEmployee;
62
+ /**
63
+ * Parse formula for multiple employees
64
+ */
65
+ parseForMultipleEmployees(formula: string, empIds: string[], auth: AuthContext): Promise<Record<string, FormulaParseResultLegacy>>;
66
+ /**
67
+ * Get list of component codes
68
+ */
69
+ private getComponentList;
70
+ /**
71
+ * Get all components for company
72
+ */
73
+ private getAllComponents;
74
+ /**
75
+ * Get employee component values
76
+ */
77
+ private getEmployeeComponents;
78
+ /**
79
+ * OPTIMIZATION: Batch get employee components for multiple employees
80
+ * This reduces database roundtrips when processing multiple employees
81
+ */
82
+ private getBatchEmployeeComponents;
83
+ /**
84
+ * Get employee data with relations
85
+ */
86
+ private getEmployeeData;
87
+ /**
88
+ * OPTIMIZATION: Batch get employee data for multiple employees
89
+ * This reduces database roundtrips significantly
90
+ */
91
+ private getBatchEmployeeData;
92
+ /**
93
+ * Get reserved words list for formula processing
94
+ */
95
+ private getReservedWords;
96
+ /**
97
+ * Extract required words from formula
98
+ */
99
+ private extractRequiredWordsFromFormula;
100
+ /**
101
+ * Batch load all required data for formula parsing
102
+ */
103
+ private batchLoadFormulaData;
104
+ /**
105
+ * Convert raw employee data to EmployeeData interface
106
+ */
107
+ private convertToEmployeeData;
108
+ /**
109
+ * Convert cache to OrganizationalData interface
110
+ */
111
+ private convertToOrganizationalData;
112
+ /**
113
+ * OPTIMIZATION: Utility to chunk array for batched processing
114
+ * This prevents memory overflow when processing thousands of items
115
+ */
116
+ private chunkArray;
117
+ }
118
+ //# sourceMappingURL=payroll-formula.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payroll-formula.service.d.ts","sourceRoot":"","sources":["../../src/database/payroll-formula.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,OAAO,EACL,WAAW,EACX,iBAAiB,EAGjB,wBAAwB,EACzB,MAAM,SAAS,CAAC;AAWjB;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,qBAAqB;IAEhC,OAAO,CAAC,kBAAkB,CAA2E;IACrG,OAAO,CAAC,kBAAkB,CAA2F;IACrH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;IAEjC;;;;;;OAMG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IA0C3H;;;OAGG;IACG,oBAAoB,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IA0KtG;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAMjE;;;OAGG;YACW,sBAAsB;IAyLpC;;OAEG;IACG,yBAAyB,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAYpD;;OAEG;YACW,gBAAgB;IAiC9B;;OAEG;YACW,gBAAgB;IAmB9B;;OAEG;YACW,qBAAqB;IAqBnC;;;OAGG;YACW,0BAA0B;IAqCxC;;OAEG;YACW,eAAe;IAkC7B;;;OAGG;YACW,oBAAoB;IA4ClC;;OAEG;YACW,gBAAgB;IAuC9B;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAavC;;OAEG;YACW,oBAAoB;IAyHlC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA8B7B;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAgBnC;;;OAGG;IACH,OAAO,CAAC,UAAU;CAOnB"}