#6274 workerTimeControl #1858
|
@ -1,8 +1,29 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('workerTimeControl clockIn()', () => {
|
describe('workerTimeControl clockIn()', () => {
|
||||||
const workerId = 9;
|
const workerId = 9;
|
||||||
|
const salesBossId = 19;
|
||||||
|
const hankPymId = 1107;
|
||||||
|
const jessicaJonesId = 1110;
|
||||||
|
const HHRRId = 37;
|
||||||
|
const teamBossId = 13;
|
||||||
|
const monday = 1;
|
||||||
|
const tuesday = 2;
|
||||||
|
const thursday = 4;
|
||||||
|
const friday = 5;
|
||||||
|
const sunday = 7;
|
||||||
const inTime = '2001-01-01T00:00:00.000Z';
|
const inTime = '2001-01-01T00:00:00.000Z';
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 50},
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should correctly clock in', async() => {
|
it('should correctly clock in', async() => {
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
@ -24,5 +45,537 @@ describe('workerTimeControl clockIn()', () => {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('as Role errors', () => {
|
||||||
|
it('should add if the current user is team boss and the target user is himself', async() => {
|
||||||
|
activeCtx.accessToken.userId = teamBossId;
|
||||||
|
const workerId = teamBossId;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const todayAtOne = Date.vnNew();
|
||||||
|
todayAtOne.setHours(1, 0, 0, 0);
|
||||||
|
|
||||||
|
ctx.args = {timed: todayAtOne, direction: 'in'};
|
||||||
|
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
expect(createdTimeEntry.id).toBeDefined();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete the created time entry for the team boss as himself', async() => {
|
||||||
|
activeCtx.accessToken.userId = teamBossId;
|
||||||
|
const workerId = teamBossId;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const todayAtOne = Date.vnNew();
|
||||||
|
todayAtOne.setHours(1, 0, 0, 0);
|
||||||
|
|
||||||
|
ctx.args = {timed: todayAtOne, direction: 'in'};
|
||||||
|
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
expect(createdTimeEntry.id).toBeDefined();
|
||||||
|
|
||||||
|
await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options);
|
||||||
|
|
||||||
|
const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options);
|
||||||
|
|
||||||
|
expect(deletedTimeEntry).toBeNull();
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should edit the created time entry for the team boss as HHRR', async() => {
|
||||||
|
activeCtx.accessToken.userId = HHRRId;
|
||||||
|
const workerId = teamBossId;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const todayAtOne = Date.vnNew();
|
||||||
|
todayAtOne.setHours(1, 0, 0, 0);
|
||||||
|
|
||||||
|
ctx.args = {timed: todayAtOne, direction: 'in'};
|
||||||
|
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
expect(createdTimeEntry.id).toBeDefined();
|
||||||
|
|
||||||
|
ctx.args = {direction: 'out'};
|
||||||
|
const updatedTimeEntry = await models.WorkerTimeControl.updateTimeEntry(
|
||||||
|
ctx, createdTimeEntry.id, options
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(updatedTimeEntry.direction).toEqual('out');
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('as saleBoss editor', () => {
|
||||||
|
let workerId;
|
||||||
|
beforeEach(() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
workerId = hankPymId;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to add a time entry if the target user has an absence that day', async() => {
|
||||||
|
const date = Date.vnNew();
|
||||||
|
date.setHours(8, 0, 0);
|
||||||
|
date.setDate(date.getDate() - 16);
|
||||||
|
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() => {
|
||||||
|
const date = Date.vnNew();
|
||||||
|
date.setFullYear(date.getFullYear() - 2);
|
||||||
|
|
||||||
|
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 hay un contrato en vigor`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to add a time entry for a worker without an existing contract and exceeding time', async() => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 2);
|
||||||
|
let error;
|
||||||
|
|
||||||
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
date.setHours(0, 0, 0);
|
||||||
|
ctx.args = {timed: date, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
|
||||||
|
try {
|
||||||
|
date.setHours(20, 0, 1);
|
||||||
|
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(`Superado el tiempo máximo entre entrada y salida`);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('direction errors', () => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 1);
|
||||||
|
let error;
|
||||||
|
it('should throw an error when trying "in" direction twice', async() => {
|
||||||
|
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() => {
|
||||||
|
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() => {
|
||||||
|
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() => {
|
||||||
|
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() => {
|
||||||
|
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', () => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = hankPymId;
|
||||||
|
it('should throw an error when the 12h rest is not fulfilled yet', async() => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 2);
|
||||||
|
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`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not fail as the 12h rest is fulfilled', async() => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 2);
|
||||||
|
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', () => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = jessicaJonesId;
|
||||||
|
it('should throw an error when the 9h enforced rest is not fulfilled', async() => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 2);
|
||||||
|
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`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not fail when the 9h enforced rest is fulfilled', async() => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setDate(date.getDate() - 2);
|
||||||
|
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 72h weekly rest', () => {
|
||||||
|
|
||||||
|
it('should throw an error when work 11 consecutive days', async() => {
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setMonth(date.getMonth() - 1);
|
||||||
|
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, friday);
|
||||||
|
date.setHours(10, 0, 1);
|
||||||
|
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`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when the 72h weekly rest is not fulfilled', async() => {
|
||||||
|
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setMonth(date.getMonth() - 1);
|
||||||
|
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, sunday);
|
||||||
|
date.setHours(17, 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`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when the 72h weekly rest is fulfilled', async() => {
|
||||||
|
|
||||||
|
let date = Date.vnNew();
|
||||||
|
date.setMonth(date.getMonth() - 1);
|
||||||
|
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, sunday);
|
||||||
|
date.setHours(18, 00, 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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(10, 0, 0);
|
||||||
|
ctx.args = {timed: dateStart, direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
dateStart.setHours(18, 0, 0);
|
||||||
|
ctx.args = {timed: dateStart, direction: 'out'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||||
|
dateStart.setDate(dateStart.getDate() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ describe('workerTimeControl login()', () => {
|
||||||
await models.WorkerTimeControl.login();
|
await models.WorkerTimeControl.login();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
expect(error).toBeInstanceOf(UserError);
|
expect(error).toBeInstanceOf(UserError);
|
||||||
expect(error.message).toBe('Indique el pin.');
|
expect(error.message).toBe('Incorrect pin.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,18 +3,10 @@ const models = require('vn-loopback/server/server').models;
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('workerTimeControl add/delete timeEntry()', () => {
|
describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
const HHRRId = 37;
|
|
||||||
const teamBossId = 13;
|
|
||||||
const employeeId = 1;
|
const employeeId = 1;
|
||||||
const salesPersonId = 1106;
|
|
||||||
const salesBossId = 19;
|
const salesBossId = 19;
|
||||||
const hankPymId = 1107;
|
const hankPymId = 1107;
|
||||||
const jessicaJonesId = 1110;
|
|
||||||
const monday = 1;
|
const monday = 1;
|
||||||
const tuesday = 2;
|
|
||||||
const thursday = 4;
|
|
||||||
const friday = 5;
|
|
||||||
const sunday = 7;
|
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
accessToken: {userId: 50},
|
accessToken: {userId: 50},
|
||||||
};
|
};
|
||||||
|
@ -61,559 +53,10 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
expect(error.statusCode).toBe(400);
|
expect(error.statusCode).toBe(400);
|
||||||
expect(error.message).toBe(`You don't have enough privileges`);
|
expect(error.message).toBe(`You don't have enough privileges`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add if the current user is team boss and the target user is himself', async() => {
|
|
||||||
activeCtx.accessToken.userId = teamBossId;
|
|
||||||
const workerId = teamBossId;
|
|
||||||
|
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
|
|
||||||
const todayAtOne = Date.vnNew();
|
|
||||||
todayAtOne.setHours(1, 0, 0, 0);
|
|
||||||
|
|
||||||
ctx.args = {timed: todayAtOne, direction: 'in'};
|
|
||||||
const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
|
||||||
|
|
||||||
expect(createdTimeEntry.id).toBeDefined();
|
|
||||||
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should try but fail to delete his own time entry', async() => {
|
|
||||||
activeCtx.accessToken.userId = salesBossId;
|
|
||||||
const workerId = salesBossId;
|
|
||||||
|
|
||||||
let error;
|
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
|
|
||||||
const todayAtOne = Date.vnNew();
|
|
||||||
todayAtOne.setHours(1, 0, 0, 0);
|
|
||||||
|
|
||||||
ctx.args = {timed: todayAtOne, direction: 'in'};
|
|
||||||
const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
|
||||||
|
|
||||||
activeCtx.accessToken.userId = salesPersonId;
|
|
||||||
await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options);
|
|
||||||
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
error = e;
|
|
||||||
await tx.rollback();
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(error).toBeDefined();
|
|
||||||
expect(error.statusCode).toBe(400);
|
|
||||||
expect(error.message).toBe(`You don't have enough privileges`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the created time entry for the team boss as himself', async() => {
|
|
||||||
activeCtx.accessToken.userId = teamBossId;
|
|
||||||
const workerId = teamBossId;
|
|
||||||
|
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
|
|
||||||
const todayAtOne = Date.vnNew();
|
|
||||||
todayAtOne.setHours(1, 0, 0, 0);
|
|
||||||
|
|
||||||
ctx.args = {timed: todayAtOne, direction: 'in'};
|
|
||||||
const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
|
||||||
|
|
||||||
expect(createdTimeEntry.id).toBeDefined();
|
|
||||||
|
|
||||||
await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options);
|
|
||||||
|
|
||||||
const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options);
|
|
||||||
|
|
||||||
expect(deletedTimeEntry).toBeNull();
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the created time entry for the team boss as HHRR', async() => {
|
|
||||||
activeCtx.accessToken.userId = HHRRId;
|
|
||||||
const workerId = teamBossId;
|
|
||||||
|
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
|
|
||||||
const todayAtOne = Date.vnNew();
|
|
||||||
todayAtOne.setHours(1, 0, 0, 0);
|
|
||||||
|
|
||||||
ctx.args = {timed: todayAtOne, direction: 'in'};
|
|
||||||
const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
|
||||||
|
|
||||||
expect(createdTimeEntry.id).toBeDefined();
|
|
||||||
|
|
||||||
await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options);
|
|
||||||
|
|
||||||
const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options);
|
|
||||||
|
|
||||||
expect(deletedTimeEntry).toBeNull();
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit the created time entry for the team boss as HHRR', async() => {
|
|
||||||
activeCtx.accessToken.userId = HHRRId;
|
|
||||||
const workerId = teamBossId;
|
|
||||||
|
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
|
|
||||||
const todayAtOne = Date.vnNew();
|
|
||||||
todayAtOne.setHours(1, 0, 0, 0);
|
|
||||||
|
|
||||||
ctx.args = {timed: todayAtOne, direction: 'in'};
|
|
||||||
const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
|
||||||
|
|
||||||
expect(createdTimeEntry.id).toBeDefined();
|
|
||||||
|
|
||||||
ctx.args = {direction: 'out'};
|
|
||||||
const updatedTimeEntry = await models.WorkerTimeControl.updateTimeEntry(ctx, createdTimeEntry.id, options);
|
|
||||||
|
|
||||||
expect(updatedTimeEntry.direction).toEqual('out');
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('WorkerTimeControl_clockIn calls', () => {
|
describe('WorkerTimeControl_clockIn calls', () => {
|
||||||
let workerId;
|
beforeEach(() => activeCtx.accessToken.userId = salesBossId);
|
||||||
beforeEach(() => {
|
|
||||||
activeCtx.accessToken.userId = salesBossId;
|
|
||||||
workerId = hankPymId;
|
|
||||||
});
|
|
||||||
it('should fail to add a time entry if the target user has an absence that day', async() => {
|
|
||||||
const date = Date.vnNew();
|
|
||||||
date.setHours(8, 0, 0);
|
|
||||||
date.setDate(date.getDate() - 16);
|
|
||||||
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() => {
|
|
||||||
const date = Date.vnNew();
|
|
||||||
date.setFullYear(date.getFullYear() - 2);
|
|
||||||
|
|
||||||
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 hay un contrato en vigor`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail to add a time entry for a worker without an existing contract', async() => {
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setDate(date.getDate() - 2);
|
|
||||||
let error;
|
|
||||||
|
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
|
||||||
const options = {transaction: tx};
|
|
||||||
date.setHours(0, 0, 0);
|
|
||||||
ctx.args = {timed: date, direction: 'in'};
|
|
||||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
|
||||||
|
|
||||||
try {
|
|
||||||
date.setHours(20,0, 1);
|
|
||||||
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(`Superado el tiempo máximo entre entrada y salida`);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('direction errors', () => {
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setDate(date.getDate() - 1);
|
|
||||||
let error;
|
|
||||||
it('should throw an error when trying "in" direction twice', async() => {
|
|
||||||
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() => {
|
|
||||||
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() => {
|
|
||||||
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() => {
|
|
||||||
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() => {
|
|
||||||
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', () => {
|
|
||||||
activeCtx.accessToken.userId = salesBossId;
|
|
||||||
const workerId = hankPymId;
|
|
||||||
it('should throw an error when the 12h rest is not fulfilled yet', async() => {
|
|
||||||
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setDate(date.getDate() - 2);
|
|
||||||
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`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not fail as the 12h rest is fulfilled', async() => {
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setDate(date.getDate() - 2);
|
|
||||||
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', () => {
|
|
||||||
activeCtx.accessToken.userId = salesBossId;
|
|
||||||
const workerId = jessicaJonesId;
|
|
||||||
it('should throw an error when the 9h enforced rest is not fulfilled', async() => {
|
|
||||||
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setDate(date.getDate() - 2);
|
|
||||||
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`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not fail when the 9h enforced rest is fulfilled', async() => {
|
|
||||||
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setDate(date.getDate() - 2);
|
|
||||||
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 72h weekly rest', () => {
|
|
||||||
|
|
||||||
it('should throw an error when work 11 consecutive days', async() => {
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setMonth(date.getMonth() - 1);
|
|
||||||
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, friday);
|
|
||||||
date.setHours(10, 0, 1);
|
|
||||||
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`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error when the 72h weekly rest is not fulfilled', async() => {
|
|
||||||
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setMonth(date.getMonth() - 1);
|
|
||||||
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, sunday);
|
|
||||||
date.setHours(17, 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`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error when the 72h weekly rest is fulfilled', async() => {
|
|
||||||
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setMonth(date.getMonth() - 1);
|
|
||||||
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, sunday);
|
|
||||||
date.setHours(18, 00, 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('WorkerTimeControl_calculate calls', () => {
|
describe('WorkerTimeControl_calculate calls', () => {
|
||||||
let dated = Date.vnNew();
|
let dated = Date.vnNew();
|
||||||
|
@ -836,25 +279,6 @@ function weekDay(date, dayToSet) {
|
||||||
return date;
|
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) {
|
async function populateWeek(date, dayStart, dayEnd, ctx, workerId, options) {
|
||||||
const dateStart = new Date(weekDay(date, dayStart));
|
const dateStart = new Date(weekDay(date, dayStart));
|
||||||
const dateEnd = new Date(dateStart);
|
const dateEnd = new Date(dateStart);
|
||||||
|
|
Loading…
Reference in New Issue