diff --git a/db/changes/10440-fallas/00-workerBusinessType.sql b/db/changes/10440-fallas/00-workerBusinessType.sql new file mode 100644 index 0000000000..489caa6c9e --- /dev/null +++ b/db/changes/10440-fallas/00-workerBusinessType.sql @@ -0,0 +1,3 @@ +ALTER TABLE `postgresql`.`business_labour_payroll` DROP FOREIGN KEY `business_labour_payroll_cod_contrato`; +ALTER TABLE `vn`.`workerBusinessType` MODIFY COLUMN `id` int(11) NOT NULL; +ALTER TABLE `postgresql`.`business_labour_payroll` ADD CONSTRAINT `business_labour_payroll_FK` FOREIGN KEY (cod_contrato) REFERENCES `vn`.`workerBusinessType`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 4632ec022f..c61bc44ed5 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1902,14 +1902,29 @@ INSERT INTO `vn`.`workCenterHoliday` (`workCenterFk`, `days`, `year`) ('1', '24.5', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))), ('5', '23', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))); -INSERT INTO `postgresql`.`calendar_state` (`calendar_state_id`, `type`, `rgb`, `code`, `holidayEntitlementRate`) +INSERT INTO `postgresql`.`calendar_state` (`calendar_state_id`, `type`, `rgb`, `code`, `holidayEntitlementRate`, `discountRate`) VALUES - (1, 'Holidays', '#FF4444', 'holiday', 0), - (2, 'Leave of absence', '#C71585', 'absence', 0), - (6, 'Half holiday', '#E65F00', 'halfHoliday', 0), - (15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0), - (20, 'Furlough', '#97B92F', 'furlough', 1), - (21, 'Furlough half day', '#778899', 'halfFurlough', 0.5); + (1, 'Holidays', '#FF4444', 'holiday', 0, 0), + (2, 'Leave of absence', '#C71585', 'absence', 0, 1), + (6, 'Half holiday', '#E65F00', 'halfHoliday', 0, 0.5), + (15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0, 1), + (20, 'Furlough', '#97B92F', 'furlough', 1, 1), + (21, 'Furlough half day', '#778899', 'halfFurlough', 0.5, 1); + +ALTER TABLE `postgresql`.`business_labour_payroll` DROP FOREIGN KEY `business_labour_payroll_cod_categoria`; + +INSERT INTO `vn`.`workerBusinessType` (`id`, `name`, `isFullTime`, `isPermanent`, `hasHolidayEntitlement`) + VALUES + (1, 'CONTRATO HOLANDA', 1, 0, 1), + (100, 'INDEFINIDO A TIEMPO COMPLETO', 1, 1, 1), + (109, 'CONVERSION DE TEMPORAL EN INDEFINIDO T.COMPLETO', 1, 1, 1); + +INSERT INTO `postgresql`.`business_labour_payroll` (`business_id`, `cod_tarifa`, `cod_categoria`, `cod_contrato`, `importepactado`) + VALUES + (1, 7, 12, 100, 900.50), + (1106, 7, 12, 100, 1263.03), + (1107, 7, 12, 100, 2000), + (1108, 7, 12, 100, 1500); INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id`, `date`) VALUES diff --git a/modules/worker/back/methods/worker/holidays.js b/modules/worker/back/methods/worker/holidays.js index bcf4d7f51c..339b84b7bd 100644 --- a/modules/worker/back/methods/worker/holidays.js +++ b/modules/worker/back/methods/worker/holidays.js @@ -1,4 +1,5 @@ const UserError = require('vn-loopback/util/user-error'); +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = Self => { Self.remoteMethodCtx('holidays', { @@ -33,7 +34,8 @@ module.exports = Self => { Self.holidays = async(ctx, id, options) => { const models = Self.app.models; const args = ctx.args; - + const conn = Self.dataSource.connector; + const stmts = []; const myOptions = {}; if (typeof options == 'object') @@ -56,42 +58,6 @@ module.exports = Self => { ended.setHours(23, 59, 59, 59); const filter = { - include: [{ - relation: 'holidays', - scope: { - where: {year: args.year} - } - }, - { - relation: 'absences', - scope: { - include: { - relation: 'absenceType', - }, - where: { - dated: {between: [started, ended]} - } - } - }, - { - relation: 'workCenter', - scope: { - include: { - relation: 'holidays', - scope: { - include: [{ - relation: 'detail' - }, - { - relation: 'type' - }], - where: { - dated: {between: [started, ended]} - } - } - } - } - }], where: { and: [ {workerFk: id}, @@ -107,76 +73,32 @@ module.exports = Self => { } }; - if (args.businessFk) - filter.where.and.push({businessFk: args.businessFk}); - const contracts = await models.WorkerLabour.find(filter, myOptions); - let [firstContract] = contracts; - let payedHolidays; + const payedHolidays = firstContract.payedHolidays; - if (firstContract.payedHolidays) - payedHolidays = firstContract.payedHolidays; - else payedHolidays = 0; + let queryIndex; + const year = started.getFullYear(); - let totalHolidays = 0; - let holidaysEnjoyed = 0; - - for (let contract of contracts) { - const contractStarted = contract.started; - contractStarted.setHours(0, 0, 0, 0); - const contractEnded = contract.ended; - if (contractEnded) - contractEnded.setHours(23, 59, 59, 59); - - let startedTime; - if (contractStarted < started) - startedTime = started.getTime(); - else startedTime = contractStarted.getTime(); - - let endedTime; - if (!contractEnded || (contractEnded && contractEnded > ended)) - endedTime = ended.getTime(); - else endedTime = contractEnded.getTime(); - - const dayTimestamp = 1000 * 60 * 60 * 24; - - // Get number of worked days between dates - let workedDays = Math.floor((endedTime - startedTime) / dayTimestamp); - workedDays += 1; // 1 day inclusion - - // Calculates absences - let entitlementRate = 0; - for (let absence of contract.absences()) { - const absenceType = absence.absenceType(); - const isHoliday = absenceType.code === 'holiday'; - const isHalfHoliday = absenceType.code === 'halfHoliday'; - - if (isHoliday) holidaysEnjoyed += 1; - if (isHalfHoliday) holidaysEnjoyed += 0.5; - - entitlementRate += absenceType.holidayEntitlementRate; - } - - workedDays -= entitlementRate; - - // Max holidays for the selected year - const maxHolidays = contract.holidays() && contract.holidays().days; - - if (workedDays < daysInYear()) - totalHolidays += Math.round(2 * maxHolidays * (workedDays) / daysInYear()) / 2; - else totalHolidays = maxHolidays; + if (args.businessFk) { + stmts.push(new ParameterizedSQL('CALL vn.workerCalendar_calculateBusiness(?,?)', [year, args.businessFk])); + queryIndex = stmts.push('SELECT * FROM tmp.workerCalendarCalculateBusiness') - 1; + stmts.push('DROP TEMPORARY TABLE tmp.workerCalendarCalculateBusiness'); + } else { + stmts.push(new ParameterizedSQL('CALL vn.workerCalendar_calculateYear(?,?)', [year, id])); + queryIndex = stmts.push('SELECT * FROM tmp.workerCalendarCalculateYear') - 1; + stmts.push('DROP TEMPORARY TABLE tmp.workerCalendarCalculateYear'); } - function daysInYear() { - const year = started.getFullYear(); + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + const [holidays] = result[queryIndex]; - return isLeapYear(year) ? 366 : 365; - } - return {totalHolidays, holidaysEnjoyed, payedHolidays}; + const totalHolidays = holidays.days; + const holidaysEnjoyed = holidays.daysEnjoyed; + const totalHours = holidays.hours; + const hoursEnjoyed = holidays.hoursEnjoyed; + + return {totalHolidays, holidaysEnjoyed, totalHours, hoursEnjoyed, payedHolidays}; }; - - function isLeapYear(year) { - return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0); - } }; diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html index 7ef586b36b..cff4d0bc9f 100644 --- a/modules/worker/front/calendar/index.html +++ b/modules/worker/front/calendar/index.html @@ -25,20 +25,28 @@ <div class="totalBox vn-mb-sm" style="text-align: center;"> <h6>{{'Contract' | translate}} #{{$ctrl.businessId}}</h6> <div> - {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed}} + {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}} {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} </div> <div> - {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays}} {{'days' | translate}} + {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}} + </div> + <div> + {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays || 0}} {{'days' | translate}} </div> </div> <div class="totalBox" style="text-align: center;"> <h6>{{'Year' | translate}} {{$ctrl.year}}</h6> <div> - {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed}} + {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}} {{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}} </div> + <div> + {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}} + </div> </div> <div class="vn-pt-md"> diff --git a/modules/worker/front/calendar/locale/es.yml b/modules/worker/front/calendar/locale/es.yml index 8e9f9cdf8d..bd75458aab 100644 --- a/modules/worker/front/calendar/locale/es.yml +++ b/modules/worker/front/calendar/locale/es.yml @@ -2,9 +2,11 @@ Calendar: Calendario Contract: Contrato Festive: Festivo Used: Utilizados +Spent: Utilizadas Year: Año of: de days: días +hours: horas Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual