const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('absences', { description: 'Returns an array of absences from an specified worker', accessType: '', 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, started, ended) => { const models = Self.app.models; const conn = Self.dataSource.connector; const myUserId = ctx.req.accessToken.userId; const myWorker = await models.Worker.findOne({where: {userFk: myUserId}}); const calendar = {totalHolidays: 0, holidaysEnjoyed: 0}; const holidays = []; const stmts = []; // Get subordinates stmts.push(new ParameterizedSQL('CALL vn.subordinateGetList(?)', [myWorker.id])); let subordinatesIndex = stmts.push('SELECT * FROM tmp.subordinate') - 1; let sql = ParameterizedSQL.join(stmts, ';'); let result = await conn.executeStmt(sql); const subordinates = result[subordinatesIndex]; const isSubordinate = subordinates.find(subordinate => { return subordinate.workerFk === workerFk; }); const isHr = await models.Account.hasRole(myUserId, 'hr'); if (!isHr && workerFk !== myWorker.id && !isSubordinate) throw new UserError(`You don't have enough privileges`); // Get absences of year let absences = await Self.find({ include: { relation: 'absenceType' }, where: { workerFk: workerFk, dated: {between: [started, ended]} } }); absences.forEach(absence => { if (absence.absenceType().id === 1) calendar.holidaysEnjoyed++; absence.dated = new Date(absence.dated); absence.dated.setHours(0, 0, 0, 0); }); // Get active contracts on current year const year = started.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: [started, ended]} } } } } }], where: { and: [ {workerFk: workerFk}, {or: [{ ended: {gte: [started]} }, {ended: null}]} ], } }); // Get number of total holidays contracts.forEach(contract => { let totalHolidays = contract.holidays().days; if (contract.started && contract.ended) totalHolidays = getHolidaysByContract(started, contract); calendar.totalHolidays += totalHolidays; 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); } }); return [calendar, absences, holidays]; }; function getHolidaysByContract(started, contract) { const dayTimestamp = 1000 * 60 * 60 * 24; const endedTime = contract.ended.getTime(); const startedTime = started.getTime(); const contractDays = Math.floor((endedTime - startedTime) / dayTimestamp); if (contractDays < 365) { let holidays = contract.holidays().days * (contractDays + 1) / 365; let integerPart = parseInt(holidays); let decimalPart = holidays - integerPart; let decimal = decimalPart >= 0.5 ? 0.5 : 0; holidays = integerPart + decimal; return holidays; } return contract.holidays().days; } };