3928-worker.time-control_sendMail #1129
|
@ -1,182 +0,0 @@
|
||||||
const Imap = require('imap');
|
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethod('checkInbox', {
|
|
||||||
description: 'Check an email inbox and process it',
|
|
||||||
accessType: 'READ',
|
|
||||||
returns:
|
|
||||||
{
|
|
||||||
arg: 'body',
|
|
||||||
type: 'file',
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/checkInbox`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.checkInbox = async() => {
|
|
||||||
let imapConfig = await Self.app.models.WorkerTimeControlParams.findOne();
|
|
||||||
let imap = new Imap({
|
|
||||||
user: imapConfig.mailUser,
|
|
||||||
password: imapConfig.mailPass,
|
|
||||||
host: imapConfig.mailHost,
|
|
||||||
port: 993,
|
|
||||||
tls: true
|
|
||||||
});
|
|
||||||
let isEmailOk;
|
|
||||||
let uid;
|
|
||||||
let emailBody;
|
|
||||||
|
|
||||||
function openInbox(cb) {
|
|
||||||
imap.openBox('INBOX', true, cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
imap.once('ready', function() {
|
|
||||||
openInbox(function(err, box) {
|
|
||||||
if (err) throw err;
|
|
||||||
const totalMessages = box.messages.total;
|
|
||||||
if (totalMessages == 0)
|
|
||||||
imap.end();
|
|
||||||
|
|
||||||
let f = imap.seq.fetch('1:*', {
|
|
||||||
bodies: ['HEADER.FIELDS (FROM SUBJECT)', '1'],
|
|
||||||
struct: true
|
|
||||||
});
|
|
||||||
f.on('message', function(msg, seqno) {
|
|
||||||
isEmailOk = false;
|
|
||||||
msg.on('body', function(stream, info) {
|
|
||||||
let buffer = '';
|
|
||||||
let bufferCopy = '';
|
|
||||||
stream.on('data', function(chunk) {
|
|
||||||
buffer = chunk.toString('utf8');
|
|
||||||
if (info.which === '1' && bufferCopy.length == 0)
|
|
||||||
bufferCopy = buffer.replace(/\s/g, ' ');
|
|
||||||
});
|
|
||||||
stream.on('end', function() {
|
|
||||||
if (bufferCopy.length > 0) {
|
|
||||||
emailBody = bufferCopy.toUpperCase().trim();
|
|
||||||
|
|
||||||
const bodyPositionOK = emailBody.match(/\bOK\b/i);
|
|
||||||
const bodyPositionIndex = (bodyPositionOK.index == 0 || bodyPositionOK.index == 122);
|
|
||||||
if (bodyPositionOK != null && bodyPositionIndex)
|
|
||||||
isEmailOk = true;
|
|
||||||
else
|
|
||||||
isEmailOk = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
msg.once('attributes', function(attrs) {
|
|
||||||
uid = attrs.uid;
|
|
||||||
});
|
|
||||||
msg.once('end', function() {
|
|
||||||
if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') {
|
|
||||||
if (isEmailOk) {
|
|
||||||
imap.move(uid, 'exito', function(err) {
|
|
||||||
});
|
|
||||||
emailConfirm(buffer);
|
|
||||||
} else {
|
|
||||||
imap.move(uid, 'error', function(err) {
|
|
||||||
});
|
|
||||||
emailReply(buffer, emailBody);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
f.once('end', function() {
|
|
||||||
imap.end();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
imap.connect();
|
|
||||||
return 'Leer emails de gestion horaria';
|
|
||||||
};
|
|
||||||
|
|
||||||
async function emailConfirm(buffer) {
|
|
||||||
const now = new Date();
|
|
||||||
const from = JSON.stringify(Imap.parseHeader(buffer).from);
|
|
||||||
const subject = JSON.stringify(Imap.parseHeader(buffer).subject);
|
|
||||||
|
|
||||||
const timeControlDate = await getEmailDate(subject);
|
|
||||||
const week = timeControlDate[0];
|
|
||||||
const year = timeControlDate[1];
|
|
||||||
const user = await getUser(from);
|
|
||||||
let workerMail;
|
|
||||||
|
|
||||||
if (user.id != null) {
|
|
||||||
workerMail = await Self.app.models.WorkerTimeControlMail.findOne({
|
|
||||||
where: {
|
|
||||||
week: week,
|
|
||||||
year: year,
|
|
||||||
workerFk: user.id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (workerMail != null) {
|
|
||||||
await workerMail.updateAttributes({
|
|
||||||
updated: now,
|
|
||||||
state: 'CONFIRMED'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function emailReply(buffer, emailBody) {
|
|
||||||
const now = new Date();
|
|
||||||
const from = JSON.stringify(Imap.parseHeader(buffer).from);
|
|
||||||
const subject = JSON.stringify(Imap.parseHeader(buffer).subject);
|
|
||||||
|
|
||||||
const timeControlDate = await getEmailDate(subject);
|
|
||||||
const week = timeControlDate[0];
|
|
||||||
const year = timeControlDate[1];
|
|
||||||
const user = await getUser(from);
|
|
||||||
let workerMail;
|
|
||||||
|
|
||||||
if (user.id != null) {
|
|
||||||
workerMail = await Self.app.models.WorkerTimeControlMail.findOne({
|
|
||||||
where: {
|
|
||||||
week: week,
|
|
||||||
year: year,
|
|
||||||
workerFk: user.id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (workerMail != null) {
|
|
||||||
await workerMail.updateAttributes({
|
|
||||||
updated: now,
|
|
||||||
state: 'REVISE',
|
|
||||||
emailResponse: emailBody
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
await sendMail(user, subject, emailBody);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getUser(workerEmail) {
|
|
||||||
const userEmail = workerEmail.match(/(?<=<)(.*?)(?=>)/);
|
|
||||||
|
|
||||||
let [user] = await Self.rawSql(`SELECT u.id,u.name FROM account.user u
|
|
||||||
LEFT JOIN account.mailForward m on m.account = u.id
|
|
||||||
WHERE forwardTo =? OR
|
|
||||||
CONCAT(u.name,'@verdnatura.es') = ?`,
|
|
||||||
[userEmail[0], userEmail[0]]);
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getEmailDate(subject) {
|
|
||||||
const date = subject.match(/\d+/g);
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendMail(user, subject, emailBody) {
|
|
||||||
const sendTo = 'rrhh@verdnatura.es';
|
|
||||||
const emailSubject = subject + ' ' + user.name;
|
|
||||||
|
|
||||||
await Self.app.models.Mail.create({
|
|
||||||
receiver: sendTo,
|
|
||||||
subject: emailSubject,
|
|
||||||
body: emailBody
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -225,11 +225,11 @@ module.exports = Self => {
|
||||||
for (let journey of journeys) {
|
for (let journey of journeys) {
|
||||||
const start = new Date();
|
const start = new Date();
|
||||||
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
||||||
start.setHours(startHours, startMinutes, startSeconds);
|
start.setHours(startHours, startMinutes, startSeconds, 0);
|
||||||
|
|
||||||
const end = new Date();
|
const end = new Date();
|
||||||
const [endHours, endMinutes, endSeconds] = getTime(journey.end);
|
const [endHours, endMinutes, endSeconds] = getTime(journey.end);
|
||||||
end.setHours(endHours, endMinutes, endSeconds);
|
end.setHours(endHours, endMinutes, endSeconds, 0);
|
||||||
|
|
||||||
const result = (end - start) / 1000;
|
const result = (end - start) / 1000;
|
||||||
timeTableDecimalInSeconds += result;
|
timeTableDecimalInSeconds += result;
|
||||||
|
@ -237,6 +237,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
for (let journey of journeys) {
|
for (let journey of journeys) {
|
||||||
const timeTableDecimal = timeTableDecimalInSeconds / 3600;
|
const timeTableDecimal = timeTableDecimalInSeconds / 3600;
|
||||||
|
console.log(timeTableDecimal);
|
||||||
if (day.timeWorkDecimal == timeTableDecimal) {
|
if (day.timeWorkDecimal == timeTableDecimal) {
|
||||||
const timed = new Date(day.dated);
|
const timed = new Date(day.dated);
|
||||||
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
||||||
|
@ -349,11 +350,11 @@ module.exports = Self => {
|
||||||
body: `${salix.url}worker/${previousWorkerFk}/time-control?timestamp=${timestamp}`
|
body: `${salix.url}worker/${previousWorkerFk}/time-control?timestamp=${timestamp}`
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
await models.WorkerTimeControlMail.create({
|
// await models.WorkerTimeControlMail.create({
|
||||||
workerFk: previousWorkerFk,
|
// workerFk: previousWorkerFk,
|
||||||
week: args.week,
|
// week: args.week,
|
||||||
year: args.year
|
// year: args.year
|
||||||
}, myOptions);
|
// }, myOptions);
|
||||||
|
|
||||||
previousWorkerFk = day.workerFk;
|
previousWorkerFk = day.workerFk;
|
||||||
previousReceiver = day.receiver;
|
previousReceiver = day.receiver;
|
||||||
|
|
|
@ -0,0 +1,529 @@
|
||||||
|
/* eslint max-len: ["error", { "code": 150 }]*/
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('workerTimeControl sendMail()', () => {
|
||||||
|
const HHRRId = 37;
|
||||||
|
const teamBossId = 13;
|
||||||
|
const employeeId = 1;
|
||||||
|
const salesPersonId = 1106;
|
||||||
|
const salesBossId = 19;
|
||||||
|
const hankPymId = 1107;
|
||||||
|
const jessicaJonesId = 1110;
|
||||||
|
const monday = 1;
|
||||||
|
const tuesday = 2;
|
||||||
|
const thursday = 4;
|
||||||
|
const friday = 5;
|
||||||
|
const saturday = 6;
|
||||||
|
const sunday = 7;
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 50},
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('WorkerTimeControl_clockIn calls', () => {
|
||||||
|
it('should fail to add a time entry if the target user has an absence that day', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
const date = new Date();
|
||||||
|
date.setDate(date.getDate() - 16);
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`No está permitido trabajar`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to add a time entry for a worker without an existing contract', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 2);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`No hay un contrato en vigor`);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('direction errors', () => {
|
||||||
|
it('should throw an error when trying "in" direction twice', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(10, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Dirección incorrecta`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when trying "in" direction after insert "in" and "middle"', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(9, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'middle'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(10, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Dirección incorrecta`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should throw an error when trying "out" before closing a "middle" couple', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(9, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'middle'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(10, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Dirección incorrecta`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when trying "middle" after "out"', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(9, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(10, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'middle'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Dirección incorrecta`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when trying "out" direction twice', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(9, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(10, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Dirección incorrecta`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('12h rest', () => {
|
||||||
|
it('should throw an error when the 12h rest is not fulfilled yet', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(16, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date = weekDay(date, tuesday);
|
||||||
|
date.setHours(4, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Descanso diario 12h.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not fail as the 12h rest is fulfilled', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(16, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date = weekDay(date, tuesday);
|
||||||
|
date.setHours(4, 1, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).not.toBeDefined;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('for 3500kg drivers with enforced 9h rest', () => {
|
||||||
|
it('should throw an error when the 9h enforced rest is not fulfilled', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = jessicaJonesId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(16, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date = weekDay(date, tuesday);
|
||||||
|
date.setHours(1, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Descanso diario 9h.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not fail when the 9h enforced rest is fulfilled', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = jessicaJonesId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setDate(date.getDate() - 21);
|
||||||
|
date = weekDay(date, monday);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
date.setHours(16, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date = weekDay(date, tuesday);
|
||||||
|
date.setHours(1, 1, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).not.toBeDefined;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('for 36h weekly rest', () => {
|
||||||
|
it('should throw an error when the 36h weekly rest is not fulfilled', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setMonth(date.getMonth() - 2);
|
||||||
|
date.setDate(1);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
await populateWeek(date, monday, sunday, ctx, workerId, options);
|
||||||
|
date = nextWeek(date);
|
||||||
|
await populateWeek(date, monday, thursday, ctx, workerId, options);
|
||||||
|
date = weekDay(date, friday);
|
||||||
|
date.setHours(7, 59, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(8, 1, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Descanso semanal 36h. / 72h.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when the 36h weekly rest is not fulfilled again', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setMonth(date.getMonth() - 2);
|
||||||
|
date.setDate(1);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
await populateWeek(date, monday, sunday, ctx, workerId, options);
|
||||||
|
date = nextWeek(date);
|
||||||
|
await populateWeek(date, monday, thursday, ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date = weekDay(date, saturday);
|
||||||
|
date.setHours(3, 59, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Descanso semanal 36h. / 72h.`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('for 72h weekly rest', () => {
|
||||||
|
it('should throw when the 72h weekly rest is not fulfilled yet', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
|
||||||
|
let date = new Date();
|
||||||
|
date.setMonth(date.getMonth() - 2);
|
||||||
|
date.setDate(1);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
await populateWeek(date, monday, sunday, ctx, workerId, options);
|
||||||
|
date = nextWeek(date);
|
||||||
|
await populateWeek(date, monday, thursday, ctx, workerId, options);
|
||||||
|
date = nextWeek(date);
|
||||||
|
await populateWeek(date, monday, friday, ctx, workerId, options);
|
||||||
|
date = nextWeek(date);
|
||||||
|
await populateWeek(date, monday, saturday, ctx, workerId, options);
|
||||||
|
date = nextWeek(date);
|
||||||
|
await populateWeek(date, monday, saturday, ctx, workerId, options);
|
||||||
|
date = lastWeek(date);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date = weekDay(date, sunday);
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`Descanso semanal 36h. / 72h.`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function weekDay(date, dayToSet) {
|
||||||
|
const currentDay = date.getDay();
|
||||||
|
const distance = dayToSet - currentDay;
|
||||||
|
|
||||||
|
date.setDate(date.getDate() + distance);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextWeek(date) {
|
||||||
|
const sunday = 7;
|
||||||
|
const currentDay = date.getDay();
|
||||||
|
let newDate = date;
|
||||||
|
if (currentDay != 0)
|
||||||
|
newDate = weekDay(date, sunday);
|
||||||
|
|
||||||
|
newDate.setDate(newDate.getDate() + 1);
|
||||||
|
return newDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lastWeek(date) {
|
||||||
|
const monday = 1;
|
||||||
|
newDate = weekDay(date, monday);
|
||||||
|
|
||||||
|
newDate.setDate(newDate.getDate() - 1);
|
||||||
|
return newDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function populateWeek(date, dayStart, dayEnd, ctx, workerId, options) {
|
||||||
|
const dateStart = new Date(weekDay(date, dayStart));
|
||||||
|
const dateEnd = new Date(dateStart);
|
||||||
|
dateEnd.setDate(dateStart.getDate() + dayEnd);
|
||||||
|
|
||||||
|
for (let i = dayStart; i <= dayEnd; i++) {
|
||||||
|
dateStart.setHours(8, 0, 0);
|
||||||
|
ctx.args = {timed: dateStart, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
dateStart.setHours(16, 0, 0);
|
||||||
|
ctx.args = {timed: dateStart, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
dateStart.setDate(dateStart.getDate() + 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
require('../methods/worker-time-control-mail/checkInbox')(Self);
|
|
||||||
};
|
|
Loading…
Reference in New Issue