diff --git a/CHANGELOG.md b/CHANGELOG.md index dfdc563fb4..1907f46bd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2352.01] - 2023-12-28 +## [2402.01] - 2024-01-11 + +### Added +### Changed +### Fixed + +## [2400.01] - 2024-01-04 ### Added ### Changed @@ -13,9 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2350.01] - 2023-12-14 -### Added -### Changed -### Fixed +### Características Añadidas 🆕 +- **Tickets → Expediciones:** Añadido soporte para Viaexpress ## [2348.01] - 2023-11-30 diff --git a/back/methods/vn-user/renew-token.js b/back/methods/vn-user/renew-token.js index 9850267d6b..194747949b 100644 --- a/back/methods/vn-user/renew-token.js +++ b/back/methods/vn-user/renew-token.js @@ -1,5 +1,14 @@ const UserError = require('vn-loopback/util/user-error'); +const {models} = require('vn-loopback/server/server'); +const handlePromiseLogout = (Self, {id}, courtesyTime) => { + new Promise(res => { + setTimeout(() => { + res(Self.logout(id)); + } + , courtesyTime * 1000); + }); +}; module.exports = Self => { Self.remoteMethodCtx('renewToken', { description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it', @@ -16,23 +25,32 @@ module.exports = Self => { }); Self.renewToken = async function(ctx) { - const models = Self.app.models; - const token = ctx.req.accessToken; + const {accessToken: token} = ctx.req; - const now = new Date(); - const differenceMilliseconds = now - token.created; - const differenceSeconds = Math.floor(differenceMilliseconds / 1000); + // Check if current token is valid + const isValid = await validateToken(token); + if (isValid) + return token; - const fields = ['renewPeriod', 'courtesyTime']; - const accessTokenConfig = await models.AccessTokenConfig.findOne({fields}); + const {courtesyTime} = await models.AccessTokenConfig.findOne({fields: ['courtesyTime']}); - if (differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime) - throw new UserError(`The renew period has not been exceeded`, 'periodNotExceeded'); + // Schedule to remove current token + handlePromiseLogout(Self, token, courtesyTime); - await Self.logout(token.id); + // Create new accessToken const user = await Self.findById(token.userId); const accessToken = await user.createAccessToken(); return {id: accessToken.id, ttl: accessToken.ttl}; }; + + async function validateToken(token) { + const accessTokenConfig = await models.AccessTokenConfig.findOne({fields: ['renewPeriod', 'courtesyTime']}); + const now = Date.now(); + const differenceMilliseconds = now - token.created; + const differenceSeconds = Math.floor(differenceMilliseconds / 1000); + const isValid = differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime; + + return isValid; + } }; diff --git a/back/methods/vn-user/specs/renew-token.spec.js b/back/methods/vn-user/specs/renew-token.spec.js new file mode 100644 index 0000000000..674ce36f40 --- /dev/null +++ b/back/methods/vn-user/specs/renew-token.spec.js @@ -0,0 +1,49 @@ +const {models} = require('vn-loopback/server/server'); +describe('Renew Token', () => { + const startingTime = Date.now(); + let ctx = null; + beforeAll(async() => { + const unAuthCtx = { + req: { + headers: {}, + connection: { + remoteAddress: '127.0.0.1' + }, + getLocale: () => 'en' + }, + args: {} + }; + let login = await models.VnUser.signIn(unAuthCtx, 'salesAssistant', 'nightmare'); + let accessToken = await models.AccessToken.findById(login.token); + ctx = {req: {accessToken: accessToken}}; + }); + + beforeEach(() => { + jasmine.clock().install(); + jasmine.clock().mockDate(new Date(startingTime)); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + it('should renew process', async() => { + jasmine.clock().mockDate(new Date(startingTime + 21600000)); + const {id} = await models.VnUser.renewToken(ctx); + + expect(id).not.toEqual(ctx.req.accessToken.id); + }); + + it('NOT should renew', async() => { + let error; + let response; + try { + response = await models.VnUser.renewToken(ctx); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + expect(response.id).toEqual(ctx.req.accessToken.id); + }); +}); diff --git a/back/methods/vn-user/validate-token.js b/back/methods/vn-user/validate-token.js deleted file mode 100644 index 7bccfe0b1d..0000000000 --- a/back/methods/vn-user/validate-token.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = Self => { - Self.remoteMethod('validateToken', { - description: 'Validates the current logged user token', - returns: { - type: 'Boolean', - root: true - }, - http: { - path: `/validateToken`, - verb: 'GET' - } - }); - - Self.validateToken = async function() { - return true; - }; -}; diff --git a/back/models/vn-user.js b/back/models/vn-user.js index e14cd30eac..80287de5b0 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -10,7 +10,6 @@ module.exports = function(Self) { require('../methods/vn-user/sign-in')(Self); require('../methods/vn-user/acl')(Self); require('../methods/vn-user/recover-password')(Self); - require('../methods/vn-user/validate-token')(Self); require('../methods/vn-user/privileges')(Self); require('../methods/vn-user/validate-auth')(Self); require('../methods/vn-user/renew-token')(Self); diff --git a/back/models/vn-user.json b/back/models/vn-user.json index 0f6daff5ac..86ffac2bbc 100644 --- a/back/models/vn-user.json +++ b/back/models/vn-user.json @@ -104,13 +104,6 @@ "permission": "ALLOW" }, { - "property": "validateToken", - "accessType": "EXECUTE", - "principalType": "ROLE", - "principalId": "$authenticated", - "permission": "ALLOW" - }, - { "property": "validateAuth", "accessType": "EXECUTE", "principalType": "ROLE", diff --git a/db/changes/234601/00-updateCourtesyTime.sql b/db/changes/234601/00-updateCourtesyTime.sql new file mode 100644 index 0000000000..4751b2e032 --- /dev/null +++ b/db/changes/234601/00-updateCourtesyTime.sql @@ -0,0 +1,4 @@ +-- Auto-generated SQL script #202311061003 +UPDATE salix.accessTokenConfig + SET courtesyTime=60 + WHERE id=1; diff --git a/db/changes/235201/00-alterTable.sql b/db/changes/240001/00-alterTable.sql similarity index 100% rename from db/changes/235201/00-alterTable.sql rename to db/changes/240001/00-alterTable.sql diff --git a/db/changes/235201/00-clientCreditLimitToRoleCreditLimit.sql b/db/changes/240001/00-clientCreditLimitToRoleCreditLimit.sql similarity index 74% rename from db/changes/235201/00-clientCreditLimitToRoleCreditLimit.sql rename to db/changes/240001/00-clientCreditLimitToRoleCreditLimit.sql index bf4cc60029..2bc0f830dd 100644 --- a/db/changes/235201/00-clientCreditLimitToRoleCreditLimit.sql +++ b/db/changes/240001/00-clientCreditLimitToRoleCreditLimit.sql @@ -1,4 +1,4 @@ RENAME TABLE `vn`.`clientCreditLimit` TO `vn`.`roleCreditLimit`; -ALTER TABLE `vn`.`clientCreditLimit` DROP FOREIGN KEY `clientCreditLimit_FK`; +ALTER TABLE `vn`.`roleCreditLimit` DROP FOREIGN KEY `clientCreditLimit_FK`; ALTER TABLE `vn`.`roleCreditLimit` ADD CONSTRAINT `roleCreditLimit_FK` FOREIGN KEY (`roleFk`) REFERENCES `account`.`role`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/db/changes/235201/01-procedures.sql b/db/changes/240001/01-procedures.sql similarity index 100% rename from db/changes/235201/01-procedures.sql rename to db/changes/240001/01-procedures.sql diff --git a/db/changes/235201/02-views.sql b/db/changes/240001/02-views.sql similarity index 76% rename from db/changes/235201/02-views.sql rename to db/changes/240001/02-views.sql index a0f41594da..86a1049a79 100644 --- a/db/changes/235201/02-views.sql +++ b/db/changes/240001/02-views.sql @@ -1,9 +1,12 @@ +CREATE SCHEMA IF NOT EXISTS `vn2008`; +USE `vn`; + CREATE OR REPLACE DEFINER=`root`@`localhost` SQL SECURITY DEFINER - VIEW `vn`.`ticketState` + VIEW `ticketState` AS SELECT `tt`.`created` AS `updated`, `tt`.`stateFk` AS `stateFk`, - `tt`.`userFk` AS `userFk`, + `tt`.`userFk` AS `workerFk`, `tls`.`ticketFk` AS `ticketFk`, `s`.`id` AS `state`, `s`.`order` AS `productionOrder`, @@ -15,10 +18,10 @@ AS SELECT `tt`.`created` AS `updated`, `s`.`isPicked` AS `isPicked` FROM ( ( - `vn`.`ticketLastState` `tls` - JOIN `vn`.`ticketTracking` `tt` ON(`tt`.`id` = `tls`.`ticketTrackingFk`) + `ticketLastState` `tls` + JOIN `ticketTracking` `tt` ON(`tt`.`id` = `tls`.`ticketTrackingFk`) ) - JOIN `vn`.`state` `s` ON(`s`.`id` = `tt`.`stateFk`) + JOIN `state` `s` ON(`s`.`id` = `tt`.`stateFk`) ); CREATE OR REPLACE DEFINER=`root`@`localhost` @@ -33,14 +36,15 @@ AS SELECT `tt`.`id` AS `inter_id`, `tt`.`supervisorFk` AS `Id_supervisor` FROM `vn`.`ticketTracking` `tt`; -CREATE OR REPLACE -ALGORITHM = UNDEFINED VIEW `ticketStateToday` AS -SELECT +CREATE OR REPLACE DEFINER=`root`@`localhost` + SQL SECURITY DEFINER + VIEW `ticketStateToday` +AS SELECT `ts`.`ticket` AS `ticket`, `ts`.`state` AS `state`, `ts`.`productionOrder` AS `productionOrder`, `ts`.`alertLevel` AS `alertLevel`, - `ts`.`userFk` AS `userFk`, + `ts`.`worker` AS `worker`, `ts`.`code` AS `code`, `ts`.`updated` AS `updated`, `ts`.`isPicked` AS `isPicked` diff --git a/db/changes/235201/.gitkeep b/db/changes/240201/.gitkeep similarity index 100% rename from db/changes/235201/.gitkeep rename to db/changes/240201/.gitkeep diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 0424e89f62..d6cfe952ff 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2967,9 +2967,9 @@ INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`) (2, 1, 50, 2), (3, 1, 0, 3); -INSERT INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `renewInterval`) +INSERT INTO `salix`.`accessTokenConfig` (`id`, `renewPeriod`, `courtesyTime`, `renewInterval`) VALUES - (1, 21600, 300); + (1, 21600, 60, 300); INSERT INTO `vn`.`travelConfig` (`id`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `companyFk`) VALUES diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 1db4252f48..694f745efa 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -26391,6 +26391,7 @@ CREATE TABLE `cplusCorrectingType` ( ) ENGINE=InnoDBDEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `cplusRectificationType` -- diff --git a/front/core/services/token.js b/front/core/services/token.js index 426fe2b731..c8cb4f6bb6 100644 --- a/front/core/services/token.js +++ b/front/core/services/token.js @@ -82,7 +82,7 @@ export default class Token { if (!data) return; this.renewPeriod = data.renewPeriod; this.stopRenewer(); - this.inservalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000); + this.intervalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000); }); } @@ -103,17 +103,13 @@ export default class Token { const token = res.data; this.set(token.id, now, token.ttl, this.remember); }) - .catch(res => { - if (res.data?.error?.code !== 'periodNotExceeded') - throw res; - }) .finally(() => { this.checking = false; }); } stopRenewer() { - clearInterval(this.inservalId); + clearInterval(this.intervalId); } } Token.$inject = ['vnInterceptor', '$http', '$rootScope']; diff --git a/front/salix/locale/es.yml b/front/salix/locale/es.yml index 8ed58a4e4a..044d0d043b 100644 --- a/front/salix/locale/es.yml +++ b/front/salix/locale/es.yml @@ -18,7 +18,7 @@ Show summary: Mostrar vista previa What is new: Novedades de la versión Settings: Ajustes There is a new version, click here to reload: Hay una nueva versión, pulse aquí para recargar -This ticket is locked.: Este ticket está bloqueado +This ticket is locked: Este ticket está bloqueado # Actions diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 7d5b5ed47f..c5e8d4fcf4 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -183,7 +183,7 @@ "Social name should be uppercase": "Social name should be uppercase", "Street should be uppercase": "Street should be uppercase", "You don't have enough privileges.": "You don't have enough privileges.", - "This ticket is locked.": "This ticket is locked.", + "This ticket is locked": "This ticket is locked", "This ticket is not editable.": "This ticket is not editable.", "The ticket doesn't exist.": "The ticket doesn't exist.", "The sales do not exists": "The sales do not exists", @@ -201,4 +201,4 @@ "keepPrice": "keepPrice", "Cannot past travels with entries": "Cannot past travels with entries", "It was not able to remove the next expeditions:": "It was not able to remove the next expeditions: {{expeditions}}" -} \ No newline at end of file +} diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 01384efb42..a8134909e8 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -312,7 +312,7 @@ "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado", "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado", "You don't have enough privileges.": "No tienes suficientes permisos.", - "This ticket is locked.": "Este ticket está bloqueado.", + "This ticket is locked": "Este ticket está bloqueado.", "This ticket is not editable.": "Este ticket no es editable.", "The ticket doesn't exist.": "No existe el ticket.", "Social name should be uppercase": "La razón social debe ir en mayúscula", @@ -330,4 +330,4 @@ "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima", "Cannot past travels with entries": "No se pueden pasar envíos con entradas", "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}" -} \ No newline at end of file +} diff --git a/loopback/server/boot/date.js b/loopback/server/boot/date.js index 8107455625..d592dc416b 100644 --- a/loopback/server/boot/date.js +++ b/loopback/server/boot/date.js @@ -1,6 +1,5 @@ module.exports = () => { - Date.vnUTC = () => { - const env = process.env.NODE_ENV; + Date.vnUTC = (env = process.env.NODE_ENV) => { if (!env || env === 'development') return new Date(Date.UTC(2001, 0, 1, 11)); diff --git a/loopback/server/middleware.json b/loopback/server/middleware.json index 31a2f113b5..cfc6932175 100644 --- a/loopback/server/middleware.json +++ b/loopback/server/middleware.json @@ -39,7 +39,7 @@ "./middleware/salix-version": {} }, "parse": { - "body-parser#json":{} + "body-parser#json":{} }, "routes": { "loopback#rest": { diff --git a/modules/account/back/methods/account/specs/change-password.spec.js b/modules/account/back/methods/account/specs/change-password.spec.js index 2fa3010afb..c799602128 100644 --- a/modules/account/back/methods/account/specs/change-password.spec.js +++ b/modules/account/back/methods/account/specs/change-password.spec.js @@ -2,7 +2,7 @@ const {models} = require('vn-loopback/server/server'); describe('account changePassword()', () => { const userId = 70; - const unauthCtx = { + const unAuthCtx = { req: { headers: {}, connection: { @@ -79,7 +79,7 @@ describe('account changePassword()', () => { passExpired: yesterday } , options); - await models.VnUser.signIn(unauthCtx, 'trainee', 'nightmare', options); + await models.VnUser.signIn(unAuthCtx, 'trainee', 'nightmare', options); } catch (e) { if (e.message != 'Pass expired') throw e; diff --git a/modules/route/back/locale/route/en.yml b/modules/route/back/locale/route/en.yml index 96aaddb72e..d86cbe3422 100644 --- a/modules/route/back/locale/route/en.yml +++ b/modules/route/back/locale/route/en.yml @@ -17,3 +17,18 @@ columns: agencyModeFk: agency routeFk: route zoneFk: zone + name: name + beachFk: beach + ticketPacked: tickets packed + ticketFree: tickets free + ticketProduction: tickets production + packages: packages + note: note + dated: dated + dockFk: dock + priority: priority + etd: etd + expeditionTruckFk: truck + m3boxes: m3 boxes + bufferFk: buffer + isPickingAllowed: is picking allowed \ No newline at end of file diff --git a/modules/route/back/locale/route/es.yml b/modules/route/back/locale/route/es.yml index c0a4347917..baefb6433e 100644 --- a/modules/route/back/locale/route/es.yml +++ b/modules/route/back/locale/route/es.yml @@ -17,3 +17,18 @@ columns: agencyModeFk: agencia routeFk: ruta zoneFk: zona + name: nombre + beachFk: playa + ticketPacked: tickets encajados + ticketFree: tickets libres + ticketProduction: tickets producción + packages: paquetes + note: nota + dated: fecha + dockFk: muelle + priority: prioridad + etd: etd + expeditionTruckFk: camión + m3boxes: m3 cajas + bufferFk: buffer + isPickingAllowed: está permitido recoger \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/isEditableOrThrow.js b/modules/ticket/back/methods/ticket/isEditableOrThrow.js index f8285cecd8..41438be3a9 100644 --- a/modules/ticket/back/methods/ticket/isEditableOrThrow.js +++ b/modules/ticket/back/methods/ticket/isEditableOrThrow.js @@ -41,7 +41,7 @@ module.exports = Self => { throw new ForbiddenError(`This ticket is not editable.`); if (isLocked && !isWeekly) - throw new ForbiddenError(`This ticket is locked.`); + throw new ForbiddenError(`This ticket is locked`); if (isWeekly && !canEditWeeklyTicket) throw new ForbiddenError(`You don't have enough privileges.`); diff --git a/modules/ticket/back/methods/ticket/specs/addSale.spec.js b/modules/ticket/back/methods/ticket/specs/addSale.spec.js index 8c0e39becf..72c9541d90 100644 --- a/modules/ticket/back/methods/ticket/specs/addSale.spec.js +++ b/modules/ticket/back/methods/ticket/specs/addSale.spec.js @@ -89,6 +89,6 @@ describe('ticket addSale()', () => { error = e; } - expect(error.message).toEqual(`This ticket is locked.`); + expect(error.message).toEqual(`This ticket is locked`); }); }); diff --git a/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js index 6c89bac268..bdf5473251 100644 --- a/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js +++ b/modules/ticket/back/methods/ticket/specs/isEditableOrThrow.spec.js @@ -40,7 +40,7 @@ describe('ticket isEditableOrThrow()', () => { expect(error.message).toEqual(`This ticket is not editable.`); }); - it('should throw an error as this ticket is locked.', async() => { + it('should throw an error as This ticket is locked', async() => { const tx = await models.Ticket.beginTransaction({}); let error; try { @@ -57,7 +57,7 @@ describe('ticket isEditableOrThrow()', () => { await tx.rollback(); } - expect(error.message).toEqual(`This ticket is locked.`); + expect(error.message).toEqual(`This ticket is locked`); }); it('should throw an error as you do not have enough privileges.', async() => { diff --git a/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js b/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js index 383c2c6d51..d358a79f5b 100644 --- a/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js +++ b/modules/ticket/back/methods/ticket/specs/recalculateComponents.spec.js @@ -39,6 +39,6 @@ describe('ticket recalculateComponents()', () => { error = e; } - expect(error).toEqual(new ForbiddenError(`This ticket is locked.`)); + expect(error).toEqual(new ForbiddenError(`This ticket is locked`)); }); }); diff --git a/modules/ticket/back/methods/ticket/specs/transferClient.spec.js b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js index c09c20083d..5a9edd17e4 100644 --- a/modules/ticket/back/methods/ticket/specs/transferClient.spec.js +++ b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js @@ -23,7 +23,7 @@ describe('Ticket transferClient()', () => { error = e; } - expect(error.message).toEqual(`This ticket is locked.`); + expect(error.message).toEqual(`This ticket is locked`); }); it('should be assigned a different clientFk', async() => { diff --git a/modules/ticket/back/models/ticket-state.json b/modules/ticket/back/models/ticket-state.json index 3ee50fac06..3dd3229397 100644 --- a/modules/ticket/back/models/ticket-state.json +++ b/modules/ticket/back/models/ticket-state.json @@ -34,9 +34,9 @@ "foreignKey": "stateFk" }, "user": { - "type": "belongsTo", - "model": "VnUser", - "foreignKey": "userFk" - } + "type": "belongsTo", + "model": "VnUser", + "foreignKey": "workerFk" + } } } diff --git a/modules/ticket/back/models/ticket-tracking.json b/modules/ticket/back/models/ticket-tracking.json index 8b0617145c..4b5a4d4732 100644 --- a/modules/ticket/back/models/ticket-tracking.json +++ b/modules/ticket/back/models/ticket-tracking.json @@ -37,9 +37,9 @@ "foreignKey": "stateFk" }, "user": { - "type": "belongsTo", - "model": "VnUser", - "foreignKey": "userFk" - } + "type": "belongsTo", + "model": "VnUser", + "foreignKey": "userFk" + } } } diff --git a/package-lock.json b/package-lock.json index 78ef939870..012fb50e75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "salix-back", - "version": "23.50.01", + "version": "24.02.01", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "salix-back", - "version": "23.50.01", + "version": "24.02.01", "license": "GPL-3.0", "dependencies": { "axios": "^1.2.2", diff --git a/package.json b/package.json index 66a5cd2fa6..ab3d99e19f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.52.01", + "version": "24.02.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0",