Skip to content

Commit

Permalink
fix(PayrollIndiceIncrease)
Browse files Browse the repository at this point in the history
- Remove Procedure UpdateStaffingIndice
- Create a new function for UpdateEmployeesBasicIndice
- Implement Integration test for check the value on Basic Indice
- Resolve conflict with branch master

closes #7498
  • Loading branch information
lomamech committed Feb 28, 2024
1 parent 6dbdb17 commit 687a9b3
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 4 deletions.
130 changes: 128 additions & 2 deletions server/controllers/payroll/configuration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
*
* This controller exposes an API to the client for reading and writing Payroll configuration
*/

const q = require('q');
const moment = require('moment');
const db = require('../../../lib/db');
const util = require('../../../lib/util');

// GET /PAYROLL_CONFIG
function lookupPayrollConfig(id) {
Expand Down Expand Up @@ -57,7 +58,7 @@ function create(req, res, next) {
db.exec(sql, [data])
.then((row) => {
insertedId = row.insertId;
return db.exec(`CALL UpdateStaffingIndices(?, ?, ?)`, [data.dateFrom, data.dateTo, insertedId]);
return updateEmployeesBasicIndice(insertedId, data.dateTo);
}).then(() => {
res.status(201).json({ id : insertedId });
})
Expand Down Expand Up @@ -185,6 +186,129 @@ function payrollReportElements(idPeriod, employees, employeesPaymentUuid) {
]);
}

