generated from FlatFilers/getting-started
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Dedupe employees * hcmValidateReportingStructure * Job name length validation * Validations * Clean up validations
- Loading branch information
Showing
9 changed files
with
364 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { FlatfileEvent, FlatfileListener } from '@flatfile/listener'; | ||
import api from '@flatfile/api'; | ||
import { dedupeEmployees } from '@/workflows/hcm/actions/dedupeEmployees'; | ||
|
||
export const hcmDedupeEmployees = | ||
() => | ||
(listener: FlatfileListener): void => { | ||
// Listen for the 'dedupe employees' action | ||
listener.filter({ job: 'sheet:dedupeEmployees' }, (configure) => { | ||
configure.on( | ||
'job:ready', | ||
async ({ context: { jobId, sheetId } }: FlatfileEvent) => { | ||
console.log(JSON.stringify(sheetId, null, 2)); | ||
try { | ||
await api.jobs.ack(jobId, { | ||
info: 'Checking for duplicates.', | ||
progress: 10, | ||
}); | ||
|
||
let count = 0; | ||
try { | ||
console.log('Sheet ID: ' + sheetId); | ||
|
||
// Call the 'get' method of api.records with the sheetId | ||
const response = await api.records.get(sheetId); | ||
|
||
// Check if the response is valid and contains records | ||
if (response?.data?.records) { | ||
const records = response.data.records; | ||
|
||
// Call the dedupeEmployees function with the records | ||
const removeThese = dedupeEmployees(records); | ||
console.log('Records to Remove: ' + removeThese); | ||
count = removeThese.length; | ||
|
||
// Check if there are any records to remove | ||
if (removeThese.length > 0) { | ||
// Delete the records identified for removal from the API | ||
await api.records.delete(sheetId, { ids: removeThese }); | ||
} else { | ||
console.log('No records found for removal.'); | ||
} | ||
} else { | ||
console.log('No records found in the response.'); | ||
} | ||
} catch (error) { | ||
console.log('Error occurred:', error); | ||
} | ||
|
||
await api.jobs.complete(jobId, { | ||
info: `${count} employees deduplicated.`, | ||
}); | ||
} catch (error) { | ||
console.error('Error:', error.stack); | ||
|
||
await api.jobs.fail(jobId, { | ||
info: 'Unable to deduplicate employees.', | ||
}); | ||
} | ||
} | ||
); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { FlatfileEvent, FlatfileListener } from '@flatfile/listener'; | ||
import api from '@flatfile/api'; | ||
import { validateReportingStructure } from '@/workflows/hcm/actions/validateReportingStructure'; | ||
|
||
export const hcmValidateReportingStructure = | ||
() => | ||
(listener: FlatfileListener): void => { | ||
listener.filter( | ||
{ job: 'sheet:validateReportingStructure' }, | ||
(configure) => { | ||
configure.on( | ||
'job:ready', | ||
async ({ context: { jobId, sheetId } }: FlatfileEvent) => { | ||
try { | ||
await api.jobs.ack(jobId, { | ||
info: 'Validating reporting structure.', | ||
progress: 10, | ||
}); | ||
|
||
let count = 0; | ||
try { | ||
console.log('Sheet ID: ' + sheetId); | ||
|
||
// Call the 'get' method of api.records with the sheetId | ||
const response = await api.records.get(sheetId); | ||
|
||
// Check if the response is valid and contains records | ||
if (response?.data?.records) { | ||
const records = response.data.records; | ||
|
||
// Call the validateReportingStructure function with the records | ||
const reportingErrors = validateReportingStructure(records); | ||
count = reportingErrors.length; | ||
|
||
// Update the records if there are any reporting errors | ||
if (reportingErrors.length > 0) { | ||
await api.records.update(sheetId, reportingErrors); | ||
console.log('Records updated successfully.'); | ||
// For example, you can send them as a notification or store them in a database | ||
} else { | ||
console.log('No records found for updating.'); | ||
} | ||
} else { | ||
console.log('No records found in the response.'); | ||
} | ||
} catch (error) { | ||
console.log('Error occurred:' + error); | ||
} | ||
|
||
await api.jobs.complete(jobId, { | ||
info: `${count} records found and flagged.`, | ||
}); | ||
} catch (error) { | ||
console.error('Error:', error.stack); | ||
|
||
await api.jobs.fail(jobId, { | ||
info: 'Unable to validate reporting structure.', | ||
}); | ||
} | ||
} | ||
); | ||
} | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
export const dedupeEmployees = (records) => { | ||
const uniques = {}; // Object to store unique records based on employeeId | ||
const removeThese = []; // Array to store record IDs to be removed | ||
|
||
for (const record of records) { | ||
const employeeId = record.values.employeeId.value; // Get the employeeId value from the record | ||
|
||
if (typeof employeeId === 'string') { | ||
// Check if the employeeId is of type string | ||
if (!(employeeId in uniques)) { | ||
// If the employeeId is not found in the uniques object, add the record as a unique record | ||
uniques[employeeId] = record; | ||
} else { | ||
// If the employeeId is already in the uniques object, compare hire dates to determine which record to keep | ||
const latestRecord = uniques[employeeId]; | ||
|
||
if (record.values.hireDate.value > latestRecord.values.hireDate.value) { | ||
// If the current record has a later hire date, remove the latestRecord and add the current record | ||
removeThese.push(latestRecord.id); | ||
uniques[employeeId] = record; | ||
} else { | ||
// If the current record has an earlier or equal hire date, add the current record to the removal list | ||
removeThese.push(record.id); | ||
} | ||
} | ||
} else { | ||
console.log('Invalid employeeId:', employeeId); // Log an error message for invalid employeeId values | ||
} | ||
} | ||
|
||
return removeThese; // Return the list of record IDs to be removed | ||
}; |
148 changes: 148 additions & 0 deletions
148
src/workflows/hcm/actions/validateReportingStructure.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
export const validateReportingStructure = (records) => { | ||
const reportingErrors = []; | ||
const employees = {}; | ||
const visited = new Set(); | ||
const managerIds = new Set(); | ||
const employeesWithManagerId = new Set(); | ||
const updatedRecords = []; // Array to store only the modified parts of records | ||
|
||
for (const record of records) { | ||
if ( | ||
record.values.employeeId.messages && | ||
record.values.employeeId.messages.length > 0 | ||
) { | ||
updatedRecords.push({ | ||
id: record.id, | ||
values: { | ||
employeeId: { | ||
...record.values.employeeId, | ||
messages: [], | ||
}, | ||
}, | ||
}); | ||
} | ||
} | ||
|
||
const detectCircularDependency = (employeeId: string, path: string[]) => { | ||
if (visited.has(employeeId)) { | ||
const record = employees[employeeId]; | ||
const error = { | ||
message: `Circular dependency detected: ${path.join( | ||
' -> ' | ||
)} -> ${employeeId}`, | ||
source: 'custom-logic', | ||
type: 'error', | ||
}; | ||
|
||
const updatedRecord = updatedRecords.find((r) => r.id === record.id); | ||
if (updatedRecord) { | ||
updatedRecord.values.employeeId.messages.push(error); | ||
} else { | ||
updatedRecords.push({ | ||
id: record.id, | ||
values: { | ||
employeeId: { | ||
...record.values.employeeId, | ||
messages: [error], | ||
}, | ||
}, | ||
}); | ||
} | ||
reportingErrors.push(record); | ||
} else { | ||
visited.add(employeeId); | ||
const managerId = employees[employeeId]?.values.managerId.value; | ||
|
||
if (managerId && managerId !== employeeId) { | ||
detectCircularDependency(managerId, [...path, employeeId]); | ||
} | ||
|
||
visited.delete(employeeId); | ||
} | ||
}; | ||
|
||
for (const record of records) { | ||
const employeeId = record.values.employeeId.value; | ||
const managerId = record.values.managerId.value; | ||
|
||
employees[employeeId] = record; | ||
|
||
if (managerId && managerId !== '') { | ||
managerIds.add(managerId); | ||
|
||
if (employeeId === managerId) { | ||
employeesWithManagerId.add(employeeId); | ||
} | ||
} | ||
} | ||
|
||
if (employeesWithManagerId.size > 1) { | ||
for (const employeeId of employeesWithManagerId) { | ||
const record = employees[employeeId as string]; | ||
const error = { | ||
message: `Multiple records have the scenario where employeeId = managerId. Please ensure that only one record has the employeeId = managerId scenario.`, | ||
source: 'custom-logic', | ||
type: 'error', | ||
}; | ||
|
||
const updatedRecord = updatedRecords.find((r) => r.id === record.id); | ||
if (updatedRecord) { | ||
updatedRecord.values.employeeId.messages.push(error); | ||
} else { | ||
updatedRecords.push({ | ||
id: record.id, | ||
values: { | ||
employeeId: { | ||
...record.values.employeeId, | ||
messages: [error], | ||
}, | ||
}, | ||
}); | ||
} | ||
reportingErrors.push(record); | ||
} | ||
} | ||
|
||
for (const record of records) { | ||
const managerId = record.values.managerId.value; | ||
if (managerId && managerId !== '' && !employees[managerId]) { | ||
const error = { | ||
message: `Manager with ID: ${managerId} does not exist as an employee`, | ||
source: 'custom-logic', | ||
type: 'error', | ||
}; | ||
|
||
const updatedRecord = updatedRecords.find((r) => r.id === record.id); | ||
if (updatedRecord) { | ||
if (!updatedRecord.values.managerId) { | ||
updatedRecord.values.managerId = { | ||
...record.values.managerId, | ||
messages: [], | ||
}; | ||
} | ||
updatedRecord.values.managerId.messages.push(error); | ||
} else { | ||
updatedRecords.push({ | ||
id: record.id, | ||
values: { | ||
managerId: { | ||
...record.values.managerId, | ||
messages: [error], | ||
}, | ||
}, | ||
}); | ||
} | ||
reportingErrors.push(record); | ||
} | ||
} | ||
|
||
for (const employeeId in employees) { | ||
if (!visited.has(employeeId)) { | ||
detectCircularDependency(employeeId, []); | ||
} | ||
} | ||
|
||
console.log('Reporting Errors: ' + JSON.stringify(reportingErrors)); | ||
|
||
return updatedRecords; // Return only the modified records | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.