Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3372-ticket_sale
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
c7e5c25a28
|
@ -0,0 +1,3 @@
|
||||||
|
UPDATE vn.absenceType
|
||||||
|
SET code='halfPaidLeave'
|
||||||
|
WHERE id=15 AND name='Permiso retribuido 1/2 día' AND rgb='#5151c0' AND code IS NULL AND permissionRate=NULL AND holidayEntitlementRate=0.50 AND discountRate=0.00;
|
|
@ -1878,6 +1878,7 @@ INSERT INTO `postgresql`.`calendar_state` (`calendar_state_id`, `type`, `rgb`, `
|
||||||
(1, 'Holidays', '#FF4444', 'holiday', 0),
|
(1, 'Holidays', '#FF4444', 'holiday', 0),
|
||||||
(2, 'Leave of absence', '#C71585', 'absence', 0),
|
(2, 'Leave of absence', '#C71585', 'absence', 0),
|
||||||
(6, 'Half holiday', '#E65F00', 'halfHoliday', 0),
|
(6, 'Half holiday', '#E65F00', 'halfHoliday', 0),
|
||||||
|
(15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0),
|
||||||
(20, 'Furlough', '#97B92F', 'furlough', 1),
|
(20, 'Furlough', '#97B92F', 'furlough', 1),
|
||||||
(21, 'Furlough half day', '#778899', 'halfFurlough', 0.5);
|
(21, 'Furlough half day', '#778899', 'halfFurlough', 0.5);
|
||||||
|
|
||||||
|
|
|
@ -214,5 +214,7 @@
|
||||||
"You can't change the credit set to zero from a manager": "No puedes cambiar el cŕedito establecido a cero por un gerente",
|
"You can't change the credit set to zero from a manager": "No puedes cambiar el cŕedito establecido a cero por un gerente",
|
||||||
"The PDF document does not exists": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'",
|
"The PDF document does not exists": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'",
|
||||||
"The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos",
|
"The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos",
|
||||||
"You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días"
|
"You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días",
|
||||||
|
"The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día",
|
||||||
|
"The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día"
|
||||||
}
|
}
|
|
@ -46,12 +46,29 @@ module.exports = Self => {
|
||||||
if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss))
|
if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss))
|
||||||
throw new UserError(`You don't have enough privileges`);
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
const timed = new Date(args.timed);
|
const minTime = new Date(args.timed);
|
||||||
|
minTime.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
query = `SELECT * FROM vn.workerLabour WHERE workerFk = ? AND (ended >= ? OR ended IS NULL);`;
|
||||||
|
const [workerLabour] = await Self.rawSql(query, [workerId, minTime]);
|
||||||
|
const absence = await models.Calendar.findOne({
|
||||||
|
where: {
|
||||||
|
businessFk: workerLabour.businessFk,
|
||||||
|
dated: minTime
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (absence) {
|
||||||
|
const absenceType = await models.AbsenceType.findById(absence.dayOffTypeFk, null, myOptions);
|
||||||
|
const isNotHalfAbsence = absenceType.code != 'halfHoliday'
|
||||||
|
&& absenceType.code != 'halfPaidLeave'
|
||||||
|
&& absenceType.code != 'halfFurlough';
|
||||||
|
if (isNotHalfAbsence)
|
||||||
|
throw new UserError(`The worker has a marked absence that day`);
|
||||||
|
}
|
||||||
return models.WorkerTimeControl.create({
|
return models.WorkerTimeControl.create({
|
||||||
userFk: workerId,
|
userFk: workerId,
|
||||||
direction: args.direction,
|
direction: args.direction,
|
||||||
timed: timed,
|
timed: args.timed,
|
||||||
manual: true
|
manual: true
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,6 +77,23 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fail to add a time entry if the target user has absent that day', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const workerId = salesPersonId;
|
||||||
|
let error;
|
||||||
|
|
||||||
|
let calendar = await app.models.Calendar.findById(3);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ctx.args = {timed: new Date(calendar.dated), direction: 'in'};
|
||||||
|
await models.WorkerTimeControl.addTimeEntry(ctx, workerId);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe(`The worker has a marked absence that day`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should try but fail to delete his own time entry', async() => {
|
it('should try but fail to delete his own time entry', async() => {
|
||||||
activeCtx.accessToken.userId = salesBossId;
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
const workerId = salesBossId;
|
const workerId = salesBossId;
|
||||||
|
|
|
@ -65,7 +65,22 @@ module.exports = Self => {
|
||||||
if (args.dated < labour.started || (labour.ended != null && args.dated > labour.ended))
|
if (args.dated < labour.started || (labour.ended != null && args.dated > labour.ended))
|
||||||
throw new UserError(`The contract was not active during the selected date`);
|
throw new UserError(`The contract was not active during the selected date`);
|
||||||
|
|
||||||
const result = await Self.rawSql(
|
query = `SELECT *
|
||||||
|
FROM vn.workerTimeControl
|
||||||
|
WHERE userFk = ? AND timed BETWEEN DATE(?) AND CONCAT(DATE(?), ' 23:59:59')
|
||||||
|
LIMIT 1;`;
|
||||||
|
const [hasHoursRecorded] = await Self.rawSql(query, [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 [result] = await Self.rawSql(
|
||||||
`SELECT COUNT(*) halfHolidayCounter
|
`SELECT COUNT(*) halfHolidayCounter
|
||||||
FROM vn.calendar c
|
FROM vn.calendar c
|
||||||
JOIN postgresql.business b ON b.business_id = c.businessFk
|
JOIN postgresql.business b ON b.business_id = c.businessFk
|
||||||
|
@ -74,10 +89,10 @@ module.exports = Self => {
|
||||||
WHERE c.dayOffTypeFk = 6
|
WHERE c.dayOffTypeFk = 6
|
||||||
AND pe.workerFk = ?
|
AND pe.workerFk = ?
|
||||||
AND c.dated BETWEEN util.firstDayOfYear(CURDATE())
|
AND c.dated BETWEEN util.firstDayOfYear(CURDATE())
|
||||||
AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 12-MONTH(NOW()) MONTH))`, [args.id]);
|
AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 12-MONTH(NOW()) MONTH))`, [id]);
|
||||||
|
|
||||||
const hasHalfHoliday = result[0].halfHolidayCounter > 0;
|
const hasHalfHoliday = result.halfHolidayCounter > 0;
|
||||||
const isHalfHoliday = args.absenceTypeId == 6;
|
const isHalfHoliday = absenceType.code === 'halfHoliday';
|
||||||
|
|
||||||
if (isHalfHoliday && hasHalfHoliday)
|
if (isHalfHoliday && hasHalfHoliday)
|
||||||
throw new UserError(`Cannot add more than one '1/2 day vacation'`);
|
throw new UserError(`Cannot add more than one '1/2 day vacation'`);
|
||||||
|
|
|
@ -77,7 +77,7 @@ describe('Worker createAbsence()', () => {
|
||||||
|
|
||||||
it(`should throw an error when adding a "Half holiday" absence if there's already one`, async() => {
|
it(`should throw an error when adding a "Half holiday" absence if there's already one`, async() => {
|
||||||
const ctx = {
|
const ctx = {
|
||||||
req: {accessToken: {userId: 19}},
|
req: {accessToken: {userId: 9}},
|
||||||
args: {
|
args: {
|
||||||
id: 1,
|
id: 1,
|
||||||
businessFk: 1,
|
businessFk: 1,
|
||||||
|
@ -85,6 +85,7 @@ describe('Worker createAbsence()', () => {
|
||||||
dated: new Date()
|
dated: new Date()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const workerId = 1;
|
||||||
|
|
||||||
const tx = await app.models.Calendar.beginTransaction({});
|
const tx = await app.models.Calendar.beginTransaction({});
|
||||||
|
|
||||||
|
@ -102,4 +103,33 @@ describe('Worker createAbsence()', () => {
|
||||||
|
|
||||||
expect(error.message).toEqual(`Cannot add more than one '1/2 day vacation'`);
|
expect(error.message).toEqual(`Cannot add more than one '1/2 day vacation'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`should throw an error when adding a absence if the worker has hours recorded that day and not is a half absence`, async() => {
|
||||||
|
const ctx = {
|
||||||
|
req: {accessToken: {userId: 19}},
|
||||||
|
args: {
|
||||||
|
id: 1106,
|
||||||
|
businessFk: 1106,
|
||||||
|
absenceTypeId: 1,
|
||||||
|
dated: new Date()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const workerId = 1106;
|
||||||
|
|
||||||
|
const tx = await app.models.Calendar.beginTransaction({});
|
||||||
|
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
await app.models.Worker.createAbsence(ctx, workerId, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toEqual(`The worker has hours recorded that day`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
},
|
},
|
||||||
|
"workerFk": {
|
||||||
|
"type": "Number"
|
||||||
|
},
|
||||||
"started": {
|
"started": {
|
||||||
"type": "date"
|
"type": "date"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue