Merge branch 'master' into test

This commit is contained in:
Guillermo Bonet 2025-01-09 11:34:41 +01:00
commit 1787cd3102
7 changed files with 95 additions and 15 deletions

View File

@ -22,7 +22,7 @@ module.exports = Self => {
description: 'The user email' description: 'The user email'
}, { }, {
arg: 'lang', arg: 'lang',
type: 'string', type: 'any',
description: 'The user lang' description: 'The user lang'
}, { }, {
arg: 'twoFactor', arg: 'twoFactor',

View File

@ -10,18 +10,26 @@ BEGIN
* @param vDateFrom Fecha desde * @param vDateFrom Fecha desde
* @param vDateTo Fecha hasta * @param vDateTo Fecha hasta
*/ */
IF vDateFrom IS NULL THEN DECLARE vDaysInYear INT;
SET vDateFrom = util.VN_CURDATE() - INTERVAL WEEKDAY(util.VN_CURDATE()) DAY; 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; END IF;
IF vDateTo IS NULL THEN -- Obtiene el primer día de la semana de esa fecha
SET vDateTo = vDateFrom + INTERVAL 6 DAY; SET vDateFrom = DATE_SUB(vDateFrom, INTERVAL ((WEEKDAY(vDateFrom) + 1) % 7) DAY);
END IF;
-- 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); CALL cache.last_buy_refresh(FALSE);
REPLACE bs.waste REPLACE bs.waste
SELECT YEAR(t.shipped), SELECT YEARWEEK(t.shipped, 6) DIV 100,
WEEK(t.shipped, 6), WEEK(t.shipped, 6),
it.workerFk, it.workerFk,
it.id, it.id,
@ -68,8 +76,8 @@ BEGIN
JOIN cache.last_buy lb ON lb.item_id = i.id JOIN cache.last_buy lb ON lb.item_id = i.id
AND lb.warehouse_id = w.id AND lb.warehouse_id = w.id
JOIN vn.buy b ON b.id = lb.buy_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 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$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -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');

View File

@ -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,

View File

@ -53,6 +53,10 @@ module.exports = Self => {
} }
} }
}, myOptions); }, myOptions);
if (!await Self.canModifyAbsenceInPast(ctx, absence.dated.getTime()))
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();

View File

@ -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');
});
}); });

View File

@ -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'],