Skip to content

Commit

Permalink
Merge branch 'master' into improve-e2e-tests-robustness
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcameron committed Feb 28, 2024
2 parents 5decd33 + a23a98d commit e89b2da
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 17 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@
"gulp-if": "^3.0.0",
"gulp-iife": "^0.4.0",
"gulp-less": "^5.0.0",
"gulp-merge-json": "^2.1.2",
"gulp-merge-json": "^2.2.0",
"gulp-postcss": "^10.0.0",
"gulp-rev": "^9.0.0",
"gulp-rev-rewrite": "^5.0.0",
Expand Down
128 changes: 126 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,8 @@ function create(req, res, next) {
db.exec(sql, [data])
.then((row) => {
insertedId = row.insertId;
return db.exec(`CALL UpdateStaffingIndices(?, ?, ?)`, [data.dateFrom, data.dateTo, insertedId]);
data.dateTo = moment(data.dateTo).format('YYYY-MM-DD');
return updateEmployeesBasicIndice(insertedId, data.dateTo);
}).then(() => {
res.status(201).json({ id : insertedId });
})
Expand Down Expand Up @@ -185,6 +187,126 @@ 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,
MAX(lastIndice.grade_indice) AS 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 = ?
GROUP BY emp.uuid
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 => {
employee.date_embauche = moment(employee.date_embauche).format('YYYY-MM-DD');
const yearOfSeniority = parseInt(moment(dateTo).diff(employee.date_embauche, 'years'), 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 => {
employee.date_embauche = moment(employee.date_embauche).format('YYYY-MM-DD');
employee.lastDateIncrease = moment(employee.lastDateIncrease).format('YYYY-MM-DD');
// 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 yearOfSeniority = parseInt(moment(dateTo).diff(employee.date_embauche, 'years'), 10);
const yearLastIncrementation = parseInt(moment(employee.lastDateIncrease).diff(employee.date_embauche, 'years'),
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 +328,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`;
4 changes: 1 addition & 3 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 Expand Up @@ -1145,7 +1143,7 @@ INSERT INTO `patient` (`uuid`, `project_id`, `reference`, `debtor_uuid`, `displa
INSERT INTO `creditor` (`uuid`, `group_uuid`, `text`) VALUES (0x75ED6B1141764BF7821D34BA638B0647, 0xB0FA5ED204F94CB392F761D6404696E7, 'Crediteur [Employee indice 1]');
INSERT INTO `creditor` (`uuid`, `group_uuid`, `text`) VALUES (0x6150E9B14D214DC28E845BFAAB40DD5E, 0xB0FA5ED204F94CB392F761D6404696E7, 'Crediteur [Employee indice 2]');

INSERT INTO `employee` (`uuid`, `code`, `date_embauche`, `grade_uuid`, `nb_spouse`, `nb_enfant`, `individual_salary`, `bank`, `bank_account`, `fonction_id`, `service_uuid`, `creditor_uuid`, `locked`, `patient_uuid`, `reference`) VALUES (0x10F64A41DA594962AA9A90CF0D42257C, 'IMA-ASSR-1', DATE_ADD(CURRENT_DATE, INTERVAL -2 YEAR), 0x71E9F21CD9B111E58AB778EB2F2A46E0, 0, 0, 0, NULL, NULL, 2, 0xB1816006555845F993A0C222B5EFA6CB, 0x75ED6B1141764BF7821D34BA638B0647, NULL, 0x4B23E6B9187F4CE69696542F798B5F32, 3);
INSERT INTO `employee` (`uuid`, `code`, `date_embauche`, `grade_uuid`, `nb_spouse`, `nb_enfant`, `individual_salary`, `bank`, `bank_account`, `fonction_id`, `service_uuid`, `creditor_uuid`, `locked`, `patient_uuid`, `reference`) VALUES (0x10F64A41DA594962AA9A90CF0D42257C, 'IMA-ASSR-1', DATE_ADD(CURRENT_DATE, INTERVAL -25 MONTH) , 0x71E9F21CD9B111E58AB778EB2F2A46E0, 0, 0, 0, NULL, NULL, 2, 0xB1816006555845F993A0C222B5EFA6CB, 0x75ED6B1141764BF7821D34BA638B0647, NULL, 0x4B23E6B9187F4CE69696542F798B5F32, 3);
INSERT INTO `employee` (`uuid`, `code`, `date_embauche`, `grade_uuid`, `nb_spouse`, `nb_enfant`, `individual_salary`, `bank`, `bank_account`, `fonction_id`, `service_uuid`, `creditor_uuid`, `locked`, `patient_uuid`, `reference`) VALUES (0xD321099D01CD41029686B87CB70B9311, 'IMA-ASSP-2', DATE_ADD(CURRENT_DATE, INTERVAL -2 YEAR), 0x61E9F21CD9B111E48AB678EB2F2A46E0, 0, 2, 0, NULL, NULL, 1, 0xE3988489EF6641DF88FA8B8ED6AA03AC, 0x6150E9B14D214DC28E845BFAAB40DD5E, NULL, 0xA6643C4F310145BA961B54FD83D71E7C, 4);

INSERT INTO `config_employee_item` (`id`, `config_employee_id`, `employee_uuid`) VALUES
Expand Down
83 changes: 82 additions & 1 deletion test/integration/staffingIndices.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint no-unused-expressions:off */
/* global expect, agent */

const moment = require('moment');
const helpers = require('./helpers');

/*
Expand Down Expand Up @@ -59,6 +59,25 @@ describe('test/integration/staffingIndices The staffing indices API', () => {
payroll_configuration_id : 6,
};

const year = new Date().getFullYear();
const datePlus2Year = moment().add(2, 'year').format('YYYY-MM-DD');

const datePlus2YearSub1Month = moment(datePlus2Year).clone().subtract(1, 'months').format('YYYY-MM-DD');
const datePlus2YearSub1MonthBegin = moment(datePlus2YearSub1Month).clone().startOf('month').format('YYYY-MM-DD');
const datePlus2YearSub1MonthEnd = moment(datePlus2YearSub1Month).clone().endOf('month').format('YYYY-MM-DD');

const yearPlus2 = year + 2;

const payrollConfigYearPlus2Sub1Month = {
label : `Account Configuration ${yearPlus2} substract one month`,
dateFrom : datePlus2YearSub1MonthBegin,
dateTo : datePlus2YearSub1MonthEnd,
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 +201,66 @@ 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(payrollConfigYearPlus2Sub1Month)
.then((res) => {
payrollConfigYearPlus2Sub1Month.id = res.body.id;
helpers.api.created(res);

// To test the new functionality intended to increase the base indices,
// the system will first calculate the number of years of employee seniority
// in relation to the pay period as well as the difference in years between
// the last increment of the base index by in relation to the pay period,
// and if this difference is greater than zero, the basic index will be
// incremented as a percentage proportionally to the number of years.

//
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 => {
// For the following example the first was hired on January 27, 2022, and
// its last base index dates from February 27, 2024 and it is 66
// The pay period is January 2026
// The system will first calculate their year of seniority in relation to the pay period
// Seniority = (2026-01-31) - (2022-01-27) is equal to 4 years (1)
// Last increment = (2024-02-27) - (2022-01-27) is equal to 2 years (2)
// Base Index Growth Rate being 5%, the base index of this employee will be increased in
// accordance with the difference in years (1)-(2) => 4 years - 2 years = 2 years,
// - Year 1: 66 + (66 x 0.05) = 69.03
// - Year 2: 69.03 + (69.03 x 0.05) = 72.77 which the system will round to 73
if (element.grade_indice === 73) {
checkIncrementationGradeIndice++;
}

// For the following example the second was hired on february 27, 2022, and
// its last base index dates from February 27, 2024 and it is 138
// The pay period is January 2026
// The system will first calculate their year of seniority in relation to the pay period
// Seniority = (2026-01-31) - (2022-02-27) is equal to 3 years (1)
// Last increment = (2024-02-27) - (2022-02-27) is equal to 2 years (2)
// Base Index Growth Rate being 5%, the base index of this employee will be increased in
// accordance with the difference in years (1)-(2) => 3 years - 2 years = 1 year
// - Year 1: 138 + (138 x 0.05) = 144.9 which the system will round to 145
if (element.grade_indice === 145) {
checkIncrementationGradeIndice++;
}

});

expect(checkIncrementationGradeIndice).to.equal(2);
expect(res2.body).to.have.length(9);
})
.catch(helpers.handler);
})
.catch(helpers.handler);
});
});
Loading

0 comments on commit e89b2da

Please sign in to comment.