const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('absences', { description: 'Returns an array of absences from an specified worker', accepts: [{ arg: 'workerFk', type: 'Number', required: true, }, { arg: 'started', type: 'Date', required: true, }, { arg: 'ended', type: 'Date', required: true, }], returns: [{ arg: 'calendar' }, { arg: 'absences', type: 'Number' }, { arg: 'holidays', type: 'Number' }], http: { path: `/absences`, verb: 'GET' } }); Self.absences = async(ctx, workerFk, yearStarted, yearEnded) => { const models = Self.app.models; const isSubordinate = await models.Worker.isSubordinate(ctx, workerFk); if (!isSubordinate) throw new UserError(`You don't have enough privileges`); const calendar = {totalHolidays: 0, holidaysEnjoyed: 0}; const holidays = []; // Get active contracts on current year const year = yearStarted.getFullYear(); const contracts = await models.WorkerLabour.find({ include: [{ relation: 'holidays', scope: { where: {year} } }, { relation: 'workCenter', scope: { include: { relation: 'holidays', scope: { include: [{ relation: 'detail' }, { relation: 'type' }], where: { dated: {between: [yearStarted, yearEnded]} } } } } }], where: { and: [ {workerFk: workerFk}, {or: [{ ended: {gte: [yearStarted]} }, {ended: null}]} ], } }); // Contracts ids const contractsId = contracts.map(contract => { return contract.businessFk; }); // Get absences of year let absences = await Self.find({ include: { relation: 'absenceType' }, where: { businessFk: {inq: contractsId}, dated: {between: [yearStarted, yearEnded]} } }); let entitlementRate = 0; absences.forEach(absence => { const absenceType = absence.absenceType(); const isHoliday = absenceType.code === 'holiday'; const isHalfHoliday = absenceType.code === 'halfHoliday'; if (isHoliday) calendar.holidaysEnjoyed += 1; if (isHalfHoliday) calendar.holidaysEnjoyed += 0.5; entitlementRate += absenceType.holidayEntitlementRate; absence.dated = new Date(absence.dated); absence.dated.setHours(0, 0, 0, 0); }); // Get number of worked days let workedDays = 0; contracts.forEach(contract => { const started = contract.started; const ended = contract.ended; const startedTime = started.getTime(); const endedTime = ended && ended.getTime() || yearEnded; const dayTimestamp = 1000 * 60 * 60 * 24; workedDays += Math.floor((endedTime - startedTime) / dayTimestamp); if (workedDays > daysInYear()) workedDays = daysInYear(); // Workcenter holidays let holidayList = contract.workCenter().holidays(); for (let day of holidayList) { day.dated = new Date(day.dated); day.dated.setHours(0, 0, 0, 0); holidays.push(day); } }); const currentContract = contracts.find(contract => { return contract.started <= new Date() && (contract.ended >= new Date() || contract.ended == null); }); if (currentContract) { const maxHolidays = currentContract.holidays() && currentContract.holidays().days; calendar.totalHolidays = maxHolidays; workedDays -= entitlementRate; if (workedDays < daysInYear()) calendar.totalHolidays = Math.round(2 * maxHolidays * (workedDays) / daysInYear()) / 2; } function daysInYear() { const year = yearStarted.getFullYear(); return isLeapYear(year) ? 366 : 365; } return [calendar, absences, holidays]; }; function isLeapYear(year) { return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0); } };