WORKFLOW ACTION SAMPLE

const onAction = (scriptContext) => {
        try {
            //log.debug('Script Execution Started', scriptContext);
            let recordObj = scriptContext.newRecord;
            let getdate = recordObj.getValue({ fieldId: 'trandate' });
            let hoursTracked = recordObj.getValue({ fieldId: 'hours' });
            let project = recordObj.getValue({ fieldId: 'customer' });
            let employee = recordObj.getValue({ fieldId: 'employee' });
            let projectAllocationId = recordObj.getValue({ fieldId: 'custcol_jj_project_allocation' });
            log.debug('Record Details', { date: getdate, hoursTracked, project, employee, projectAllocationId });
            let date = new Date(getdate);
            let month = date.getMonth() + 1;
            let year = date.getFullYear();
            let formattedStartDate = format.format({ value: date, type: format.Type.DATE });
            //log.debug('Formatted start date', formattedStartDate);
            let employeeWorkCalendarId = getEmployeeWorkCalendar(employee);
            let minWorkHours = getWorkCalendarHours(employeeWorkCalendarId);
            log.debug('Employee min Work hr', minWorkHours)
            let payrollId = getPayrollDetails(employee, month, year, project);
            let timeBillDetails = getTimeBillsData(employee, formattedStartDate);
            log.debug('Payroll & TimeBill Details', { payrollId, timeBillDetails });
            let approvedTimebill = timeBillDetails.approvedTimesheets || [];
            let existingEntry = approvedTimebill.find(entry => entry.projectAllocationId === projectAllocationId);
            if (existingEntry) {
                // If the projectAllocationId already exists, add to the existing hours
                existingEntry.hours += hoursTracked;
            } else {
                // If it doesn't exist, push a new entry
                if (project !== LEAVE_PROJECT) {
                    approvedTimebill.push({
                        employee: employee,
                        donor: project,
                        hours: hoursTracked,
                        projectAllocationId: projectAllocationId
                    });
                }
            }
            log.debug('Approved Time Sheets After Addition', approvedTimebill);
            if ((approvedTimebill.length === 1) && (project !== LEAVE_PROJECT)) {
                updateTrackedHoursForProjectAllocation(projectAllocationId, minWorkHours, formattedStartDate);
            }
            else {
                // let totalTime = approvedTimebill.reduce((sum, item) => sum + item.hours, 0);
                // log.debug('Total Time Calculated', totalTime);
                let updatedApprovedTimebill = [...approvedTimebill]; // Copy existing timebill entries
                if (project === LEAVE_PROJECT) {
                    let allProjectAllocationArray = getAllProjectsAllocations(payrollId);
                    log.debug('All Project Allocations', allProjectAllocationArray);
                    allProjectAllocationArray.forEach(allocation => {
                        let projectAllocationId = allocation.ProjectAllocationId;
                        let budgetAllocationPercent = parseFloat(allocation.budgetedAllocationPercent) || 0;
                        let budgetAllocation = budgetAllocationPercent / 100;
                        // Calculate prorated leave hours for this project allocation
                        let proratedHours = hoursTracked * budgetAllocation;
                        let existingEntry = updatedApprovedTimebill.find(entry => entry.projectAllocationId === projectAllocationId);
                        if (existingEntry) {
                            // If found, update existing entry by adding prorated hours
                            existingEntry.hours += proratedHours;
                        } else {
                            // If not found, create a new entry
                            updatedApprovedTimebill.push({
                                projectAllocationId: projectAllocationId,
                                hours: proratedHours,
                                donor: allocation.donor // Ensure donor is included for checking LEAVE_PROJECT
                            });
                        }
                    });
                    // Step 1: Create a Set of projectAllocationIds already in updatedApprovedTimebill
                    let existingProjectAllocationIds = new Set(updatedApprovedTimebill.map(entry => entry.projectAllocationId));
                    // Step 2: Append only non-duplicate entries from approvedTimebill
                    approvedTimebill.forEach(entry => {
                        if (!existingProjectAllocationIds.has(entry.projectAllocationId) && entry.donor !== LEAVE_PROJECT) {
                            updatedApprovedTimebill.push(entry);
                            existingProjectAllocationIds.add(entry.projectAllocationId); // Add to Set to track duplicates
                        }
                    });
                    // Step 3: Log the final updated time allocations
                    log.debug('Final Approved Timebill after Leave Hours Distribution', updatedApprovedTimebill);
                }
                let totalTime = updatedApprovedTimebill.reduce((sum, item) => sum + item.hours, 0);
                log.debug('Total Time after Leave Distribution', totalTime);
                for (let entry of updatedApprovedTimebill) {
                    //log.debug('Processing Approved Time Bill', entry);
                    if (entry.donor !== LEAVE_PROJECT) {
                        // **Regular Project Allocation Logic**
                        log.debug('currentApprovedProHrs Calculation',
                            `(${minWorkHours} * (${entry.hours} ) / ${totalTime}`);
                        let currentApprovedProHrs = (minWorkHours * entry.hours) / totalTime;
                        currentApprovedProHrs = currentApprovedProHrs !== 0 ? parseFloat(currentApprovedProHrs) : 0;
                        log.debug('Current Approved Pro-rated Hours', { projectAllocationId: entry.projectAllocationId, currentApprovedProHrs });
                        updateTrackedHoursForProjectAllocation(entry.projectAllocationId, currentApprovedProHrs, formattedStartDate);
                    }
                }
            }
            updatePayrollTrackedHours(payrollFlag, payrollId, minWorkHours);
        } catch (e) {
            log.error('Error in onAction', e);
        }
    };
    return { onAction };
});

Retrieve Key Record Values

Extracts important field values from the transaction record, such as date, hours tracked, project, employee, and project allocation ID.

Format Date & Get Employee Work Hours

Converts the transaction date into a formatted string.
Fetches the employee's work calendar to determine their minimum required work hours.

Retrieve Payroll & Time Bill Data

Fetches payroll details for the employee for the given month and year.
Retrieves previously approved time entries for the employee on that date.

Check for Existing Time Entries

Searches for an existing entry with the same project allocation ID in the approved time bills.
If found, adds the new tracked hours to the existing entry.
If not found, creates a new entry (excluding leave projects).

Update Time Tracking for Single Entry

If there is only one non-leave project entry, updates the project allocation’s tracked hours with the minimum work hours.

Handle Leave Project Hours

Retrieves all project allocations associated with the employee’s payroll.
Distributes leave hours proportionally across project allocations based on budgeted allocation percentages.
Merges newly calculated leave hours with existing approved time bills, avoiding duplicate project allocations.

Calculate Total Time & Normalize Work Hours

Computes the total tracked hours, including prorated leave.
Distributes the minimum required work hours proportionally across all project allocations based on tracked hours.

Update Project Allocations

Iterates through the updated list of time-tracked entries.
Updates each project allocation’s tracked hours, excluding leave projects.

Update Payroll Tracked Hours

Updates the total tracked hours in the payroll record.

Error Handling

Wraps the entire logic in a try-catch block to capture and log any unexpected errors.

Leave a comment

Your email address will not be published. Required fields are marked *