From c07e30a89c691e11e2bace073b0c587e54d15d9d Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 8 Jan 2025 12:48:28 +0100 Subject: [PATCH 1/8] fix: prevent deleting absences for past dates --- db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql | 2 ++ modules/worker/back/methods/worker/deleteAbsence.js | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql diff --git a/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql b/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql new file mode 100644 index 000000000..8ab24cb0d --- /dev/null +++ b/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql @@ -0,0 +1,2 @@ +INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) + VALUES ('Worker','canDeleteAbsenceInPast','WRITE','ALLOW','ROLE','hr'); \ No newline at end of file diff --git a/modules/worker/back/methods/worker/deleteAbsence.js b/modules/worker/back/methods/worker/deleteAbsence.js index b71d077a4..a7c6efc21 100644 --- a/modules/worker/back/methods/worker/deleteAbsence.js +++ b/modules/worker/back/methods/worker/deleteAbsence.js @@ -53,6 +53,12 @@ module.exports = Self => { } } }, myOptions); + const canDeleteAbsenceInPast = + await models.ACL.checkAccessAcl(ctx, 'Worker', 'canDeleteAbsenceInPast', 'WRITE'); + + if (!canDeleteAbsenceInPast && Date.vnNow() > absence.dated.getTime()) + throw new UserError(`Holidays to past days not available`); + const result = await absence.destroy(myOptions); const labour = absence.labour(); const department = labour && labour.department(); From f557b41feb782d1f1eb9788ec3d8fd413f2d3284 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 8 Jan 2025 13:52:50 +0100 Subject: [PATCH 2/8] fix: tests --- .../worker/specs/deleteAbsence.spec.js | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index 0f3f913dc..c0d05e4a2 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -4,6 +4,8 @@ const LoopBackContext = require('loopback-context'); describe('Worker deleteAbsence()', () => { const businessId = 18; const workerId = 18; + const hrId = 37; + const salesBossId = 19; const activeCtx = { accessToken: {userId: 1106}, headers: {origin: 'http://localhost'} @@ -50,16 +52,16 @@ describe('Worker deleteAbsence()', () => { }); it('should successfully delete an absence', async() => { - activeCtx.accessToken.userId = 19; + activeCtx.accessToken.userId = salesBossId; const tx = await app.models.Calendar.beginTransaction({}); - + const pastDate = new Date(Date.vnNow() + 24 * 60 * 60 * 1000); try { const options = {transaction: tx}; const createdAbsence = await app.models.Calendar.create({ businessFk: businessId, dayOffTypeFk: 1, - dated: Date.vnNew() + dated: pastDate }, options); ctx.args = {absenceId: createdAbsence.id}; @@ -76,4 +78,61 @@ describe('Worker deleteAbsence()', () => { 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'); + }); }); From 838617e3f667fdb9ad14d454cdaa1854eca7d6d5 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 8 Jan 2025 15:47:53 +0100 Subject: [PATCH 3/8] fix: update access control for modifying absences in the past --- db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql | 4 +++- modules/worker/back/methods/worker/createAbsence.js | 6 +++--- modules/worker/back/methods/worker/deleteAbsence.js | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql b/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql index 8ab24cb0d..f3e0355a8 100644 --- a/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql +++ b/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql @@ -1,2 +1,4 @@ +DELETE FROM salix.ACL WHERE property = 'canCreateAbsenceInPast'; + INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) - VALUES ('Worker','canDeleteAbsenceInPast','WRITE','ALLOW','ROLE','hr'); \ No newline at end of file + VALUES ('Worker','canModifyAbsenceInPast','WRITE','ALLOW','ROLE','hr'); diff --git a/modules/worker/back/methods/worker/createAbsence.js b/modules/worker/back/methods/worker/createAbsence.js index 93ca7fd89..36781bc3f 100644 --- a/modules/worker/back/methods/worker/createAbsence.js +++ b/modules/worker/back/methods/worker/createAbsence.js @@ -58,12 +58,12 @@ module.exports = Self => { 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 canModifyAbsenceInPast = + await models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE'); const now = Date.vnNew(); const newDate = new Date(args.dated).getTime(); - if ((now.getTime() > newDate) && !canCreateAbsenceInPast) + if ((now.getTime() > newDate) && !canModifyAbsenceInPast) throw new UserError(`Holidays to past days not available`); const labour = await models.WorkerLabour.findById(args.businessFk, diff --git a/modules/worker/back/methods/worker/deleteAbsence.js b/modules/worker/back/methods/worker/deleteAbsence.js index a7c6efc21..11a8cb0c1 100644 --- a/modules/worker/back/methods/worker/deleteAbsence.js +++ b/modules/worker/back/methods/worker/deleteAbsence.js @@ -53,10 +53,10 @@ module.exports = Self => { } } }, myOptions); - const canDeleteAbsenceInPast = - await models.ACL.checkAccessAcl(ctx, 'Worker', 'canDeleteAbsenceInPast', 'WRITE'); + const canModifyAbsenceInPast = + await models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE'); - if (!canDeleteAbsenceInPast && Date.vnNow() > absence.dated.getTime()) + if (!canModifyAbsenceInPast && Date.vnNow() > absence.dated.getTime()) throw new UserError(`Holidays to past days not available`); const result = await absence.destroy(myOptions); From 412638d59000f04fbe10aa45c4429230e57f1a41 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 8 Jan 2025 18:27:23 +0100 Subject: [PATCH 4/8] fix: refactor access control for modifying past absences --- modules/worker/back/methods/worker/createAbsence.js | 4 +--- modules/worker/back/methods/worker/deleteAbsence.js | 4 +--- .../worker/back/methods/worker/specs/createAbsence.spec.js | 2 +- .../worker/back/methods/worker/specs/deleteAbsence.spec.js | 2 +- modules/worker/back/models/worker.js | 7 +++++++ 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/worker/back/methods/worker/createAbsence.js b/modules/worker/back/methods/worker/createAbsence.js index 36781bc3f..dc716c95d 100644 --- a/modules/worker/back/methods/worker/createAbsence.js +++ b/modules/worker/back/methods/worker/createAbsence.js @@ -58,12 +58,10 @@ module.exports = Self => { if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - const canModifyAbsenceInPast = - await models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE'); const now = Date.vnNew(); const newDate = new Date(args.dated).getTime(); - if ((now.getTime() > newDate) && !canModifyAbsenceInPast) + if (!await Self.canModifyAbsenceInPast(ctx, newDate)) throw new UserError(`Holidays to past days not available`); const labour = await models.WorkerLabour.findById(args.businessFk, diff --git a/modules/worker/back/methods/worker/deleteAbsence.js b/modules/worker/back/methods/worker/deleteAbsence.js index 11a8cb0c1..596f8f28d 100644 --- a/modules/worker/back/methods/worker/deleteAbsence.js +++ b/modules/worker/back/methods/worker/deleteAbsence.js @@ -53,10 +53,8 @@ module.exports = Self => { } } }, myOptions); - const canModifyAbsenceInPast = - await models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE'); - if (!canModifyAbsenceInPast && Date.vnNow() > absence.dated.getTime()) + if (!await Self.canModifyAbsenceInPast(ctx, absence.dated.getTime())) throw new UserError(`Holidays to past days not available`); const result = await absence.destroy(myOptions); diff --git a/modules/worker/back/methods/worker/specs/createAbsence.spec.js b/modules/worker/back/methods/worker/specs/createAbsence.spec.js index 1c7efcd28..b6600048f 100644 --- a/modules/worker/back/methods/worker/specs/createAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/createAbsence.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const LoopBackContext = require('loopback-context'); -describe('Worker createAbsence()', () => { +fdescribe('Worker createAbsence()', () => { const workerId = 18; it('should return an error for a user without enough privileges', async() => { diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index c0d05e4a2..dfbcd9835 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const LoopBackContext = require('loopback-context'); -describe('Worker deleteAbsence()', () => { +fdescribe('Worker deleteAbsence()', () => { const businessId = 18; const workerId = 18; const hrId = 37; diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index 3351c348c..e1adca77e 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -26,6 +26,13 @@ module.exports = Self => { message: 'Invalid TIN' }); + Self.canModifyAbsenceInPast = async(ctx, time) => { + const hasPrivs = await Self.app.models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE'); + const now = Date.vnNew(); + now.setHours(0, 0, 0, 0); + return hasPrivs || now.getTime() < time; + }; + async function tinIsValid(err, done) { const country = await Self.app.models.Country.findOne({ fields: ['code'], From b12c3bb72f8d182983bfd89d64c55237bf20f834 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 8 Jan 2025 18:28:00 +0100 Subject: [PATCH 5/8] fix: enable tests for createAbsence and deleteAbsence methods --- modules/worker/back/methods/worker/specs/createAbsence.spec.js | 2 +- modules/worker/back/methods/worker/specs/deleteAbsence.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/worker/back/methods/worker/specs/createAbsence.spec.js b/modules/worker/back/methods/worker/specs/createAbsence.spec.js index b6600048f..1c7efcd28 100644 --- a/modules/worker/back/methods/worker/specs/createAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/createAbsence.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const LoopBackContext = require('loopback-context'); -fdescribe('Worker createAbsence()', () => { +describe('Worker createAbsence()', () => { const workerId = 18; it('should return an error for a user without enough privileges', async() => { diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index dfbcd9835..c0d05e4a2 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const LoopBackContext = require('loopback-context'); -fdescribe('Worker deleteAbsence()', () => { +describe('Worker deleteAbsence()', () => { const businessId = 18; const workerId = 18; const hrId = 37; From 50a95ed3c4bdb1396d1d1c1ad12b81ed301e1561 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 8 Jan 2025 18:30:33 +0100 Subject: [PATCH 6/8] fix: correct variable name in canModifyAbsenceInPast method --- modules/worker/back/models/worker.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index e1adca77e..2e45b78da 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -28,9 +28,9 @@ module.exports = Self => { Self.canModifyAbsenceInPast = async(ctx, time) => { const hasPrivs = await Self.app.models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE'); - const now = Date.vnNew(); - now.setHours(0, 0, 0, 0); - return hasPrivs || now.getTime() < time; + const today = Date.vnNew(); + today.setHours(0, 0, 0, 0); + return hasPrivs || today.getTime() < time; }; async function tinIsValid(err, done) { From d258de1194deb54a730a39d59484e0aa83dac77b Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 9 Jan 2025 07:58:59 +0100 Subject: [PATCH 7/8] fix: lang any --- back/methods/vn-user/update-user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/vn-user/update-user.js b/back/methods/vn-user/update-user.js index 2bb390cf9..32bad0f17 100644 --- a/back/methods/vn-user/update-user.js +++ b/back/methods/vn-user/update-user.js @@ -22,7 +22,7 @@ module.exports = Self => { description: 'The user email' }, { arg: 'lang', - type: 'string', + type: 'any', description: 'The user lang' }, { arg: 'twoFactor', From 2141d7d95dc6273e2cc44b12629686b69cd959b8 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 9 Jan 2025 11:29:07 +0100 Subject: [PATCH 8/8] fix: refs #7912 Major corrections waste_addSales --- db/routines/bs/procedures/waste_addSales.sql | 24 +++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/db/routines/bs/procedures/waste_addSales.sql b/db/routines/bs/procedures/waste_addSales.sql index 9ce67b19d..4a34d74b3 100644 --- a/db/routines/bs/procedures/waste_addSales.sql +++ b/db/routines/bs/procedures/waste_addSales.sql @@ -10,18 +10,26 @@ BEGIN * @param vDateFrom Fecha desde * @param vDateTo Fecha hasta */ - IF vDateFrom IS NULL THEN - SET vDateFrom = util.VN_CURDATE() - INTERVAL WEEKDAY(util.VN_CURDATE()) DAY; + DECLARE vDaysInYear INT; + SET vDaysInYear = DATEDIFF(util.lastDayOfYear(CURDATE()), util.firstDayOfYear(CURDATE())); + + SET vDateFrom = COALESCE(vDateFrom, util.VN_CURDATE()); + SET vDateTo = COALESCE(vDateTo, util.VN_CURDATE()); + + IF DATEDIFF(vDateTo, vDateFrom) > vDaysInYear THEN + CALL util.throw('The period cannot be longer than one year'); END IF; - IF vDateTo IS NULL THEN - SET vDateTo = vDateFrom + INTERVAL 6 DAY; - END IF; + -- Obtiene el primer día de la semana de esa fecha + SET vDateFrom = DATE_SUB(vDateFrom, INTERVAL ((WEEKDAY(vDateFrom) + 1) % 7) DAY); + + -- Obtiene el último día de la semana de esa fecha + SET vDateTo = DATE_ADD(vDateTo, INTERVAL (6 - ((WEEKDAY(vDateTo) + 1) % 7)) DAY); CALL cache.last_buy_refresh(FALSE); REPLACE bs.waste - SELECT YEAR(t.shipped), + SELECT YEARWEEK(t.shipped, 6) DIV 100, WEEK(t.shipped, 6), it.workerFk, it.id, @@ -68,8 +76,8 @@ BEGIN JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = w.id JOIN vn.buy b ON b.id = lb.buy_id - WHERE t.shipped BETWEEN vDateFrom AND vDateTo + WHERE t.shipped BETWEEN vDateFrom AND util.dayEnd(vDateTo) AND w.isManaged - GROUP BY YEAR(t.shipped), WEEK(t.shipped, 6), i.id; + GROUP BY YEARWEEK(t.shipped, 6) DIV 100, WEEK(t.shipped, 6), i.id; END$$ DELIMITER ;