Merge branch 'dev' into 3621-worker_calendar
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
74fb7c95c2
|
@ -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;
|
|
@ -1902,14 +1902,29 @@ INSERT INTO `vn`.`workCenterHoliday` (`workCenterFk`, `days`, `year`)
|
||||||
('1', '24.5', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))),
|
('1', '24.5', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))),
|
||||||
('5', '23', 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
|
VALUES
|
||||||
(1, 'Holidays', '#FF4444', 'holiday', 0),
|
(1, 'Holidays', '#FF4444', 'holiday', 0, 0),
|
||||||
(2, 'Leave of absence', '#C71585', 'absence', 0),
|
(2, 'Leave of absence', '#C71585', 'absence', 0, 1),
|
||||||
(6, 'Half holiday', '#E65F00', 'halfHoliday', 0),
|
(6, 'Half holiday', '#E65F00', 'halfHoliday', 0, 0.5),
|
||||||
(15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0),
|
(15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0, 1),
|
||||||
(20, 'Furlough', '#97B92F', 'furlough', 1),
|
(20, 'Furlough', '#97B92F', 'furlough', 1, 1),
|
||||||
(21, 'Furlough half day', '#778899', 'halfFurlough', 0.5);
|
(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`)
|
INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id`, `date`)
|
||||||
VALUES
|
VALUES
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('holidays', {
|
Self.remoteMethodCtx('holidays', {
|
||||||
|
@ -33,7 +34,8 @@ module.exports = Self => {
|
||||||
Self.holidays = async(ctx, id, options) => {
|
Self.holidays = async(ctx, id, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const args = ctx.args;
|
const args = ctx.args;
|
||||||
|
const conn = Self.dataSource.connector;
|
||||||
|
const stmts = [];
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
|
@ -56,42 +58,6 @@ module.exports = Self => {
|
||||||
ended.setHours(23, 59, 59, 59);
|
ended.setHours(23, 59, 59, 59);
|
||||||
|
|
||||||
const filter = {
|
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: {
|
where: {
|
||||||
and: [
|
and: [
|
||||||
{workerFk: id},
|
{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);
|
const contracts = await models.WorkerLabour.find(filter, myOptions);
|
||||||
|
|
||||||
let [firstContract] = contracts;
|
let [firstContract] = contracts;
|
||||||
let payedHolidays;
|
const payedHolidays = firstContract.payedHolidays;
|
||||||
|
|
||||||
if (firstContract.payedHolidays)
|
let queryIndex;
|
||||||
payedHolidays = firstContract.payedHolidays;
|
|
||||||
else payedHolidays = 0;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function daysInYear() {
|
|
||||||
const year = started.getFullYear();
|
const year = started.getFullYear();
|
||||||
|
|
||||||
return isLeapYear(year) ? 366 : 365;
|
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');
|
||||||
}
|
}
|
||||||
return {totalHolidays, holidaysEnjoyed, payedHolidays};
|
|
||||||
};
|
|
||||||
|
|
||||||
function isLeapYear(year) {
|
const sql = ParameterizedSQL.join(stmts, ';');
|
||||||
return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0);
|
const result = await conn.executeStmt(sql, myOptions);
|
||||||
}
|
const [holidays] = result[queryIndex];
|
||||||
|
|
||||||
|
const totalHolidays = holidays.days;
|
||||||
|
const holidaysEnjoyed = holidays.daysEnjoyed;
|
||||||
|
const totalHours = holidays.hours;
|
||||||
|
const hoursEnjoyed = holidays.hoursEnjoyed;
|
||||||
|
|
||||||
|
return {totalHolidays, holidaysEnjoyed, totalHours, hoursEnjoyed, payedHolidays};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,20 +25,28 @@
|
||||||
<div class="totalBox vn-mb-sm" style="text-align: center;">
|
<div class="totalBox vn-mb-sm" style="text-align: center;">
|
||||||
<h6>{{'Contract' | translate}} #{{$ctrl.businessId}}</h6>
|
<h6>{{'Contract' | translate}} #{{$ctrl.businessId}}</h6>
|
||||||
<div>
|
<div>
|
||||||
{{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed}}
|
{{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}}
|
||||||
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
|
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
|
||||||
</div>
|
</div>
|
||||||
<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>
|
</div>
|
||||||
|
|
||||||
<div class="totalBox" style="text-align: center;">
|
<div class="totalBox" style="text-align: center;">
|
||||||
<h6>{{'Year' | translate}} {{$ctrl.year}}</h6>
|
<h6>{{'Year' | translate}} {{$ctrl.year}}</h6>
|
||||||
<div>
|
<div>
|
||||||
{{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed}}
|
{{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}}
|
||||||
{{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}}
|
{{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
{{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}}
|
||||||
|
{{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="vn-pt-md">
|
<div class="vn-pt-md">
|
||||||
|
|
|
@ -2,9 +2,11 @@ Calendar: Calendario
|
||||||
Contract: Contrato
|
Contract: Contrato
|
||||||
Festive: Festivo
|
Festive: Festivo
|
||||||
Used: Utilizados
|
Used: Utilizados
|
||||||
|
Spent: Utilizadas
|
||||||
Year: Año
|
Year: Año
|
||||||
of: de
|
of: de
|
||||||
days: días
|
days: días
|
||||||
|
hours: horas
|
||||||
Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha
|
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
|
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
|
You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual
|
||||||
|
|
Loading…
Reference in New Issue