async function updateEmployeesBasicIndice(idPeriod, dateTo) {
// This query is executed when running payroll with index for the very first time or
// when dealing with employees who are configured for the very first time,
// this query searches for the date of hire, their relative base index with their rank,
// their responsibility index linked to their function,
const sqlFindNewEmployees = `
SELECT emp.uuid, emp.date_embauche, sgi.value, sfi.value AS function_indice_value,
emp.grade_uuid, emp.fonction_id, pa.display_name
FROM employee AS emp
JOIN config_employee_item AS it ON it.employee_uuid = emp.uuid
JOIN config_employee AS conf ON conf.id = it.config_employee_id
JOIN payroll_configuration AS pay ON pay.config_employee_id = conf.id
JOIN grade AS gr ON gr.uuid = emp.grade_uuid
JOIN staffing_grade_indice AS sgi ON sgi.grade_uuid = emp.grade_uuid
LEFT JOIN staffing_function_indice AS sfi ON sfi.fonction_id = emp.fonction_id
JOIN patient AS pa ON pa.uuid = emp.patient_uuid
WHERE pay.id = ? AND emp.uuid NOT IN (SELECT stf.employee_uuid FROM staffing_indice AS stf)
ORDER BY pa.display_name ASC;
`;

// The following query is executed when dealing with employees who have already been configured,
// this query the date of the very first increment as well as the last value of the base index,
// the responsibility index linked to the function and date of hire
const sqlFindOldEmployees = `
SELECT emp.uuid, emp.date_embauche, lastIndice.date AS lastDateIncrease, lastIndice.grade_indice,
sfi.value AS function_indice_value, emp.grade_uuid, emp.fonction_id, pa.display_name
FROM employee AS emp
JOIN config_employee_item AS it ON it.employee_uuid = emp.uuid
JOIN config_employee AS conf ON conf.id = it.config_employee_id
JOIN payroll_configuration AS pay ON pay.config_employee_id = conf.id
JOIN grade AS gr ON gr.uuid = emp.grade_uuid
JOIN (
SELECT st.uuid, st.employee_uuid, st.grade_indice, st.date
FROM staffing_indice st
JOIN (
SELECT uuid, employee_uuid, MAX(date) AS maxdate
FROM staffing_indice st
GROUP BY st.employee_uuid
) AS currentInd ON currentInd.employee_uuid = st.employee_uuid AND currentInd.maxdate = st.date
) AS lastIndice ON lastIndice.employee_uuid = emp.uuid
LEFT JOIN staffing_function_indice AS sfi ON sfi.fonction_id = emp.fonction_id
JOIN patient AS pa ON pa.uuid = emp.patient_uuid
WHERE pay.id = ?
ORDER BY pa.display_name ASC;
`;

const sqlGetBaseIndexGrowthRate = `
SELECT base_index_growth_rate FROM enterprise_setting LIMIT 1;
`;

const [newEmployees, oldEmployees, dataEnterprise] = await Promise.all([
db.exec(sqlFindNewEmployees, idPeriod),
db.exec(sqlFindOldEmployees, idPeriod),
db.exec(sqlGetBaseIndexGrowthRate),
]);

const transaction = db.transaction();

const baseIndexGrowthRate = dataEnterprise[0].base_index_growth_rate;

// Processing of new employee data
newEmployees.forEach(employee => {
const diff = moment(dateTo).diff(moment(employee.date_embauche));
const duration = moment.duration(diff, 'milliseconds');
// Here we calculate in years the number of years of seniority
const yearOfSeniority = parseInt(duration.asYears(), 10);

// Here we increment the base index based on the number of years
for (let i = 0; i < yearOfSeniority; i++) {
employee.value += (employee.value * (baseIndexGrowthRate / 100));
}

const dataStaffingIndice = {
uuid : db.uuid(),
employee_uuid : employee.uuid,
grade_uuid : employee.grade_uuid,
fonction_id : employee.fonction_id,
grade_indice : util.roundDecimal(employee.value, 0),
function_indice : employee.function_indice_value || 0,
date : new Date(),
};
transaction.addQuery('INSERT INTO staffing_indice SET ?', dataStaffingIndice);
});

oldEmployees.forEach(employee => {
// For employees who have already been configured, we will compare the number of years of seniority
// and the difference in years between the date of the last increment of the base index,
// if this difference is greater than zero, the we will have to increment
// the base index in relation to this difference

const diffSeriority = moment(dateTo).diff(moment(employee.date_embauche));
const durationSeniority = moment.duration(diffSeriority, 'milliseconds');
const yearOfSeniority = parseInt(durationSeniority.asYears(), 10);

const diffLastIncrementation = moment(employee.lastDateIncrease).diff(moment(employee.date_embauche));
const durationLastIncrementation = moment.duration(diffLastIncrementation, 'milliseconds');
const yearLastIncrementation = parseInt(durationLastIncrementation.asYears(), 10);

const diffSeniorityIncrementation = yearOfSeniority - yearLastIncrementation;

if ((diffSeniorityIncrementation > 0) && (baseIndexGrowthRate > 0)) {
for (let i = 0; i < diffSeniorityIncrementation; i++) {
employee.grade_indice += (employee.grade_indice * (baseIndexGrowthRate / 100));
}

const dataStaffingIndice = {
uuid : db.uuid(),
employee_uuid : employee.uuid,
grade_uuid : employee.grade_uuid,
fonction_id : employee.fonction_id,
grade_indice : util.roundDecimal(employee.grade_indice, 0),
function_indice : employee.function_indice_value || 0,
date : new Date(),
};

transaction.addQuery('INSERT INTO staffing_indice SET ?', dataStaffingIndice);

}
});

return transaction.execute();
}

// get list of Payroll configuration
exports.list = list;

Expand All @@ -206,3 +330,5 @@ exports.paymentStatus = paymentStatus;
exports.lookupPayrollConfig = lookupPayrollConfig;

exports.payrollReportElements = payrollReportElements;

exports.updateEmployeesBasicIndice = updateEmployeesBasicIndice;
6 changes: 6 additions & 0 deletions server/models/migrations/next/migrate.sql
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
/* Release 1.31.0 */

