salix/modules/worker/back/methods/worker/createAbsence.js

166 lines
6.1 KiB
JavaScript

const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('createAbsence', {
description: 'Creates a new worker absence',
accepts: [{
arg: 'id',
type: 'number',
description: 'The worker id',
http: {source: 'path'}
},
{
arg: 'businessFk',
type: 'number',
required: true
},
{
arg: 'absenceTypeId',
type: 'number',
required: true
},
{
arg: 'dated',
type: 'date',
required: true
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/:id/createAbsence`,
verb: 'POST'
}
});
Self.createAbsence = async(ctx, id, options) => {
const models = Self.app.models;
const $t = ctx.req.__; // $translate
const args = ctx.args;
const userId = ctx.req.accessToken.userId;
let tx;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const isSubordinate = await models.Worker.isSubordinate(ctx, id, myOptions);
const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE');
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
throw new UserError(`You don't have enough privileges`);
const canCreateAbsenceInPast =
await models.ACL.checkAccessAcl(ctx, 'Worker', 'canCreateAbsenceInPast', 'WRITE');
const now = Date.vnNew();
const newDate = new Date(args.dated).getTime();
if ((now.getTime() > newDate) && !canCreateAbsenceInPast)
throw new UserError(`Holidays to past days not available`);
const labour = await models.WorkerLabour.findById(args.businessFk,
{fields: ['started', 'ended', 'businessFk']}, myOptions);
if (args.dated < labour.started || (labour.ended != null && args.dated > labour.ended))
throw new UserError(`The contract was not active during the selected date`);
const [hasHoursRecorded] = await Self.rawSql(`SELECT *
FROM vn.workerTimeControl
WHERE userFk = ? AND timed BETWEEN DATE(?) AND CONCAT(DATE(?), ' 23:59:59')
LIMIT 1;`, [id, args.dated, args.dated]);
const absenceType = await models.AbsenceType.findById(args.absenceTypeId, null, myOptions);
const isNotHalfAbsence = absenceType.code != 'halfHoliday'
&& absenceType.code != 'halfPaidLeave'
&& absenceType.code != 'halfFurlough';
if (hasHoursRecorded && isNotHalfAbsence)
throw new UserError(`The worker has hours recorded that day`);
const date = Date.vnNew();
date.setHours(0, 0, 0, 0);
const [result] = await Self.rawSql(
`SELECT COUNT(*) halfHolidayCounter
FROM vn.calendar c
JOIN vn.business b ON b.id = c.businessFk
JOIN vn.absenceType at ON at.id = c.dayOffTypeFk
WHERE at.code = 'halfHoliday'
AND b.workerFk = ?
AND c.dated BETWEEN util.firstDayOfYear(?)
AND LAST_DAY(DATE_ADD(?, INTERVAL 12 - MONTH(?) MONTH))`, [id, date, now, now]);
const hasHalfHoliday = result.halfHolidayCounter > 0;
const isHalfHoliday = absenceType.code === 'halfHoliday';
if (isHalfHoliday && hasHalfHoliday)
throw new UserError(`Cannot add more than one '1/2 day vacation'`);
const isFestive = absenceType.isFestiveEligible;
const workCenter = await models.Business.findOne({
where: {id: args.businessFk}
},);
const [holiday] = await models.CalendarHoliday.find({
where: {
dated: args.dated,
workCenterFk: workCenter.workCenterFk
}
});
if ((holiday && isFestive) && (workCenter.workcenterFk === holiday.workCenterFk))
throw new UserError(`Cannot add holidays on this day`);
const absence = await models.Calendar.create({
businessFk: labour.businessFk,
dayOffTypeFk: args.absenceTypeId,
dated: args.dated
}, myOptions);
const account = await models.VnUser.findById(userId, null, myOptions);
const subordinated = await models.VnUser.findById(id, null, myOptions);
const worker = await models.Worker.findById(subordinated.id, null, myOptions);
const departmentBoss = await models.VnUser.findById(worker.bossFk, null, myOptions);
const url = await Self.app.models.Url.getUrl();
const body = $t('Created absence', {
author: account.nickname,
employee: subordinated.nickname,
absenceType: absenceType.name,
dated: formatDate(args.dated),
workerUrl: `${url}worker/${id}/calendar`
});
await models.Mail.create({
subject: $t('Absence change notification on the labour calendar'),
body: body,
receiver: departmentBoss.email
}, myOptions);
if (tx) await tx.commit();
return absence;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
function formatDate(date) {
let day = date.getDate();
if (day < 10) day = `0${day}`;
let month = date.getMonth() + 1;
if (month < 10) month = `0${month}`;
let year = date.getFullYear();
return `${day}-${month}-${year}`;
}
};