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
@@ -0,0 +1,640 @@
1
+ "use strict";
2
+ /**
3
+ * NestJS Payroll Formula Parser Service
4
+ *
5
+ * This service provides database-integrated formula parsing.
6
+ * It fetches employee data and component values from the database
7
+ * and then uses the core formula parser.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.PayrollFormulaService = void 0;
11
+ const formula_engine_1 = require("../formula-engine");
12
+ const formula_parser_1 = require("../formula-parser");
13
+ const helpers_1 = require("./helpers");
14
+ /**
15
+ * Payroll Formula Parser Service
16
+ *
17
+ * Use this service when you need to parse formulas with just formula and empId.
18
+ * This service handles fetching employee data and component values from the database.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const service = new PayrollFormulaService();
23
+ * const result = await service.parseByEmpId({
24
+ * formula: 'SALARY * 0.1 + AL_001',
25
+ * empId: 'EMP001',
26
+ * auth: authContext,
27
+ * });
28
+ * console.log(result.result);
29
+ * ```
30
+ */
31
+ class PayrollFormulaService {
32
+ /**
33
+ * Parse formula by employee ID(s)
34
+ * This method fetches all required data from database and evaluates the formula
35
+ *
36
+ * When listEmpId is provided: returns Record<empId, hasil>
37
+ * When empId is provided: returns FormulaParseResultLegacy
38
+ */
39
+ async parseByEmpId(input) {
40
+ const { formula: rawFormula, empId, listEmpId, auth } = input;
41
+ console.log('>>> PayrollFormulaService.parseByEmpId CALLED', { rawFormula, listEmpIdLen: listEmpId?.length });
42
+ // If listEmpId is provided, process multiple employees
43
+ if (listEmpId && listEmpId.length > 0) {
44
+ const resultData = {};
45
+ for (const emp of listEmpId) {
46
+ const res = await this.parseForSingleEmployee(rawFormula, emp, auth);
47
+ resultData[emp] = res.hasil;
48
+ }
49
+ return resultData;
50
+ }
51
+ // Single employee processing
52
+ if (!empId) {
53
+ return {
54
+ hasil: 0,
55
+ message: 'Either empId or listEmpId must be provided',
56
+ };
57
+ }
58
+ return this.parseForSingleEmployee(rawFormula, empId, auth);
59
+ }
60
+ /**
61
+ * Check if a formula is valid
62
+ * This ports the logic from payroll-server's formulaValidtyCheck
63
+ */
64
+ async formulaValidityCheck(input) {
65
+ const { formula: rawFormula, auth } = input;
66
+ try {
67
+ if (!rawFormula) {
68
+ throw new Error('Formula cannot be empty');
69
+ }
70
+ const formula = rawFormula.replace(/"/g, `'`);
71
+ // 1. Get reserved words from DB
72
+ const getWordList = await this.getReservedWords(auth);
73
+ const reservedWords = new Set(getWordList.words2); // words2 contains allowdeductCode
74
+ // 2. Extra keywords that are always valid
75
+ // Added more from server logic
76
+ const extraValid = new Set([
77
+ 'IF', 'AND', 'OR', 'NOT', 'TRUE', 'FALSE', 'SALARY',
78
+ 'MIN', 'MAX', 'MOD', 'ROUND', 'ROUNDDOWN', 'ROUNDUP', 'TRUNC',
79
+ 'DATE', 'DAYS', 'TODAY', 'DATETIME_NOW', 'ISDATE', 'DAY', 'MONTH', 'YEAR',
80
+ 'DAYSINMONTH', 'DAYOFWEEK', 'ISNUMERIC', 'HOUR', 'MINUTE', 'SECOND',
81
+ 'DATEDIFF', 'DATEADD', 'CONCATENATE', 'CONCATENATESKIPNULL', 'FINDLIST', 'CREATEDATE',
82
+ 'LENGTHOFSERVICE', 'CHILDDEPENDENTS',
83
+ 'CUSTOMFIELD', // Base word
84
+ ]);
85
+ // 3. Handle String Literals first!
86
+ // Anything inside quotes should NOT be validated as a variable.
87
+ // Replace quoted strings with placeholders
88
+ const formulaNoStrings = formula.replace(/'[^']*'/g, 'STRING_LITERAL');
89
+ // 4. Extract all alpha tokens (potential variables/functions)
90
+ // This regex matches words like GRADE, CUSTOMFIELD5, AL_001, etc.
91
+ // We use the formula WITHOUT strings to check tokens.
92
+ const tokens = formulaNoStrings.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g) || [];
93
+ for (const token of tokens) {
94
+ const upperToken = token.toUpperCase();
95
+ // Skip placeholders
96
+ if (upperToken === 'STRING_LITERAL')
97
+ continue;
98
+ // Skip if it's a reserved word or a known function/keyword
99
+ if (reservedWords.has(upperToken) || extraValid.has(upperToken)) {
100
+ continue;
101
+ }
102
+ // Special handling for CUSTOMFIELD1 - CUSTOMFIELD10
103
+ if (/^CUSTOMFIELD\d+$/.test(upperToken)) {
104
+ continue;
105
+ }
106
+ // Skip if it's a payroll component code (AL_xxx, DE_xxx, NE_xxx)
107
+ if (/^(AL|DE|NE)_\d+$/i.test(token)) {
108
+ continue;
109
+ }
110
+ // Potential typo or invalid keyword
111
+ throw new Error(`Failed not defined reserve word or formula is not valid: ${token}`);
112
+ }
113
+ // 5. Final syntax check by attempting a dummy parse
114
+ // We need to replace all valid tokens with dummy values, otherwise the parser will complain about #NAME?
115
+ let dummyFormula = formula;
116
+ // Sort tokens by length (desc) to avoid partial replacement
117
+ const sortedTokens = [...new Set(tokens)].sort((a, b) => b.length - a.length);
118
+ for (const token of sortedTokens) {
119
+ // Replace token with "0" (as string) or 0 (as number)
120
+ // Since we don't know the type, let's use 0 which is safe for most math/logic
121
+ // Use regex for word boundary replacement
122
+ const regex = new RegExp(`\\b${token}\\b`, 'g');
123
+ dummyFormula = dummyFormula.replace(regex, '0');
124
+ }
125
+ // Restore string literals (they were replaced by 'STRING_LITERAL' in token check step? No, that was a copy)
126
+ // wait, 'tokens' were extracted from 'formulaNoStrings'.
127
+ // 'dummyFormula' starts from original 'formula' (which has strings).
128
+ // If we replace tokens in original formula, we might accidentally replace content inside strings!
129
+ // But we know 'tokens' are extracted from outside strings.
130
+ // Safer approach:
131
+ // We already validated all tokens are "legal".
132
+ // The only reason to run parseFormula is to check parentheses balance, commas in functions, etc.
133
+ // So let's run parseFormula on the dummy-filled string.
134
+ // But we must be careful not to replace text inside quotes.
135
+ // E.g. IF(GRADE = "GRADE", ...) -> The second GRADE is string.
136
+ // Strategy:
137
+ // 1. Hide strings placeholders
138
+ const regexKutip = /'[^']*'/g;
139
+ let match;
140
+ const placeholders = {};
141
+ let pIdx = 0;
142
+ let formulaWithPlaceholders = formula.replace(regexKutip, (m) => {
143
+ const key = `__STR_${pIdx++}__`;
144
+ placeholders[key] = m; // equivalent to "0" for parsing safety?
145
+ // Actually, for syntax check, a string literal is just a value.
146
+ // Let's replace it with "0" (string "0") to be safe?
147
+ // Or just keep it as a string literal but simple one like 'S'
148
+ return "'S'";
149
+ });
150
+ // 2. Replace variables in non-string part with 0
151
+ // We must NOT replace Functions (IF, MAX, etc) with 0. Only variables.
152
+ const functionsToPreserve = new Set([
153
+ 'IF', 'AND', 'OR', 'NOT',
154
+ 'MIN', 'MAX', 'MOD', 'ROUND', 'ROUNDDOWN', 'ROUNDUP', 'TRUNC',
155
+ 'DATE', 'DAYS', 'TODAY', 'DATETIME_NOW', 'ISDATE', 'DAY', 'MONTH', 'YEAR',
156
+ 'DAYSINMONTH', 'DAYOFWEEK', 'ISNUMERIC', 'HOUR', 'MINUTE', 'SECOND',
157
+ 'DATEDIFF', 'DATEADD', 'CONCATENATE', 'CONCATENATESKIPNULL', 'FINDLIST', 'CREATEDATE',
158
+ 'LENGTHOFSERVICE'
159
+ ]);
160
+ for (const token of sortedTokens) {
161
+ const upperToken = token.toUpperCase();
162
+ // If it is a function, DO NOT replace it.
163
+ if (functionsToPreserve.has(upperToken)) {
164
+ continue;
165
+ }
166
+ // `TRUE` and `FALSE` are boolean literals, parser handles them. No need to replace.
167
+ if (upperToken === 'TRUE' || upperToken === 'FALSE') {
168
+ continue;
169
+ }
170
+ const regex = new RegExp(`\\b${token}\\b`, 'g');
171
+ formulaWithPlaceholders = formulaWithPlaceholders.replace(regex, '0');
172
+ }
173
+ // 3. Test parse
174
+ try {
175
+ const result = (0, formula_engine_1.parseFormula)(formulaWithPlaceholders);
176
+ // We ignore the result value, just checking for throw
177
+ }
178
+ catch (parseError) {
179
+ // If it's #NAME?, it means we missed a token?
180
+ // Any other error is syntax error.
181
+ const err = parseError;
182
+ if (err.message.includes('#NAME?')) {
183
+ // This can happen if hot-formula-parser doesn't support a specific function
184
+ // that we thought was valid in extraValid (e.g. LENGTHOFSERVICE is custom registered).
185
+ // But Custom functions SHOULD be registered in formula-engine.ts
186
+ // If we validated token as legal, but parser says #NAME, it might be a function name we didn't replace?
187
+ // Functions like 'IF', 'ROUND' are in extraValid.
188
+ // We should NOT replace function names with 0!
189
+ // Ah! My token extraction logic extracts everything including IF, ROUND.
190
+ // But my validation loop "continues" (skips error) if it is in extraValid.
191
+ // So 'IF' is in tokens?
192
+ // Yes: const tokens = formulaNoStrings.match(...)
193
+ // Wait, I should ONLY replace "Variables", not "Functions".
194
+ throw parseError; // Rethrow to see details if needed
195
+ }
196
+ throw parseError;
197
+ }
198
+ return { result: 'success' };
199
+ }
200
+ catch (e) {
201
+ throw e;
202
+ }
203
+ }
204
+ /**
205
+ * Parse formula for a single employee
206
+ * Internal method used by parseByEmpId
207
+ */
208
+ async parseForSingleEmployee(rawFormula, empId, auth) {
209
+ try {
210
+ // Normalize formula
211
+ const formula = rawFormula.replace(/"/g, `'`);
212
+ // Optimization: Check if formula actually needs payroll components
213
+ // Using regex to detect AL_001, DE_001, NE_001 or SALARY
214
+ const hasComponents = /\b(AL_\d+|DE_\d+|NE_\d+|SALARY)\b/i.test(formula);
215
+ let allCompo = [];
216
+ let empCompo = [];
217
+ let compoCodes = [];
218
+ if (hasComponents) {
219
+ // Step 1: Get list of component codes
220
+ const listCompo = await this.getComponentList(auth);
221
+ compoCodes = listCompo.map(v => v.allowdeductCode);
222
+ }
223
+ // Step 2: Fetch all required data in parallel
224
+ // Only fetch components if they are actually in the formula
225
+ const currencyCode = (0, helpers_1.getCurrencyCode)(auth.userData.taxCountry);
226
+ const [allCompoRes, empCompoRes, empData, getWordList] = await Promise.all([
227
+ hasComponents ? this.getAllComponents(auth, compoCodes, currencyCode) : Promise.resolve([]),
228
+ hasComponents ? this.getEmployeeComponents(auth, empId, compoCodes, currencyCode) : Promise.resolve([]),
229
+ this.getEmployeeData(auth, empId),
230
+ this.getReservedWords(auth),
231
+ ]);
232
+ allCompo = allCompoRes;
233
+ empCompo = empCompoRes;
234
+ if (!empData) {
235
+ return {
236
+ hasil: 0,
237
+ message: `Employee not found: ${empId}`,
238
+ };
239
+ }
240
+ // Step 3: Build object values from components
241
+ const objectVal = {};
242
+ if (hasComponents) {
243
+ // Initialize all components to 0
244
+ for (const compo of allCompo) {
245
+ objectVal[compo.allowdeductCode] = '0';
246
+ }
247
+ // Fill in employee's component values (with decryption)
248
+ for (const empCompoItem of empCompo) {
249
+ objectVal[empCompoItem.allowdeductCode] = '0';
250
+ if (empCompoItem.allowdeductValue) {
251
+ const decryptedValue = await (0, helpers_1.decryptValue)(empCompoItem.allowdeductValue, auth, empId);
252
+ objectVal[empCompoItem.allowdeductCode] = decryptedValue.toString();
253
+ }
254
+ }
255
+ }
256
+ // Step 4: Extract required words from formula
257
+ const requiredWords = this.extractRequiredWordsFromFormula(formula, getWordList.words2);
258
+ // Step 5: Batch load organizational data
259
+ const dataCache = await this.batchLoadFormulaData(auth, empData, requiredWords);
260
+ // Step 6: Process all words using cached data
261
+ const employeeDataConverted = this.convertToEmployeeData(empData);
262
+ const orgDataConverted = this.convertToOrganizationalData(dataCache);
263
+ for (const word of requiredWords) {
264
+ // Process personal data
265
+ (0, formula_parser_1.processPersonalData)(word, objectVal, employeeDataConverted);
266
+ // Process organizational data
267
+ (0, formula_parser_1.processOrganizationalData)(word, objectVal, orgDataConverted, formula);
268
+ // Process custom fields
269
+ (0, formula_parser_1.processCustomFields)(word, objectVal, orgDataConverted);
270
+ }
271
+ // Step 7: Handle formula replacement (same as original logic)
272
+ let processedFormula = formula;
273
+ // Handle quoted strings
274
+ const regexKutip = /\"(.*?)\"/g;
275
+ let match;
276
+ const objectX = {};
277
+ let arr = 0;
278
+ const replacements = {};
279
+ while ((match = regexKutip.exec(processedFormula))) {
280
+ replacements[`${match[1]}`] = 'PART' + arr;
281
+ objectX['PART' + arr] = `${match[1]}`;
282
+ arr++;
283
+ }
284
+ const hasReplacements = Object.values(replacements).some(value => value !== undefined && value !== '');
285
+ if (hasReplacements) {
286
+ const regex = new RegExp(Object.keys(replacements).join('|'), 'g');
287
+ processedFormula = processedFormula.replace(regex, m => replacements[m]);
288
+ }
289
+ // Extract and replace keywords
290
+ const formula2 = processedFormula.match(/[a-zA-Z0-9_]+|[+\-*/]/g) || [];
291
+ let keys = Object.keys(objectVal);
292
+ keys = (0, formula_parser_1.sortKeyByLengthDesc)(keys);
293
+ // Build replacement map
294
+ const replacementMap = new Map();
295
+ for (const wordnya of formula2) {
296
+ if (keys.includes(wordnya) && wordnya !== 'LENGTHOFSERVICE' && !replacementMap.has(wordnya)) {
297
+ replacementMap.set(wordnya, objectVal[wordnya].toString());
298
+ }
299
+ }
300
+ // Single-pass replacement
301
+ if (replacementMap.size > 0) {
302
+ const pattern = Array.from(replacementMap.keys())
303
+ .map(word => `\\b${word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`)
304
+ .join('|');
305
+ const regex = new RegExp(pattern, 'g');
306
+ processedFormula = processedFormula.replace(regex, m => replacementMap.get(m) || m);
307
+ }
308
+ // Restore quoted strings
309
+ const keys2 = Object.keys(objectX);
310
+ if (keys2.length > 0) {
311
+ keys2.forEach(key => {
312
+ processedFormula = processedFormula.replace(new RegExp(key, 'g'), `${objectX[key]}`);
313
+ });
314
+ }
315
+ // Step 8: Parse the formula
316
+ const result = (0, formula_engine_1.parseFormula)(processedFormula);
317
+ // console.log('\n=== DEBUG PAYROLL-FORMULA-PARSER ===');
318
+ // console.log('Emp ID:', empId);
319
+ // console.log('Raw Formula:', rawFormula);
320
+ // console.log('Processed Formula:', processedFormula);
321
+ // console.log('Result:', result);
322
+ // console.log('Resolved Variables:', JSON.stringify(objectVal, null, 2));
323
+ // console.log('====================================\n');
324
+ return {
325
+ hasil: result,
326
+ message: 'success',
327
+ };
328
+ }
329
+ catch (error) {
330
+ console.log(error);
331
+ throw error;
332
+ }
333
+ }
334
+ /**
335
+ * Parse formula for multiple employees
336
+ */
337
+ async parseForMultipleEmployees(formula, empIds, auth) {
338
+ const results = {};
339
+ for (const empId of empIds) {
340
+ results[empId] = await this.parseForSingleEmployee(formula, empId, auth);
341
+ }
342
+ return results;
343
+ }
344
+ // ==================== Private Methods ====================
345
+ /**
346
+ * Get list of component codes
347
+ */
348
+ async getComponentList(auth) {
349
+ let query = `
350
+ SELECT allowdeduct_code as allowdeductCode
351
+ FROM tpympayallowdeduct
352
+ WHERE company_id = ?
353
+ AND (
354
+ (allowdeduct_code LIKE 'AL_%' AND allowdeducttype = 'A' AND allowdeduct_code REGEXP 'AL_[0-9]+')
355
+ OR (allowdeduct_code LIKE 'DE_%' AND allowdeducttype = 'D' AND allowdeduct_code REGEXP 'DE_[0-9]+')
356
+ OR (allowdeduct_code LIKE 'NE_%' AND allowdeducttype = 'N' AND allowdeduct_code REGEXP 'NE_[0-9]+')
357
+ OR allowdeduct_code = 'SALARY'
358
+ )
359
+ `;
360
+ if (auth.userData.taxCountry === 'TH') {
361
+ query += ` AND allowdeduct_code NOT IN ('NE_002', 'NE_003')`;
362
+ }
363
+ return auth.connFin.query(query, [auth.userData.companyId]);
364
+ }
365
+ /**
366
+ * Get all components for company
367
+ */
368
+ async getAllComponents(auth, compoCodes, currencyCode) {
369
+ if (compoCodes.length === 0)
370
+ return [];
371
+ const placeholders = compoCodes.map(() => '?').join(',');
372
+ const query = `
373
+ SELECT allowdeduct_code as allowdeductCode
374
+ FROM tpympayallowdeduct
375
+ WHERE company_id = ?
376
+ AND allowdeduct_code IN (${placeholders})
377
+ AND currency_code = ?
378
+ `;
379
+ return auth.connFin.query(query, [auth.userData.companyId, ...compoCodes, currencyCode]);
380
+ }
381
+ /**
382
+ * Get employee component values
383
+ */
384
+ async getEmployeeComponents(auth, empId, compoCodes, currencyCode) {
385
+ if (compoCodes.length === 0)
386
+ return [];
387
+ const placeholders = compoCodes.map(() => '?').join(',');
388
+ const query = `
389
+ SELECT allowdeduct_code as allowdeductCode, allowdeduct_value as allowdeductValue
390
+ FROM tpydempallowdeduct
391
+ WHERE emp_id = ?
392
+ AND company_id = ?
393
+ AND allowdeduct_code IN (${placeholders})
394
+ AND currency_code = ?
395
+ `;
396
+ return auth.connFin.query(query, [empId, auth.userData.companyId, ...compoCodes, currencyCode]);
397
+ }
398
+ /**
399
+ * Get employee data with relations
400
+ */
401
+ async getEmployeeData(auth, empId) {
402
+ const query = `
403
+ SELECT
404
+ ec.emp_id as empId,
405
+ ec.emp_no as empNo,
406
+ ec.start_date as startDate,
407
+ ec.end_date as endDate,
408
+ ec.position_id as positionId,
409
+ ec.cost_code as costCode,
410
+ ec.grade_code as gradeCode,
411
+ ec.work_location_code as workLocationCode,
412
+ ec.job_status_code as jobStatusCode,
413
+ ecg.join_date as joinDate,
414
+ ecg.fulljoin_date as fulljoinDate,
415
+ ecg.permanent_date as permanentDate,
416
+ ecg.pension_date as pensionDate,
417
+ ecg.terminate_date as terminateDate,
418
+ ep.gender as gender,
419
+ edp.birthdate as birthdate,
420
+ edp.maritalstatus as maritalstatus,
421
+ edp.religion_code as religionCode,
422
+ ejs.jobstatusname_en as jobstatusnameEn
423
+ FROM teodempcompany ec
424
+ LEFT JOIN teodempcompanygroup ecg ON ec.emp_id = ecg.emp_id
425
+ LEFT JOIN teomemppersonal ep ON ec.emp_id = ep.emp_id
426
+ LEFT JOIN teodemppersonal edp ON ec.emp_id = edp.emp_id
427
+ LEFT JOIN teomjobstatus ejs ON ec.job_status_code = ejs.jobstatuscode AND ec.company_id = ejs.company_id
428
+ WHERE ec.emp_id = ? AND ec.company_id = ?
429
+ `;
430
+ const results = await auth.connFin.query(query, [empId, auth.userData.companyId]);
431
+ return results[0] || null;
432
+ }
433
+ /**
434
+ * Get reserved words list for formula processing
435
+ */
436
+ async getReservedWords(auth) {
437
+ const query = `
438
+ SELECT word
439
+ FROM tsfmreserveword
440
+ WHERE (ISNULL(taxcountry) OR taxcountry = '' OR taxcountry = ?)
441
+ AND (company_id = 1 OR company_id = ?)
442
+ AND module IN ('GENERAL', 'PAYROLL')
443
+ AND (category = 'EMPLOYEE' OR category = 'PAYFORMULA' OR category = 'CLAIMFORMULA')
444
+ GROUP BY word
445
+ `;
446
+ const results = await auth.connFin.query(query, [auth.userData.taxCountry, auth.userData.companyId]);
447
+ const words2 = results.map((r) => r.word);
448
+ return {
449
+ words2,
450
+ arrayAcr: [],
451
+ claimTypes2: [],
452
+ attStatuses: [],
453
+ leaveTypes: [],
454
+ payvarMaster: [],
455
+ arrayDiscp: [],
456
+ attintfWord: [],
457
+ };
458
+ }
459
+ /**
460
+ * Extract required words from formula
461
+ */
462
+ extractRequiredWordsFromFormula(formula, wordList) {
463
+ const required = new Set();
464
+ if (!formula)
465
+ return required;
466
+ for (const word of wordList) {
467
+ if (formula.includes(word)) {
468
+ required.add(word);
469
+ }
470
+ }
471
+ return required;
472
+ }
473
+ /**
474
+ * Batch load all required data for formula parsing
475
+ */
476
+ async batchLoadFormulaData(auth, empData, requiredWords) {
477
+ const cache = {};
478
+ const queries = [];
479
+ const queryMap = [];
480
+ // Position data
481
+ if ((0, helpers_1.needsPositionData)(requiredWords) && empData.positionId) {
482
+ queryMap.push('position');
483
+ queries.push(auth.conn.query(`
484
+ SELECT p.pos_name_en as posNameEn, p.pos_code as posCode,
485
+ d.pos_name_en as deptNameEn, d.pos_code as deptCode
486
+ FROM teomposition p
487
+ LEFT JOIN teomposition d ON p.dept_id = d.position_id AND p.company_id = d.company_id
488
+ WHERE p.position_id = ? AND p.company_id = ?
489
+ `, [empData.positionId, auth.userData.companyId]));
490
+ }
491
+ // Cost Center data
492
+ if ((0, helpers_1.needsCostCenterData)(requiredWords) && empData.costCode) {
493
+ queryMap.push('costCenter');
494
+ queries.push(auth.conn.query(`
495
+ SELECT costcenter_code as costcenterCode, costcenter_name_en as costcenterNameEn
496
+ FROM teomcostcenter
497
+ WHERE costcenter_code = ? AND company_id = ?
498
+ `, [empData.costCode, auth.userData.companyId]));
499
+ }
500
+ // Grade data
501
+ if ((0, helpers_1.needsGradeData)(requiredWords) && empData.gradeCode) {
502
+ queryMap.push('grade');
503
+ queries.push(auth.conn.query(`
504
+ SELECT grade_code as gradeCode, grade_name as gradeName
505
+ FROM teomjobgrade
506
+ WHERE grade_code = ? AND company_id = ?
507
+ `, [empData.gradeCode, auth.userData.companyId]));
508
+ }
509
+ // Work Location data
510
+ if ((0, helpers_1.needsWorkLocationData)(requiredWords) && empData.workLocationCode) {
511
+ queryMap.push('workLocation');
512
+ queries.push(auth.conn.query(`
513
+ SELECT worklocation_code as worklocationCode, worklocation_name as worklocationName
514
+ FROM teomworklocation
515
+ WHERE worklocation_code = ?
516
+ `, [empData.workLocationCode]));
517
+ }
518
+ // Custom Field data
519
+ if ((0, helpers_1.needsCustomFieldData)(requiredWords)) {
520
+ queryMap.push('customField');
521
+ queries.push(auth.conn.query(`
522
+ SELECT customfield1, customfield2, customfield3, customfield4, customfield5,
523
+ customfield6, customfield7, customfield8, customfield9, customfield10
524
+ FROM teodempcustomfield
525
+ WHERE emp_id = ? AND company_code = ?
526
+ `, [empData.empId, auth.userData.companyCode]));
527
+ }
528
+ // Employment Status
529
+ if (requiredWords.has('EMPLOYMENTSTATUS')) {
530
+ queryMap.push('employmentStatus');
531
+ queries.push(auth.connFin.query(`
532
+ SELECT employmentstatus_code as employmentStatusCode
533
+ FROM teodemploymenthistory
534
+ WHERE emp_id = ?
535
+ AND effectivedt = (
536
+ SELECT MAX(effectivedt)
537
+ FROM teodemploymenthistory
538
+ WHERE emp_id = ? AND company_id = ?
539
+ )
540
+ `, [empData.empId, empData.empId, auth.userData.companyId]));
541
+ }
542
+ // Child Dependents
543
+ if (requiredWords.has('CHILDDEPENDENTS')) {
544
+ queryMap.push('childDependents');
545
+ queries.push(auth.conn.query(`
546
+ SELECT COUNT(*) as count
547
+ FROM teodempfamily f
548
+ INNER JOIN teomfamilyrelation r ON f.relationship = r.relationship_code AND r.ischild = 1
549
+ WHERE f.emp_id = ? AND f.dependentsts = 1
550
+ `, [empData.empId]));
551
+ }
552
+ // Execute all queries in parallel
553
+ const results = await Promise.all(queries);
554
+ // Map results back to cache
555
+ results.forEach((result, index) => {
556
+ const key = queryMap[index];
557
+ if (key === 'position' && result[0]) {
558
+ cache.position = {
559
+ posNameEn: result[0].posNameEn,
560
+ posCode: result[0].posCode,
561
+ dept: {
562
+ posNameEn: result[0].deptNameEn,
563
+ posCode: result[0].deptCode,
564
+ },
565
+ };
566
+ }
567
+ else if (key === 'costCenter' && result[0]) {
568
+ cache.costCenter = result[0];
569
+ }
570
+ else if (key === 'grade' && result[0]) {
571
+ cache.grade = result[0];
572
+ }
573
+ else if (key === 'workLocation' && result[0]) {
574
+ cache.workLocation = result[0];
575
+ }
576
+ else if (key === 'customField' && result[0]) {
577
+ cache.customField = result[0];
578
+ }
579
+ else if (key === 'employmentStatus' && result[0]) {
580
+ cache.employmentStatus = result[0].employmentStatusCode;
581
+ }
582
+ else if (key === 'childDependents' && result[0]) {
583
+ cache.childDependents = result[0].count;
584
+ }
585
+ });
586
+ return cache;
587
+ }
588
+ /**
589
+ * Convert raw employee data to EmployeeData interface
590
+ */
591
+ convertToEmployeeData(empData) {
592
+ return {
593
+ empId: empData.empId,
594
+ empNo: empData.empNo,
595
+ startDate: empData.startDate,
596
+ endDate: empData.endDate,
597
+ positionId: empData.positionId,
598
+ costCode: empData.costCode,
599
+ gradeCode: empData.gradeCode,
600
+ workLocationCode: empData.workLocationCode,
601
+ jobStatusCode: empData.jobStatusCode,
602
+ personal: {
603
+ birthdate: empData.birthdate,
604
+ maritalstatus: empData.maritalstatus,
605
+ religionCode: empData.religionCode,
606
+ gender: empData.gender,
607
+ },
608
+ companyGroup: {
609
+ joinDate: empData.joinDate,
610
+ fulljoinDate: empData.fulljoinDate,
611
+ permanentDate: empData.permanentDate,
612
+ pensionDate: empData.pensionDate,
613
+ terminateDate: empData.terminateDate,
614
+ },
615
+ jobStatus: {
616
+ jobstatusnameEn: empData.jobstatusnameEn,
617
+ },
618
+ };
619
+ }
620
+ /**
621
+ * Convert cache to OrganizationalData interface
622
+ */
623
+ convertToOrganizationalData(cache) {
624
+ return {
625
+ position: cache.position ? {
626
+ posNameEn: cache.position.posNameEn,
627
+ posCode: cache.position.posCode,
628
+ dept: cache.position.dept,
629
+ } : undefined,
630
+ costCenter: cache.costCenter,
631
+ grade: cache.grade,
632
+ workLocation: cache.workLocation,
633
+ customField: cache.customField,
634
+ employmentStatus: cache.employmentStatus,
635
+ childDependents: cache.childDependents,
636
+ };
637
+ }
638
+ }
639
+ exports.PayrollFormulaService = PayrollFormulaService;
640
+ //# sourceMappingURL=payroll-formula.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payroll-formula.service.js","sourceRoot":"","sources":["../../src/nestjs/payroll-formula.service.ts"],"names":[],"mappings":"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"}