/*
* @author: lomamech
* @description: Problem regarding the increase in basic indices based on percentages
* @date: 2024-02-26
*/
DROP PROCEDURE IF EXISTS `UpdateStaffingIndices`;
2 changes: 0 additions & 2 deletions test/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -803,8 +803,6 @@ INSERT INTO `payroll_configuration` (`id`, `label`, `dateFrom`, `dateTo`,
(1, 'Février 2018', '2018-02-01', '2018-02-28', 1, 1, 1, 1, 1),
(2, 'Juin 2019', '2019-06-01', '2019-06-30', 2, 1, 1, 1, 1);

CALL UpdateStaffingIndices('2019-06-01', '2019-06-30', 2);

SET @paymentUuid = HUID('2a3f17b0ae3242bb9333a760825fd257');
SET @employeeUuid = HUID('75e0969465f245a1a8a28b025003d793');
-- payment DATA
Expand Down
109 changes: 109 additions & 0 deletions test/integration/staffingIndices.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@ describe('test/integration/staffingIndices The staffing indices API', () => {
payroll_configuration_id : 6,
};

const year = new Date().getFullYear();
const yearPlus2 = year + 2;

const payrollConfigYearPlus2 = {
label : `Account Configuration ${yearPlus2}`,
dateFrom : `${yearPlus2}-01-01`,
dateTo : `${yearPlus2}-01-31`,
config_rubric_id : 2,
config_accounting_id : 1,
config_weekend_id : 1,
config_employee_id : 2,
};

const payrollConfigYearPlus2Month = {
label : `Account Configuration ${yearPlus2} plus one month`,
dateFrom : `${yearPlus2}-02-01`,
dateTo : `${yearPlus2}-02-28`,
config_rubric_id : 2,
config_accounting_id : 1,
config_weekend_id : 1,
config_employee_id : 2,
};

it('POST /staffing_indices add a new staffing indice', () => {
return agent.post('/staffing_indices')
.send(newIndice)
Expand Down Expand Up @@ -182,4 +205,90 @@ describe('test/integration/staffingIndices The staffing indices API', () => {
})
.catch(helpers.handler);
});

// Checking the increase in base indices when creating a futuristic pay period
it(`POST /PAYROLL_CONFIG should Payroll Configuration Year+2 for Checking
the increase in base indices when creating a futuristic pay period`, () => {
return agent.post('/payroll_config')
.send(payrollConfigYearPlus2)
.then((res) => {
payrollConfigYearPlus2.id = res.body.id;
helpers.api.created(res);

// This test must verify that the two configured employees must benefit from
// the increase in their base index for two years the first employee has a base index of 66
// with a rate of 5% in accordance with his date of hire and his last configuration
// its index after configuring the new pay period must be 69

// And the second employee has a base index of 138
// with a rate of 5% in accordance with his date of hire and his last configuration
// its index after configuring the new pay period must be 144

return agent.get('/staffing_indices')
.then(res2 => {
expect(res2).to.have.status(200);
expect(res2.body).to.be.an('array');

let checkIncrementationGradeIndice = 0;

res2.body.forEach(element => {
if (element.grade_indice === 145) {
checkIncrementationGradeIndice++;
}

if (element.grade_indice === 69) {
checkIncrementationGradeIndice++;
}
});
expect(checkIncrementationGradeIndice).to.equal(2);
expect(res2.body).to.have.length(9);
})
.catch(helpers.handler);
})
.catch(helpers.handler);
});

// With the following test, which takes place in the period corresponding
// to the same period in which the employees were hired, they must benefit from the increase in their base index
it(`POST /PAYROLL_CONFIG should Payroll Configuration Year+2 + One month for Checking
the increase in base indices when creating a futuristic pay period`, () => {
return agent.post('/payroll_config')
.send(payrollConfigYearPlus2Month)
.then((res) => {
payrollConfigYearPlus2Month.id = res.body.id;
helpers.api.created(res);

// This test must verify that the two configured employees must benefit from
// the increase in their base index for two years the first employee has a base index of 69
// with a rate of 5% in accordance with his date of hire and his last configuration
// its index after configuring the new pay period must be 76

// And the second employee has a base index of 144
// with a rate of 5% in accordance with his date of hire and his last configuration
// its index after configuring the new pay period must be 160

return agent.get('/staffing_indices')
.then(res2 => {
expect(res2).to.have.status(200);
expect(res2.body).to.be.an('array');

let checkIncrementationGradeIndice = 0;

res2.body.forEach(element => {
if (element.grade_indice === 160) {
checkIncrementationGradeIndice++;
}

if (element.grade_indice === 76) {
checkIncrementationGradeIndice++;
}
});
expect(checkIncrementationGradeIndice).to.equal(2);
expect(res2.body).to.have.length(11);
expect(6).to.equal(11);
})
.catch(helpers.handler);
})
.catch(helpers.handler);
});
});

0 comments on commit 687a9b3

Please sign in to comment.