fix: prevent deleting absences for past dates #3346
|
@ -0,0 +1,4 @@
|
||||||
|
DELETE FROM salix.ACL WHERE property = 'canCreateAbsenceInPast';
|
||||||
|
|
||||||
|
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||||
|
VALUES ('Worker','canModifyAbsenceInPast','WRITE','ALLOW','ROLE','hr');
|
|
@ -58,12 +58,10 @@ module.exports = Self => {
|
||||||
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
|
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
|
||||||
throw new UserError(`You don't have enough privileges`);
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
const canCreateAbsenceInPast =
|
|
||||||
await models.ACL.checkAccessAcl(ctx, 'Worker', 'canCreateAbsenceInPast', 'WRITE');
|
|
||||||
const now = Date.vnNew();
|
const now = Date.vnNew();
|
||||||
const newDate = new Date(args.dated).getTime();
|
const newDate = new Date(args.dated).getTime();
|
||||||
|
|
||||||
if ((now.getTime() > newDate) && !canCreateAbsenceInPast)
|
if (!await Self.canModifyAbsenceInPast(ctx, newDate))
|
||||||
throw new UserError(`Holidays to past days not available`);
|
throw new UserError(`Holidays to past days not available`);
|
||||||
|
|||||||
|
|
||||||
const labour = await models.WorkerLabour.findById(args.businessFk,
|
const labour = await models.WorkerLabour.findById(args.businessFk,
|
||||||
|
|
|
@ -53,6 +53,10 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
|
if (!await Self.canModifyAbsenceInPast(ctx, absence.dated.getTime()))
|
||||||
jorgep marked this conversation as resolved
Outdated
alexm
commented
En create ya esta codigo parecido Ver si unificar En create ya esta codigo parecido https://gitea.verdnatura.es/verdnatura/salix/src/commit/b14268ef1bfd0091526255e390255ad664f3839a/modules/worker/back/methods/worker/createAbsence.js#L63
Ver si unificar
|
|||||||
|
throw new UserError(`Holidays to past days not available`);
|
||||||
|
|
||||||
const result = await absence.destroy(myOptions);
|
const result = await absence.destroy(myOptions);
|
||||||
const labour = absence.labour();
|
const labour = absence.labour();
|
||||||
const department = labour && labour.department();
|
const department = labour && labour.department();
|
||||||
|
|
|
@ -4,6 +4,8 @@ const LoopBackContext = require('loopback-context');
|
||||||
describe('Worker deleteAbsence()', () => {
|
describe('Worker deleteAbsence()', () => {
|
||||||
const businessId = 18;
|
const businessId = 18;
|
||||||
const workerId = 18;
|
const workerId = 18;
|
||||||
|
const hrId = 37;
|
||||||
|
const salesBossId = 19;
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
accessToken: {userId: 1106},
|
accessToken: {userId: 1106},
|
||||||
headers: {origin: 'http://localhost'}
|
headers: {origin: 'http://localhost'}
|
||||||
|
@ -50,16 +52,16 @@ describe('Worker deleteAbsence()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should successfully delete an absence', async() => {
|
it('should successfully delete an absence', async() => {
|
||||||
activeCtx.accessToken.userId = 19;
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
|
||||||
const tx = await app.models.Calendar.beginTransaction({});
|
const tx = await app.models.Calendar.beginTransaction({});
|
||||||
|
const pastDate = new Date(Date.vnNow() + 24 * 60 * 60 * 1000);
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
const createdAbsence = await app.models.Calendar.create({
|
const createdAbsence = await app.models.Calendar.create({
|
||||||
businessFk: businessId,
|
businessFk: businessId,
|
||||||
dayOffTypeFk: 1,
|
dayOffTypeFk: 1,
|
||||||
dated: Date.vnNew()
|
dated: pastDate
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
ctx.args = {absenceId: createdAbsence.id};
|
ctx.args = {absenceId: createdAbsence.id};
|
||||||
|
@ -76,4 +78,61 @@ describe('Worker deleteAbsence()', () => {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should successfully delete an absence if the user is HR even if the date is in the past', async() => {
|
||||||
|
activeCtx.accessToken.userId = hrId;
|
||||||
|
const tx = await app.models.Calendar.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const pastDate = new Date(Date.vnNow() - 24 * 60 * 60 * 1000); // Restar un día
|
||||||
|
const createdAbsence = await app.models.Calendar.create({
|
||||||
|
businessFk: businessId,
|
||||||
|
dayOffTypeFk: 1,
|
||||||
|
dated: pastDate
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
ctx.args = {absenceId: createdAbsence.id};
|
||||||
|
await app.models.Worker.deleteAbsence(ctx, workerId, options);
|
||||||
|
|
||||||
|
const deletedAbsence = await app.models.Calendar.findById(createdAbsence.id, null, options);
|
||||||
|
|
||||||
|
expect(deletedAbsence).toBeNull();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the date is in the past', async() => {
|
||||||
|
activeCtx.accessToken.userId = salesBossId;
|
||||||
|
const tx = await app.models.Calendar.beginTransaction({});
|
||||||
|
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const pastDate = new Date(Date.vnNow() - 24 * 60 * 60 * 1000);
|
||||||
|
const createdAbsence = await app.models.Calendar.create({
|
||||||
|
businessFk: businessId,
|
||||||
|
dayOffTypeFk: 1,
|
||||||
|
dated: pastDate
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
ctx.args = {absenceId: createdAbsence.id};
|
||||||
|
await app.models.Worker.deleteAbsence(ctx, workerId, options);
|
||||||
|
|
||||||
|
const deletedAbsence = await app.models.Calendar.findById(createdAbsence.id, null, options);
|
||||||
|
|
||||||
|
expect(deletedAbsence).toBeNull();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toBe('Holidays to past days not available');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,6 +26,13 @@ module.exports = Self => {
|
||||||
message: 'Invalid TIN'
|
message: 'Invalid TIN'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Self.canModifyAbsenceInPast = async(ctx, time) => {
|
||||||
|
const hasPrivs = await Self.app.models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE');
|
||||||
|
const today = Date.vnNew();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
return hasPrivs || today.getTime() < time;
|
||||||
|
};
|
||||||
|
|
||||||
async function tinIsValid(err, done) {
|
async function tinIsValid(err, done) {
|
||||||
const country = await Self.app.models.Country.findOne({
|
const country = await Self.app.models.Country.findOne({
|
||||||
fields: ['code'],
|
fields: ['code'],
|
||||||
|
|
Loading…
Reference in New Issue
No acabo de ver el duplicar el UserError