From 5dbfe31a60d129f2d076c548096f5e653050b218 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Fri, 10 Nov 2023 15:12:03 +0100 Subject: [PATCH 01/87] refs #5666 feat: define VnRole --- .vscode/settings.json | 6 ++++++ back/model-config.json | 3 +++ back/models/vn-role.json | 13 +++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 back/models/vn-role.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 05d23f3bb..4c2761987 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,11 @@ "eslint.format.enable": true, "[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "cSpell.words": [ + "Loggable" + ], + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features" } } diff --git a/back/model-config.json b/back/model-config.json index ebc0e321b..84dd9eebd 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -142,6 +142,9 @@ "VnUser": { "dataSource": "vn" }, + "VnRole": { + "dataSource": "vn" + }, "OsTicket": { "dataSource": "osticket" }, diff --git a/back/models/vn-role.json b/back/models/vn-role.json new file mode 100644 index 000000000..e841f8a88 --- /dev/null +++ b/back/models/vn-role.json @@ -0,0 +1,13 @@ +{ + "name": "VnRole", + "base": "Role", + "validateUpsert": true, + "options": { + "mysql": { + "table": "account.role" + } + }, + "mixins": { + "RegisterLog": true + } +} From cf3cc37d97f61372dd9072492b60ffce5ad35cfd Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Fri, 10 Nov 2023 15:12:24 +0100 Subject: [PATCH 02/87] refs #5666 feat: create mixin --- back/mixins/register-log.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 back/mixins/register-log.js diff --git a/back/mixins/register-log.js b/back/mixins/register-log.js new file mode 100644 index 000000000..555191e57 --- /dev/null +++ b/back/mixins/register-log.js @@ -0,0 +1,20 @@ + +const loggable = require('vn-loopback/util/log'); + +module.exports = function(Self, options) { + Self.once('attached', function(ctx) { + }); + + Self.observe('before save', async function(ctx, next) { + await loggable.translateValues(Self, ctx.currentInstance); + }); + + let Mixin = { + + }; + + for (let method in Mixin) { + if (!Self.prototype[method]) + Self.prototype[method] = Mixin[method]; + } +}; From 3c5af184bbc6458ca3963b7a561b187577a1509f Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Fri, 10 Nov 2023 15:12:49 +0100 Subject: [PATCH 03/87] refs #5666 feat: use mixin for this models --- back/models/vn-user.json | 3 +++ modules/account/back/models/account.json | 3 +++ 2 files changed, 6 insertions(+) diff --git a/back/models/vn-user.json b/back/models/vn-user.json index 0f6daff5a..28fca8fe8 100644 --- a/back/models/vn-user.json +++ b/back/models/vn-user.json @@ -7,6 +7,9 @@ "table": "account.user" } }, + "mixins": { + "RegisterLog": true + }, "resetPasswordTokenTTL": "604800", "properties": { "id": { diff --git a/modules/account/back/models/account.json b/modules/account/back/models/account.json index 3c22521cb..3c76c85c3 100644 --- a/modules/account/back/models/account.json +++ b/modules/account/back/models/account.json @@ -6,6 +6,9 @@ "table": "account.account" } }, + "mixins": { + "RegisterLog": true + }, "properties": { "id": { "id": true From a102c3f3a952da468734039c1e133e4470270842 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Mon, 13 Nov 2023 09:53:35 +0100 Subject: [PATCH 04/87] refs #5666 perf: loggable to mixin --- loopback/common/mixins/loggable.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 loopback/common/mixins/loggable.js diff --git a/loopback/common/mixins/loggable.js b/loopback/common/mixins/loggable.js new file mode 100644 index 000000000..760fdf60a --- /dev/null +++ b/loopback/common/mixins/loggable.js @@ -0,0 +1,12 @@ +const LoopBackContext = require('loopback-context'); +async function handleObserve(ctx) { + ctx.options.httpCtx = LoopBackContext.getCurrentContext(); +} +module.exports = function(Self) { + let Mixin = { + 'before save': handleObserve, + 'before delete': handleObserve, + }; + for (const [listener, handler] of Object.entries(Mixin)) + Self.observe(listener, handler); +}; From aab88dc7dede9b31d733b5ff647224fc3b93d3f4 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Mon, 13 Nov 2023 09:54:12 +0100 Subject: [PATCH 05/87] refs #5666 perf: use use loggable as mixin --- back/models/vn-role.json | 2 +- back/models/vn-user.json | 2 +- loopback/common/models/loggable.json | 13 ++++++++----- modules/account/back/models/account.json | 5 +---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/back/models/vn-role.json b/back/models/vn-role.json index e841f8a88..c7d7e172b 100644 --- a/back/models/vn-role.json +++ b/back/models/vn-role.json @@ -8,6 +8,6 @@ } }, "mixins": { - "RegisterLog": true + "Loggable": true } } diff --git a/back/models/vn-user.json b/back/models/vn-user.json index 28fca8fe8..bda0a6ec3 100644 --- a/back/models/vn-user.json +++ b/back/models/vn-user.json @@ -8,7 +8,7 @@ } }, "mixins": { - "RegisterLog": true + "Loggable": true }, "resetPasswordTokenTTL": "604800", "properties": { diff --git a/loopback/common/models/loggable.json b/loopback/common/models/loggable.json index 9101532a3..62822d0af 100644 --- a/loopback/common/models/loggable.json +++ b/loopback/common/models/loggable.json @@ -1,5 +1,8 @@ -{ - "name": "Loggable", - "base": "VnModel", - "validateUpsert": true -} +{ + "name": "Loggable", + "base": "VnModel", + "validateUpsert": true, + "mixins": { + "Loggable": true + } +} diff --git a/modules/account/back/models/account.json b/modules/account/back/models/account.json index 3c76c85c3..3e4371604 100644 --- a/modules/account/back/models/account.json +++ b/modules/account/back/models/account.json @@ -6,10 +6,7 @@ "table": "account.account" } }, - "mixins": { - "RegisterLog": true - }, - "properties": { + "properties": { "id": { "id": true } From 384b5eb7c7705cc1603bebaa67d09d58afbe4c91 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Mon, 13 Nov 2023 09:56:16 +0100 Subject: [PATCH 06/87] refs #5666 remove old file --- back/mixins/register-log.js | 20 ------ modules/account/back/models/account.json | 86 ++++++++++++------------ 2 files changed, 43 insertions(+), 63 deletions(-) delete mode 100644 back/mixins/register-log.js diff --git a/back/mixins/register-log.js b/back/mixins/register-log.js deleted file mode 100644 index 555191e57..000000000 --- a/back/mixins/register-log.js +++ /dev/null @@ -1,20 +0,0 @@ - -const loggable = require('vn-loopback/util/log'); - -module.exports = function(Self, options) { - Self.once('attached', function(ctx) { - }); - - Self.observe('before save', async function(ctx, next) { - await loggable.translateValues(Self, ctx.currentInstance); - }); - - let Mixin = { - - }; - - for (let method in Mixin) { - if (!Self.prototype[method]) - Self.prototype[method] = Mixin[method]; - } -}; diff --git a/modules/account/back/models/account.json b/modules/account/back/models/account.json index 3e4371604..6c2784696 100644 --- a/modules/account/back/models/account.json +++ b/modules/account/back/models/account.json @@ -1,49 +1,49 @@ { - "name": "Account", - "base": "VnModel", - "options": { - "mysql": { - "table": "account.account" - } - }, + "name": "Account", + "base": "VnModel", + "options": { + "mysql": { + "table": "account.account" + } + }, "properties": { - "id": { - "id": true - } - }, - "relations": { - "user": { - "type": "belongsTo", - "model": "VnUser", - "foreignKey": "id" - }, - "aliases": { - "type": "hasMany", - "model": "MailAliasAccount", - "foreignKey": "account" - } - }, - "acls": [ - { - "property": "login", - "accessType": "EXECUTE", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" + "id": { + "id": true + } + }, + "relations": { + "user": { + "type": "belongsTo", + "model": "VnUser", + "foreignKey": "id" }, - { + "aliases": { + "type": "hasMany", + "model": "MailAliasAccount", + "foreignKey": "account" + } + }, + "acls": [ + { + "property": "login", + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + }, + { "property": "logout", - "accessType": "EXECUTE", - "principalType": "ROLE", - "principalId": "$authenticated", - "permission": "ALLOW" - }, - { + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$authenticated", + "permission": "ALLOW" + }, + { "property": "changePassword", - "accessType": "EXECUTE", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" - } - ] + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] } From 5c777c705feecca80213dd5a7ef4d70d246e4c26 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 14 Nov 2023 13:00:20 +0100 Subject: [PATCH 07/87] refs #6434 feat: add new error message --- back/methods/vn-user/sign-in.js | 28 +++++++++++++++------------- back/models/vn-user.js | 13 +++++++++++-- loopback/locale/es.json | 4 +++- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/back/methods/vn-user/sign-in.js b/back/methods/vn-user/sign-in.js index b9e0d2f70..5c84b654e 100644 --- a/back/methods/vn-user/sign-in.js +++ b/back/methods/vn-user/sign-in.js @@ -26,7 +26,7 @@ module.exports = Self => { } }); - Self.signIn = async function(ctx, user, password, options) { + Self.signIn = async function (ctx, user, password, options) { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); @@ -40,15 +40,17 @@ module.exports = Self => { const validCredentials = vnUser && await vnUser.hasPassword(password); - if (validCredentials) { - if (!vnUser.active) - throw new UserError('User disabled'); - await Self.sendTwoFactor(ctx, vnUser, myOptions); - await Self.passExpired(vnUser, myOptions); + if (!validCredentials) + throw new UserError('Invalid credentials'); - if (vnUser.twoFactor) - throw new ForbiddenError(null, 'REQUIRES_2FA'); - } + if (!vnUser.active) + throw new UserError('User disabled'); + + await Self.sendTwoFactor(ctx, vnUser, myOptions); + await Self.passExpired(vnUser, myOptions); + + if (vnUser.twoFactor) + throw new ForbiddenError(null, 'REQUIRES_2FA'); return Self.validateLogin(user, password); }; @@ -59,18 +61,18 @@ module.exports = Self => { if (vnUser.passExpired && vnUser.passExpired.getTime() <= today.getTime()) { const err = new UserError('Pass expired', 'passExpired'); - err.details = {userId: vnUser.id, twoFactor: vnUser.twoFactor ? true : false}; + err.details = { userId: vnUser.id, twoFactor: vnUser.twoFactor ? true : false }; throw err; } }; - Self.sendTwoFactor = async(ctx, vnUser, myOptions) => { + Self.sendTwoFactor = async (ctx, vnUser, myOptions) => { if (vnUser.twoFactor === 'email') { const $ = Self.app.models; const code = String(Math.floor(Math.random() * 999999)); const maxTTL = ((60 * 1000) * 5); // 5 min - await $.AuthCode.upsertWithWhere({userFk: vnUser.id}, { + await $.AuthCode.upsertWithWhere({ userFk: vnUser.id }, { userFk: vnUser.id, code: code, expires: Date.vnNow() + maxTTL @@ -87,7 +89,7 @@ module.exports = Self => { ip: ctx.req?.connection?.remoteAddress, device: platform && browser ? platform + ', ' + browser : headers['user-agent'], }, - req: {getLocale: ctx.req.getLocale}, + req: { getLocale: ctx.req.getLocale }, }; await Self.sendTemplate(params, 'auth-code', true); diff --git a/back/models/vn-user.js b/back/models/vn-user.js index de5bf7b63..5c6e4a30f 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -2,6 +2,7 @@ const vnModel = require('vn-loopback/common/models/vn-model'); const {Email} = require('vn-print'); const ForbiddenError = require('vn-loopback/util/forbiddenError'); const LoopBackContext = require('loopback-context'); +const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self) { vnModel(Self); @@ -121,10 +122,18 @@ module.exports = function(Self) { }); Self.validateLogin = async function(user, password) { - let loginInfo = Object.assign({password}, Self.userUses(user)); - token = await Self.login(loginInfo, 'user'); + const loginInfo = Object.assign({password}, Self.userUses(user)); + const token = await Self.login(loginInfo, 'user'); const userToken = await token.user.get(); + + if (userToken.username !== user) { + console.error('ERROR!!! - Signin with other user', userToken, user); + throw new UserError('Try again'); + } + + const userCheck = await Self.app.models.VnUser.findOne({where: {name: user}}); + if (userToken.id != userCheck.id) await Self.validateLogin(user, password); try { await Self.app.models.Account.sync(userToken.name, password); } catch (err) { diff --git a/loopback/locale/es.json b/loopback/locale/es.json index b42720458..7cccc0fd0 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -325,5 +325,7 @@ "The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación", "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mímina", "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mímina", - "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada" + "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada", + "User disabled": "User disabled", + "Invalid credentials": "Invalid credentials" } From 7f82243ce6000176d9b9eeab03f81d68c781530f Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 14 Nov 2023 15:00:03 +0100 Subject: [PATCH 08/87] refs #6434 feat: create signInLog table --- back/methods/vn-user/sign-in.js | 19 ++++++---- db/changes/234801/00-createSignInLogTable.sql | 19 ++++++++++ modules/account/back/model-config.json | 3 ++ modules/account/back/models/sign_in-log.json | 35 +++++++++++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 db/changes/234801/00-createSignInLogTable.sql create mode 100644 modules/account/back/models/sign_in-log.json diff --git a/back/methods/vn-user/sign-in.js b/back/methods/vn-user/sign-in.js index 5c84b654e..78d74b147 100644 --- a/back/methods/vn-user/sign-in.js +++ b/back/methods/vn-user/sign-in.js @@ -26,7 +26,7 @@ module.exports = Self => { } }); - Self.signIn = async function (ctx, user, password, options) { + Self.signIn = async function(ctx, user, password, options) { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); @@ -51,8 +51,13 @@ module.exports = Self => { if (vnUser.twoFactor) throw new ForbiddenError(null, 'REQUIRES_2FA'); - - return Self.validateLogin(user, password); + const validateLogin = await Self.validateLogin(user, password); + await Self.app.models.SignInLog.create({ + id: validateLogin.token, + userFk: vnUser.id, + ip: ctx.req.ip + }); + return validateLogin; }; Self.passExpired = async vnUser => { @@ -61,18 +66,18 @@ module.exports = Self => { if (vnUser.passExpired && vnUser.passExpired.getTime() <= today.getTime()) { const err = new UserError('Pass expired', 'passExpired'); - err.details = { userId: vnUser.id, twoFactor: vnUser.twoFactor ? true : false }; + err.details = {userId: vnUser.id, twoFactor: vnUser.twoFactor ? true : false}; throw err; } }; - Self.sendTwoFactor = async (ctx, vnUser, myOptions) => { + Self.sendTwoFactor = async(ctx, vnUser, myOptions) => { if (vnUser.twoFactor === 'email') { const $ = Self.app.models; const code = String(Math.floor(Math.random() * 999999)); const maxTTL = ((60 * 1000) * 5); // 5 min - await $.AuthCode.upsertWithWhere({ userFk: vnUser.id }, { + await $.AuthCode.upsertWithWhere({userFk: vnUser.id}, { userFk: vnUser.id, code: code, expires: Date.vnNow() + maxTTL @@ -89,7 +94,7 @@ module.exports = Self => { ip: ctx.req?.connection?.remoteAddress, device: platform && browser ? platform + ', ' + browser : headers['user-agent'], }, - req: { getLocale: ctx.req.getLocale }, + req: {getLocale: ctx.req.getLocale}, }; await Self.sendTemplate(params, 'auth-code', true); diff --git a/db/changes/234801/00-createSignInLogTable.sql b/db/changes/234801/00-createSignInLogTable.sql new file mode 100644 index 000000000..977de4646 --- /dev/null +++ b/db/changes/234801/00-createSignInLogTable.sql @@ -0,0 +1,19 @@ + + +-- +-- Table structure for table `signInLog` +-- + +DROP TABLE IF EXISTS `account`.`signInLog`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `account`.`signInLog` ( + `id` varchar(10) NOT NULL , + `userFk` int(10) unsigned DEFAULT NULL, + `creationDate` timestamp NULL DEFAULT current_timestamp(), + `ip` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, + PRIMARY KEY (`id`), + KEY `userFk` (`userFk`), + CONSTRAINT `signInLog_ibfk_1` FOREIGN KEY (`userFk`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); + diff --git a/modules/account/back/model-config.json b/modules/account/back/model-config.json index a4eb9fa57..b4bd6dbaf 100644 --- a/modules/account/back/model-config.json +++ b/modules/account/back/model-config.json @@ -35,6 +35,9 @@ "SambaConfig": { "dataSource": "vn" }, + "SignInLog": { + "dataSource": "vn" + }, "Sip": { "dataSource": "vn" }, diff --git a/modules/account/back/models/sign_in-log.json b/modules/account/back/models/sign_in-log.json new file mode 100644 index 000000000..df9ad8153 --- /dev/null +++ b/modules/account/back/models/sign_in-log.json @@ -0,0 +1,35 @@ +{ + "name": "SignInLog", + "base": "VnModel", + "options": { + "mysql": { + "table": "account.signInLog" + } + }, + "properties": { + "id": { + "id": true, + "type": "string", + "forceId": false + }, + "creationDate": { + "type": "date" + }, + "userFk": { + "type": "number" + }, + "ip": { + "type": "string" + } + }, + "relations": { + "user": { + "type": "belongsTo", + "model": "VnUser", + "foreignKey": "userFk" + } + }, + "scope": { + "order": ["creationDate DESC", "id DESC"] + } +} From add3a81032aae8ecfa41e3fad37179c6b1dacac4 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 15 Nov 2023 09:29:26 +0100 Subject: [PATCH 09/87] refs #6434 feat: remove recursively fn --- back/methods/vn-user/sign-in.js | 2 ++ back/models/vn-user.js | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/back/methods/vn-user/sign-in.js b/back/methods/vn-user/sign-in.js index 78d74b147..e51cf8d8e 100644 --- a/back/methods/vn-user/sign-in.js +++ b/back/methods/vn-user/sign-in.js @@ -51,7 +51,9 @@ module.exports = Self => { if (vnUser.twoFactor) throw new ForbiddenError(null, 'REQUIRES_2FA'); + const validateLogin = await Self.validateLogin(user, password); + await Self.app.models.SignInLog.create({ id: validateLogin.token, userFk: vnUser.id, diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 5c6e4a30f..00f5cd0b8 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -132,8 +132,6 @@ module.exports = function(Self) { throw new UserError('Try again'); } - const userCheck = await Self.app.models.VnUser.findOne({where: {name: user}}); - if (userToken.id != userCheck.id) await Self.validateLogin(user, password); try { await Self.app.models.Account.sync(userToken.name, password); } catch (err) { From 0ddfb28327a2723fe394eec50482f3669a6bf274 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 20 Nov 2023 07:56:15 +0100 Subject: [PATCH 10/87] refs #5914 fix: transferInvoice --- db/dump/dumpedFixtures.sql | 13 +- db/dump/structure.sql | 6 +- loopback/locale/es.json | 15 ++- .../invoiceOut/specs/transferinvoice.spec.js | 4 +- .../methods/invoiceOut/transferInvoice.js | 34 +++-- .../back/models/invoice-correction.json | 9 +- ...ype-477.json => sii-type-invoice-out.json} | 3 + .../front/descriptor-menu/index.html | 120 +++++++++--------- .../invoiceOut/front/descriptor-menu/index.js | 10 +- .../front/descriptor-menu/locale/es.yml | 2 +- modules/ticket/back/methods/sale/refund.js | 4 +- .../back/methods/ticket/invoiceTickets.js | 19 ++- .../ticket/back/methods/ticket/makeInvoice.js | 18 ++- modules/ticket/back/methods/ticket/refund.js | 2 +- 14 files changed, 155 insertions(+), 104 deletions(-) rename modules/invoiceOut/back/models/{cplus-invoice-type-477.json => sii-type-invoice-out.json} (86%) diff --git a/db/dump/dumpedFixtures.sql b/db/dump/dumpedFixtures.sql index 43eba7f24..5e3438dbf 100644 --- a/db/dump/dumpedFixtures.sql +++ b/db/dump/dumpedFixtures.sql @@ -280,7 +280,18 @@ UNLOCK TABLES; LOCK TABLES `siiTypeInvoiceOut` WRITE; /*!40000 ALTER TABLE `siiTypeInvoiceOut` DISABLE KEYS */; -INSERT INTO `siiTypeInvoiceOut` VALUES (1,'F1 - Factura'),(2,'F2 - Factura simplificada (ticket)'),(3,'F3 - Factura emitida en sustitución de facturas simplificadas facturadas y declaradas'),(4,'F4 - Asiento resumen de facturas'),(5,'R1 - Factura rectificativa (Art. 80.1, 80.2 y error fundado en derecho)'),(6,'R2 - Factura rectificativa (Art. 80.3)'),(7,'R3 - Factura rectificativa (Art. 80.4)'),(8,'R4 - Factura rectificativa (Resto)'),(9,'R5 - Factura rectificativa en facturas simplificadas'); + +INSERT INTO `siiTypeInvoiceOut` (id, code, description) VALUES + (1, 'F1', 'Factura'), + (2, 'F2', 'Factura simplificada (ticket)'), + (3, 'F3', 'Factura emitida en sustitución de facturas simplificadas facturadas y declaradas'), + (4, 'F4', 'Asiento resumen de facturas'), + (5, 'R1', 'Factura rectificativa (Art. 80.1, 80.2 y error fundado en derecho)'), + (6, 'R2', 'Factura rectificativa (Art. 80.3)'), + (7, 'R3', 'Factura rectificativa (Art. 80.4)'), + (8, 'R4', 'Factura rectificativa (Resto)'), + (9, 'R5', 'Factura rectificativa en facturas simplificadas'); + /*!40000 ALTER TABLE `siiTypeInvoiceOut` ENABLE KEYS */; UNLOCK TABLES; diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 3dab0c5a4..2eecf6c30 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -26001,9 +26001,11 @@ DROP TABLE IF EXISTS `siiTypeInvoiceOut`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `siiTypeInvoiceOut` ( `id` int(10) unsigned NOT NULL, + `code` varchar(2) NOT NULL, `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='(*18) TIPO FACTURA (Asientos)REPERCUTIDO - DEVENGADO (477)'; + PRIMARY KEY (`id`), + UNIQUE KEY `code_UNIQUE` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Tipo de Factura Emitidas en el suministro de inmediato'; /*!40101 SET character_set_client = @saved_cs_client */; -- diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 239faff34..0dcbe0dc2 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -326,5 +326,16 @@ "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada", "User disabled": "Usuario desactivado", "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", - "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima" -} + "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima", + "Base negativa para los tickets: 65": "Base negativa para los tickets: 65", + "Base negativa para los tickets: 67": "Base negativa para los tickets: 67", + "Base negativa para los tickets: 70": "Base negativa para los tickets: 70", + "Base negativa para los tickets: 72": "Base negativa para los tickets: 72", + "Base negativa para los tickets: 74": "Base negativa para los tickets: 74", + "Base negativa para los tickets: 33": "Base negativa para los tickets: 33", + "Base negativa para los tickets: 35": "Base negativa para los tickets: 35", + "Base negativa para los tickets: 37": "Base negativa para los tickets: 37", + "Base negativa para los tickets: 39": "Base negativa para los tickets: 39", + "Base negativa para los tickets: 41": "Base negativa para los tickets: 41", + "Base negativa para los tickets: 43": "Base negativa para los tickets: 43" +} \ No newline at end of file diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js index 800a4ea83..dea4b6d00 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js @@ -24,7 +24,7 @@ describe('InvoiceOut tranferInvoice()', () => { const options = {transaction: tx}; const args = { id: '1', - ref: 'T4444444', + refFk: 'T4444444', newClientFk: 1, cplusRectificationId: 1, siiTypeInvoiceOutId: 1, @@ -49,7 +49,7 @@ describe('InvoiceOut tranferInvoice()', () => { const options = {transaction: tx}; const args = { id: '1', - ref: 'T1111111', + refFk: 'T1111111', newClientFk: 1101, cplusRectificationId: 1, siiTypeInvoiceOutId: 1, diff --git a/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js index dde535c99..dcdd9b9b1 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js @@ -12,7 +12,7 @@ module.exports = Self => { description: 'Issued invoice id' }, { - arg: 'ref', + arg: 'refFk', type: 'string', required: true }, @@ -22,17 +22,17 @@ module.exports = Self => { required: true }, { - arg: 'cplusRectificationId', + arg: 'cplusRectificationFk', type: 'number', required: true }, { - arg: 'siiTypeInvoiceOutId', + arg: 'siiTypeInvoiceOutFk', type: 'number', required: true }, { - arg: 'invoiceCorrectionTypeId', + arg: 'invoiceCorrectionTypeFk', type: 'number', required: true }, @@ -50,14 +50,14 @@ module.exports = Self => { Self.transferInvoice = async(ctx, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; - const args = ctx.args; + const {id, refFk, newClientFk, cplusRectificationFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk} = ctx.args; let tx; if (typeof options == 'object') Object.assign(myOptions, options); - const {clientFk} = await models.InvoiceOut.findById(args.id); + const {clientFk} = await models.InvoiceOut.findById(id); - if (clientFk == args.newClientFk) + if (clientFk == newClientFk) throw new UserError(`Select a different client`); if (!myOptions.transaction) { @@ -65,10 +65,10 @@ module.exports = Self => { myOptions.transaction = tx; } try { - const filterRef = {where: {refFk: args.ref}}; + const filterRef = {where: {refFk: refFk}}; const tickets = await models.Ticket.find(filterRef, myOptions); const ticketsIds = tickets.map(ticket => ticket.id); - await models.Ticket.refund(ctx, ticketsIds, null, myOptions); + const refundTickets = await models.Ticket.refund(ctx, ticketsIds, null, myOptions); const filterTicket = {where: {ticketFk: {inq: ticketsIds}}}; @@ -82,20 +82,16 @@ module.exports = Self => { const clonedTicketIds = []; for (const clonedTicket of clonedTickets) { - await clonedTicket.updateAttribute('clientFk', args.newClientFk, myOptions); + await clonedTicket.updateAttribute('clientFk', newClientFk, myOptions); clonedTicketIds.push(clonedTicket.id); } - const invoiceIds = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions); - const [invoiceId] = invoiceIds; + const invoiceCorrection = + {correctedFk: id, cplusRectificationFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk}; + const refundTicketIds = refundTickets.map(ticket => ticket.id); - await models.InvoiceCorrection.create({ - correctingFk: invoiceId, - correctedFk: args.id, - cplusRectificationTypeFk: args.cplusRectificationId, - siiTypeInvoiceOutFk: args.siiTypeInvoiceOutId, - invoiceCorrectionTypeFk: args.invoiceCorrectionTypeId - }, myOptions); + await models.Ticket.invoiceTickets(ctx, refundTicketIds, invoiceCorrection, myOptions); + const [[invoiceId]] = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions); if (tx) { await tx.commit(); diff --git a/modules/invoiceOut/back/models/invoice-correction.json b/modules/invoiceOut/back/models/invoice-correction.json index 43e4f07ef..5924c9232 100644 --- a/modules/invoiceOut/back/models/invoice-correction.json +++ b/modules/invoiceOut/back/models/invoice-correction.json @@ -16,13 +16,16 @@ "type": "number" }, "cplusRectificationTypeFk": { - "type": "number" + "type": "number", + "required": true }, "siiTypeInvoiceOutFk": { - "type": "number" + "type": "number", + "required": true }, "invoiceCorrectionTypeFk": { - "type": "number" + "type": "number", + "required": true } } } diff --git a/modules/invoiceOut/back/models/cplus-invoice-type-477.json b/modules/invoiceOut/back/models/sii-type-invoice-out.json similarity index 86% rename from modules/invoiceOut/back/models/cplus-invoice-type-477.json rename to modules/invoiceOut/back/models/sii-type-invoice-out.json index 17b312617..58d50a12c 100644 --- a/modules/invoiceOut/back/models/cplus-invoice-type-477.json +++ b/modules/invoiceOut/back/models/sii-type-invoice-out.json @@ -12,6 +12,9 @@ "type": "number", "description": "Identifier" }, + "code": { + "type": "string" + }, "description": { "type": "string" } diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html index 0052f0c03..267aa0b15 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.html +++ b/modules/invoiceOut/front/descriptor-menu/index.html @@ -7,7 +7,8 @@ + data="siiTypeInvoiceOuts" + where="{code: {like: 'R%'}}"> + + transferInvoice +
- - - - #{{id}} - {{::name}} - - - - - {{::description}} - - - - - - - - - -
+ + + + #{{id}} - {{::name}} + + + + + {{::description}} + + + + + + + {{::code}} - {{::description}} + + + + + +
diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js index d3862a753..f9d436092 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.js +++ b/modules/invoiceOut/front/descriptor-menu/index.js @@ -129,11 +129,11 @@ class Controller extends Section { transferInvoice() { const params = { id: this.invoiceOut.id, - ref: this.invoiceOut.ref, - newClientFk: this.invoiceOut.client.id, - cplusRectificationId: this.cplusRectificationType, - siiTypeInvoiceOutId: this.siiTypeInvoiceOut, - invoiceCorrectionTypeId: this.invoiceCorrectionType + refFk: this.invoiceOut.ref, + newClientFk: this.clientId, + cplusRectificationFk: this.cplusRectificationType, + siiTypeInvoiceOutFk: this.siiTypeInvoiceOut, + invoiceCorrectionTypeFk: this.invoiceCorrectionType }; this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => { const invoiceId = res.data; diff --git a/modules/invoiceOut/front/descriptor-menu/locale/es.yml b/modules/invoiceOut/front/descriptor-menu/locale/es.yml index 0f74b5fec..9456646af 100644 --- a/modules/invoiceOut/front/descriptor-menu/locale/es.yml +++ b/modules/invoiceOut/front/descriptor-menu/locale/es.yml @@ -22,4 +22,4 @@ The email can't be empty: El correo no puede estar vacío The following refund tickets have been created: "Se han creado los siguientes tickets de abono: {{ticketIds}}" Refund...: Abono... Transfer invoice to...: Transferir factura a... -Cplus Type: Cplus Tipo +Rectificative type: Tipo rectificativa diff --git a/modules/ticket/back/methods/sale/refund.js b/modules/ticket/back/methods/sale/refund.js index 17b70f12b..a7831e7e3 100644 --- a/modules/ticket/back/methods/sale/refund.js +++ b/modules/ticket/back/methods/sale/refund.js @@ -19,7 +19,7 @@ module.exports = Self => { } ], returns: { - type: ['number'], + type: ['object'], root: true }, http: { @@ -54,7 +54,7 @@ module.exports = Self => { if (tx) await tx.commit(); - return refundsTicket[0]; + return refundsTicket; } catch (e) { if (tx) await tx.rollback(); throw e; diff --git a/modules/ticket/back/methods/ticket/invoiceTickets.js b/modules/ticket/back/methods/ticket/invoiceTickets.js index fa3ee93af..29fb1769b 100644 --- a/modules/ticket/back/methods/ticket/invoiceTickets.js +++ b/modules/ticket/back/methods/ticket/invoiceTickets.js @@ -10,7 +10,13 @@ module.exports = function(Self) { description: 'The tickets id', type: ['number'], required: true + }, + { + arg: 'invoiceCorrection', + description: 'The invoice correction', + type: 'object', } + ], returns: { type: ['object'], @@ -22,7 +28,7 @@ module.exports = function(Self) { } }); - Self.invoiceTickets = async(ctx, ticketsIds, options) => { + Self.invoiceTickets = async(ctx, ticketsIds, invoiceCorrection, options) => { const models = Self.app.models; const date = Date.vnNew(); date.setHours(0, 0, 0, 0); @@ -68,9 +74,9 @@ module.exports = function(Self) { const addressIds = result.map(address => address.addressFk); for (const address of addressIds) - await createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, myOptions); + await createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, invoiceCorrection, myOptions); } else - await createInvoice(ctx, companyId, ticketsIds, null, invoicesIds, myOptions); + await createInvoice(ctx, companyId, ticketsIds, null, invoicesIds, invoiceCorrection, myOptions); if (tx) await tx.commit(); } catch (e) { @@ -85,9 +91,9 @@ module.exports = function(Self) { return invoicesIds; }; - async function createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, myOptions) { + async function createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, invoiceCorrection, myOptions) { const models = Self.app.models; - + console.log(ticketsIds, address); await models.Ticket.rawSql(` CREATE OR REPLACE TEMPORARY TABLE tmp.ticketToInvoice (PRIMARY KEY (id)) @@ -98,7 +104,8 @@ module.exports = function(Self) { ${address ? `AND addressFk = ${address}` : ''} `, [ticketsIds], myOptions); - const invoiceId = await models.Ticket.makeInvoice(ctx, 'R', companyId, Date.vnNew(), myOptions); + const invoiceId = + await models.Ticket.makeInvoice(ctx, 'R', companyId, Date.vnNew(), invoiceCorrection, myOptions); invoicesIds.push(invoiceId); } }; diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index e18e58e0b..9618e49e0 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -22,6 +22,11 @@ module.exports = function(Self) { description: 'The invoice date', type: 'date', required: true + }, + { + arg: 'invoiceCorrection', + description: 'The invoice correction', + type: 'object', } ], returns: { @@ -34,7 +39,7 @@ module.exports = function(Self) { } }); - Self.makeInvoice = async(ctx, invoiceType, companyFk, invoiceDate, options) => { + Self.makeInvoice = async(ctx, invoiceType, companyFk, invoiceDate, invoiceCorrection, options) => { const models = Self.app.models; invoiceDate.setHours(0, 0, 0, 0); @@ -67,8 +72,8 @@ module.exports = function(Self) { const [firstTicket] = tickets; const clientId = firstTicket.clientFk; - const clientCanBeInvoiced = await models.Client.canBeInvoiced(clientId, companyFk, myOptions); - if (!clientCanBeInvoiced) + const clientCanBeInvoiced = await models.Client.canBeInvoiced(clientId, companyFk, invoiceCorrection, myOptions); + if (!clientCanBeInvoiced && !invoiceCorrection) throw new UserError(`This client can't be invoiced`); const query = `SELECT vn.invoiceSerial(?, ?, ?) AS serial`; @@ -85,6 +90,13 @@ module.exports = function(Self) { if (!resultInvoice) throw new UserError('No tickets to invoice', 'notInvoiced'); + if (invoiceCorrection) { + await models.InvoiceCorrection.create( + Object.assign(invoiceCorrection, {correctingFk: resultInvoice.id}), + myOptions + ); + } + if (serial != 'R' && resultInvoice.id) await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions); diff --git a/modules/ticket/back/methods/ticket/refund.js b/modules/ticket/back/methods/ticket/refund.js index 758384ae2..4fed02260 100644 --- a/modules/ticket/back/methods/ticket/refund.js +++ b/modules/ticket/back/methods/ticket/refund.js @@ -15,7 +15,7 @@ module.exports = Self => { } ], returns: { - type: ['number'], + type: ['object'], root: true }, http: { From e314a67fe72f6112337330f7aefa1e46b7d7e84f Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 23 Nov 2023 13:25:31 +0100 Subject: [PATCH 11/87] refs #6274 time control methods migrated --- .../methods/worker-time-control/clockIn.js | 34 ++++++++++++++++ .../methods/worker-time-control/getClockIn.js | 30 ++++++++++++++ .../back/methods/worker-time-control/login.js | 39 +++++++++++++++++++ .../worker/back/models/worker-time-control.js | 3 ++ 4 files changed, 106 insertions(+) create mode 100644 modules/worker/back/methods/worker-time-control/clockIn.js create mode 100644 modules/worker/back/methods/worker-time-control/getClockIn.js create mode 100644 modules/worker/back/methods/worker-time-control/login.js diff --git a/modules/worker/back/methods/worker-time-control/clockIn.js b/modules/worker/back/methods/worker-time-control/clockIn.js new file mode 100644 index 000000000..45de85f1d --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/clockIn.js @@ -0,0 +1,34 @@ +module.exports = Self => { + Self.remoteMethodCtx('clockIn', { + description: 'Check if the employee can clock in', + accessType: 'READ', + accepts: [ + { + arg: 'workerFk', + type: 'integer', + required: true, + }, + { + arg: 'direction', + type: 'integer' + }, + { + arg: 'key', + type: 'string', + } + ], + http: { + path: `/clockIn`, + verb: 'POST' + } + }); + + Self.clockIn = async(ctx, pin, direction, key, options) => { + const myOptions = {}; + if (typeof options == 'object') + Object.assign(myOptions, options); + + const query = 'CALL vn.workerTimeControl_clockIn(?, NULL, ?)'; + return await Self.rawSql(query, [workerFk, direction], options); + }; +}; diff --git a/modules/worker/back/methods/worker-time-control/getClockIn.js b/modules/worker/back/methods/worker-time-control/getClockIn.js new file mode 100644 index 000000000..603914655 --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/getClockIn.js @@ -0,0 +1,30 @@ +module.exports = Self => { + Self.remoteMethodCtx('getClockIn', { + description: 'Shows the clockings for each day, in columns per day', + accessType: 'READ', + accepts: [ + { + arg: 'workerFk', + type: 'int', + required: true, + }, + { + arg: 'key', + type: 'string', + } + ], + http: { + path: `/getClockIn`, + verb: 'POST' + } + }); + + Self.getClockIn = async(ctx, workerFk, key, options) => { + const myOptions = {}; + if (typeof options == 'object') + Object.assign(myOptions, options); + + const query = `CALL vn.workerTimeControl_getClockIn(?, CURDATE())`; + return await Self.rawSql(query, [workerFk], myOptions); + }; +}; diff --git a/modules/worker/back/methods/worker-time-control/login.js b/modules/worker/back/methods/worker-time-control/login.js new file mode 100644 index 000000000..75813411a --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/login.js @@ -0,0 +1,39 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('login', { + description: 'Consult the user\'s information and the buttons that must be activated after logging in', + accessType: 'READ', + accepts: [ + { + arg: 'pin', + type: 'string', + required: true, + }, + { + arg: 'key', + type: 'string', + } + ], + returns: { + type: 'Object', + root: true + }, + http: { + path: `/login`, + verb: 'POST' + } + }); + + Self.login = async(ctx, pin, key, options) => { + const myOptions = {}; + if (typeof options == 'object') + Object.assign(myOptions, options); + + const query = `CALL vn.workerTimeControl_login(?)`; + const user = await Self.rawSql(query, [pin], myOptions); + + if (!user) throw new UserError('Indique el pin.'); + return user; + }; +}; diff --git a/modules/worker/back/models/worker-time-control.js b/modules/worker/back/models/worker-time-control.js index d5da680cf..1457c7a46 100644 --- a/modules/worker/back/models/worker-time-control.js +++ b/modules/worker/back/models/worker-time-control.js @@ -10,6 +10,9 @@ module.exports = Self => { require('../methods/worker-time-control/weeklyHourRecordEmail')(Self); require('../methods/worker-time-control/getMailStates')(Self); require('../methods/worker-time-control/resendWeeklyHourEmail')(Self); + require('../methods/worker-time-control/login')(Self); + require('../methods/worker-time-control/getClockIn')(Self); + require('../methods/worker-time-control/clockIn')(Self); Self.rewriteDbError(function(err) { if (err.code === 'ER_DUP_ENTRY') From 62fab4e74412ed9df395079ee92371deb48b8e1e Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 27 Nov 2023 11:52:37 +0100 Subject: [PATCH 12/87] refs #5854 itemShelving traducciones --- modules/item/back/locale/item-shelving/en.yml | 13 +++++++++++++ modules/item/back/locale/item-shelving/es.yml | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 modules/item/back/locale/item-shelving/en.yml create mode 100644 modules/item/back/locale/item-shelving/es.yml diff --git a/modules/item/back/locale/item-shelving/en.yml b/modules/item/back/locale/item-shelving/en.yml new file mode 100644 index 000000000..062d4db3f --- /dev/null +++ b/modules/item/back/locale/item-shelving/en.yml @@ -0,0 +1,13 @@ +name: itemShelving +columns: + id: id + itemFk: itemFk + shelvingFk: shelvingFk + visible: visible + created: created + grouping: grouping + packing: packing + packagingFk: packagingFk + userFk: userFk + isChecked: isChecked + buyFk: buyFk diff --git a/modules/item/back/locale/item-shelving/es.yml b/modules/item/back/locale/item-shelving/es.yml new file mode 100644 index 000000000..a64b23bfa --- /dev/null +++ b/modules/item/back/locale/item-shelving/es.yml @@ -0,0 +1,13 @@ +name: artículo del carro +columns: + id: id + itemFk: artículo + shelvingFk: matrícula carro + visible: visible + created: creado + grouping: agrupación + packing: embalaje + packagingFk: paquete + userFk: usuario + isChecked: está revisado + buyFk: compra \ No newline at end of file From 50a97693b99d91df8d5c6b776de7d784a6195c4f Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 28 Nov 2023 07:48:42 +0100 Subject: [PATCH 13/87] refs 5666 feat: remove loggable.js file --- loopback/common/models/loggable.js | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 loopback/common/models/loggable.js diff --git a/loopback/common/models/loggable.js b/loopback/common/models/loggable.js deleted file mode 100644 index 360c84566..000000000 --- a/loopback/common/models/loggable.js +++ /dev/null @@ -1,15 +0,0 @@ -const LoopBackContext = require('loopback-context'); - -module.exports = function(Self) { - Self.setup = function() { - Self.super_.setup.call(this); - }; - - Self.observe('before save', async function(ctx) { - ctx.options.httpCtx = LoopBackContext.getCurrentContext(); - }); - - Self.observe('before delete', async function(ctx) { - ctx.options.httpCtx = LoopBackContext.getCurrentContext(); - }); -}; From f5f2896cbf3be60d1c70d4eb1f850143d1eb0153 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 28 Nov 2023 08:12:16 +0100 Subject: [PATCH 14/87] refs 5666 feat: replace Role model by VnRole model --- back/models/dms-type.json | 4 ++-- back/models/image-collection.json | 5 ++--- back/models/notificationAcl.json | 4 ++-- back/models/vn-user.json | 2 +- modules/account/back/models/role-inherit.json | 4 ++-- modules/account/back/models/role-role.json | 4 ++-- modules/claim/back/models/claim-state.json | 2 +- modules/client/back/models/client-credit-limit.json | 4 ++-- 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/back/models/dms-type.json b/back/models/dms-type.json index de3d564b4..8d7195132 100644 --- a/back/models/dms-type.json +++ b/back/models/dms-type.json @@ -29,12 +29,12 @@ "relations": { "readRole": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "readRoleFk" }, "writeRole": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "writeRoleFk" } }, diff --git a/back/models/image-collection.json b/back/models/image-collection.json index 186ab0208..ae0e0adcd 100644 --- a/back/models/image-collection.json +++ b/back/models/image-collection.json @@ -46,12 +46,12 @@ }, "readRole": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "readRoleFk" }, "writeRole": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "writeRoleFk" } }, @@ -64,4 +64,3 @@ } ] } - \ No newline at end of file diff --git a/back/models/notificationAcl.json b/back/models/notificationAcl.json index a20187961..9ab85530f 100644 --- a/back/models/notificationAcl.json +++ b/back/models/notificationAcl.json @@ -24,8 +24,8 @@ }, "role": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "roleFk" } } -} \ No newline at end of file +} diff --git a/back/models/vn-user.json b/back/models/vn-user.json index bda0a6ec3..cf5796123 100644 --- a/back/models/vn-user.json +++ b/back/models/vn-user.json @@ -66,7 +66,7 @@ "relations": { "role": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "roleFk" }, "roles": { diff --git a/modules/account/back/models/role-inherit.json b/modules/account/back/models/role-inherit.json index 4b69ffdc2..a89f47b77 100644 --- a/modules/account/back/models/role-inherit.json +++ b/modules/account/back/models/role-inherit.json @@ -15,12 +15,12 @@ "relations": { "owner": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "role" }, "inherits": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "inheritsFrom" } } diff --git a/modules/account/back/models/role-role.json b/modules/account/back/models/role-role.json index 77df7a920..e59351c59 100644 --- a/modules/account/back/models/role-role.json +++ b/modules/account/back/models/role-role.json @@ -14,12 +14,12 @@ "relations": { "owner": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "role" }, "inherits": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "inheritsFrom" } } diff --git a/modules/claim/back/models/claim-state.json b/modules/claim/back/models/claim-state.json index f5bde4168..3ee932f16 100644 --- a/modules/claim/back/models/claim-state.json +++ b/modules/claim/back/models/claim-state.json @@ -32,7 +32,7 @@ "relations": { "writeRole": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "roleFk" } }, diff --git a/modules/client/back/models/client-credit-limit.json b/modules/client/back/models/client-credit-limit.json index 740f0cf53..922d4d14b 100644 --- a/modules/client/back/models/client-credit-limit.json +++ b/modules/client/back/models/client-credit-limit.json @@ -19,8 +19,8 @@ "relations": { "role": { "type": "belongsTo", - "model": "Role", + "model": "VnRole", "foreignKey": "roleFk" } } -} \ No newline at end of file +} From 29fb36010cd303390b1f56b686d57d644f67ce88 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 28 Nov 2023 14:48:03 +0100 Subject: [PATCH 15/87] refs #6274 back methods created --- db/changes/235001/00-timecontrol.sql | 13 ++++++++++++ .../methods/worker-time-control/clockIn.js | 19 +++++++++--------- .../methods/worker-time-control/getClockIn.js | 20 ++++++++++--------- .../back/methods/worker-time-control/login.js | 10 +++------- 4 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 db/changes/235001/00-timecontrol.sql diff --git a/db/changes/235001/00-timecontrol.sql b/db/changes/235001/00-timecontrol.sql new file mode 100644 index 000000000..ac7dc85d6 --- /dev/null +++ b/db/changes/235001/00-timecontrol.sql @@ -0,0 +1,13 @@ +INSERT INTO `account`.`role` (name, description) + VALUES ('timeControl','Tablet para fichar'); + +INSERT INTO `account`.`roleInherit` (role, inheritsFrom) + VALUES (127, 11); + +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('workerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', '*'), + ('workerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', '*'), + ('workerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', '*'); + +CALL `account`.`role_sync`(); diff --git a/modules/worker/back/methods/worker-time-control/clockIn.js b/modules/worker/back/methods/worker-time-control/clockIn.js index 45de85f1d..3cc57d341 100644 --- a/modules/worker/back/methods/worker-time-control/clockIn.js +++ b/modules/worker/back/methods/worker-time-control/clockIn.js @@ -1,7 +1,7 @@ module.exports = Self => { - Self.remoteMethodCtx('clockIn', { + Self.remoteMethod('clockIn', { description: 'Check if the employee can clock in', - accessType: 'READ', + accessType: 'WRITE', accepts: [ { arg: 'workerFk', @@ -10,25 +10,26 @@ module.exports = Self => { }, { arg: 'direction', - type: 'integer' + type: 'string' }, - { - arg: 'key', - type: 'string', - } + ], http: { path: `/clockIn`, verb: 'POST' + }, + returns: { + type: 'Object', + root: true } }); - Self.clockIn = async(ctx, pin, direction, key, options) => { + Self.clockIn = async(workerFk, direction, options) => { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); const query = 'CALL vn.workerTimeControl_clockIn(?, NULL, ?)'; - return await Self.rawSql(query, [workerFk, direction], options); + return await Self.rawSql(query, [workerFk, direction], myOptions); }; }; diff --git a/modules/worker/back/methods/worker-time-control/getClockIn.js b/modules/worker/back/methods/worker-time-control/getClockIn.js index 603914655..bc0675db8 100644 --- a/modules/worker/back/methods/worker-time-control/getClockIn.js +++ b/modules/worker/back/methods/worker-time-control/getClockIn.js @@ -1,5 +1,5 @@ module.exports = Self => { - Self.remoteMethodCtx('getClockIn', { + Self.remoteMethod('getClockIn', { description: 'Shows the clockings for each day, in columns per day', accessType: 'READ', accepts: [ @@ -8,23 +8,25 @@ module.exports = Self => { type: 'int', required: true, }, - { - arg: 'key', - type: 'string', - } + ], http: { path: `/getClockIn`, - verb: 'POST' - } + verb: 'GET' + }, + returns: { + type: ['Object'], + root: true + }, }); - Self.getClockIn = async(ctx, workerFk, key, options) => { + Self.getClockIn = async(workerFk, options) => { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); const query = `CALL vn.workerTimeControl_getClockIn(?, CURDATE())`; - return await Self.rawSql(query, [workerFk], myOptions); + const [result] = await Self.rawSql(query, [workerFk], myOptions); + return result; }; }; diff --git a/modules/worker/back/methods/worker-time-control/login.js b/modules/worker/back/methods/worker-time-control/login.js index 75813411a..894b5ba17 100644 --- a/modules/worker/back/methods/worker-time-control/login.js +++ b/modules/worker/back/methods/worker-time-control/login.js @@ -1,7 +1,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethodCtx('login', { + Self.remoteMethod('login', { description: 'Consult the user\'s information and the buttons that must be activated after logging in', accessType: 'READ', accepts: [ @@ -10,10 +10,6 @@ module.exports = Self => { type: 'string', required: true, }, - { - arg: 'key', - type: 'string', - } ], returns: { type: 'Object', @@ -25,7 +21,7 @@ module.exports = Self => { } }); - Self.login = async(ctx, pin, key, options) => { + Self.login = async(pin, options) => { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); @@ -34,6 +30,6 @@ module.exports = Self => { const user = await Self.rawSql(query, [pin], myOptions); if (!user) throw new UserError('Indique el pin.'); - return user; + return user[0][0]; }; }; From 0186c2c80678f518de105192d1e306f2361f056a Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 29 Nov 2023 07:33:49 +0100 Subject: [PATCH 16/87] refs #6085 aclMail back --- db/changes/235001/00-aclsMails.sql | 7 ++++ .../account/front/alias/acl/create/index.js | 33 +++++++++++++++++++ modules/account/front/alias/acl/index.js | 4 +++ .../account/front/alias/acl/index/index.js | 15 +++++++++ modules/account/front/alias/acl/main/index.js | 18 ++++++++++ 5 files changed, 77 insertions(+) create mode 100644 db/changes/235001/00-aclsMails.sql create mode 100644 modules/account/front/alias/acl/create/index.js create mode 100644 modules/account/front/alias/acl/index.js create mode 100644 modules/account/front/alias/acl/index/index.js create mode 100644 modules/account/front/alias/acl/main/index.js diff --git a/db/changes/235001/00-aclsMails.sql b/db/changes/235001/00-aclsMails.sql new file mode 100644 index 000000000..92603aec4 --- /dev/null +++ b/db/changes/235001/00-aclsMails.sql @@ -0,0 +1,7 @@ +-- Definición de la tabla mailAliasACL +CREATE TABLE `account`.`mailAliasACL` ( + `mailAliasFk` int(10) unsigned NOT NULL, + `roleFk` int(10) unsigned NOT NULL, + FOREIGN KEY (`mailAliasFk`) REFERENCES `account`.`mailAlias` (`id`), + FOREIGN KEY (`roleFk`) REFERENCES `account`.`role` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; diff --git a/modules/account/front/alias/acl/create/index.js b/modules/account/front/alias/acl/create/index.js new file mode 100644 index 000000000..1f9d73272 --- /dev/null +++ b/modules/account/front/alias/acl/create/index.js @@ -0,0 +1,33 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor(...args) { + super(...args); + this.accessTypes = [ + {name: '*'}, + {name: 'READ'}, + {name: 'WRITE'} + ]; + this.permissions = [ + {name: 'ALLOW'}, + {name: 'DENY'} + ]; + + this.models = []; + for (let model in window.validations) + this.models.push({name: model}); + + this.acl = { + property: '*', + principalType: 'ROLE', + accessType: 'READ', + permission: 'ALLOW' + }; + } +} + +ngModule.component('vnAclMailCreate', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/account/front/alias/acl/index.js b/modules/account/front/alias/acl/index.js new file mode 100644 index 000000000..8393859a5 --- /dev/null +++ b/modules/account/front/alias/acl/index.js @@ -0,0 +1,4 @@ +import './main'; +import './index/'; +import './create'; +import './search-panel'; diff --git a/modules/account/front/alias/acl/index/index.js b/modules/account/front/alias/acl/index/index.js new file mode 100644 index 000000000..b78dfa7f5 --- /dev/null +++ b/modules/account/front/alias/acl/index/index.js @@ -0,0 +1,15 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + onDelete(row) { + return this.$http.delete(`ACLs/${row.id}`) + .then(() => this.$.model.refresh()) + .then(() => this.vnApp.showSuccess(this.$t('ACL removed'))); + } +} + +ngModule.component('vnAclMailIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/account/front/alias/acl/main/index.js b/modules/account/front/alias/acl/main/index.js new file mode 100644 index 000000000..431ef48c5 --- /dev/null +++ b/modules/account/front/alias/acl/main/index.js @@ -0,0 +1,18 @@ +import ngModule from '../../module'; +import ModuleMain from 'salix/components/module-main'; + +export default class ACL extends ModuleMain { + exprBuilder(param, value) { + switch (param) { + case 'search': + return {model: {like: `%${value}%`}}; + default: + return {[param]: value}; + } + } +} + +ngModule.vnComponent('vnAclMailComponent', { + controller: ACL, + template: require('./index.html') +}); From e548ef4dae1d056cfc2f34396a3e3e164ee2b9a8 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 29 Nov 2023 07:51:58 +0100 Subject: [PATCH 17/87] refs #6085 searchpanel and change path --- .../account/front/alias/acl/create/index.js | 4 +-- .../account/front/alias/acl/index/index.js | 4 +-- modules/account/front/alias/acl/main/index.js | 6 ++--- .../front/alias/acl/search-panel/index.js | 26 +++++++++++++++++++ modules/account/front/alias/index.js | 1 + 5 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 modules/account/front/alias/acl/search-panel/index.js diff --git a/modules/account/front/alias/acl/create/index.js b/modules/account/front/alias/acl/create/index.js index 1f9d73272..58e70e4aa 100644 --- a/modules/account/front/alias/acl/create/index.js +++ b/modules/account/front/alias/acl/create/index.js @@ -1,4 +1,4 @@ -import ngModule from '../../module'; +import ngModule from '../../../module'; import Section from 'salix/components/section'; export default class Controller extends Section { @@ -28,6 +28,6 @@ export default class Controller extends Section { } ngModule.component('vnAclMailCreate', { - template: require('./index.html'), + // template: require('./index.html'), controller: Controller }); diff --git a/modules/account/front/alias/acl/index/index.js b/modules/account/front/alias/acl/index/index.js index b78dfa7f5..5d8d49574 100644 --- a/modules/account/front/alias/acl/index/index.js +++ b/modules/account/front/alias/acl/index/index.js @@ -1,4 +1,4 @@ -import ngModule from '../../module'; +import ngModule from '../../../module'; import Section from 'salix/components/section'; export default class Controller extends Section { @@ -10,6 +10,6 @@ export default class Controller extends Section { } ngModule.component('vnAclMailIndex', { - template: require('./index.html'), + // template: require('./index.html'), controller: Controller }); diff --git a/modules/account/front/alias/acl/main/index.js b/modules/account/front/alias/acl/main/index.js index 431ef48c5..97f04ee50 100644 --- a/modules/account/front/alias/acl/main/index.js +++ b/modules/account/front/alias/acl/main/index.js @@ -1,4 +1,4 @@ -import ngModule from '../../module'; +import ngModule from '../../../module'; import ModuleMain from 'salix/components/module-main'; export default class ACL extends ModuleMain { @@ -13,6 +13,6 @@ export default class ACL extends ModuleMain { } ngModule.vnComponent('vnAclMailComponent', { - controller: ACL, - template: require('./index.html') + controller: ACL + // template: require('./index.html') }); diff --git a/modules/account/front/alias/acl/search-panel/index.js b/modules/account/front/alias/acl/search-panel/index.js new file mode 100644 index 000000000..67db33383 --- /dev/null +++ b/modules/account/front/alias/acl/search-panel/index.js @@ -0,0 +1,26 @@ +import ngModule from '../../../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; + +export default class Controller extends SearchPanel { + constructor(...args) { + super(...args); + this.accessTypes = [ + {name: '*'}, + {name: 'READ'}, + {name: 'WRITE'} + ]; + this.permissions = [ + {name: 'ALLOW'}, + {name: 'DENY'} + ]; + + this.models = []; + for (let model in window.validations) + this.models.push({name: model}); + } +} + +ngModule.component('vnAclSearchPanel', { + // template: require('./index.html'), + controller: Controller +}); diff --git a/modules/account/front/alias/index.js b/modules/account/front/alias/index.js index 8eed3a3d3..598421749 100644 --- a/modules/account/front/alias/index.js +++ b/modules/account/front/alias/index.js @@ -7,3 +7,4 @@ import './descriptor'; import './create'; import './basic-data'; import './users'; +import './acl'; From 48dd068190e20819d9906b8212c5f1c74b58e00d Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 29 Nov 2023 08:37:56 +0100 Subject: [PATCH 18/87] refs #6274 upperCase Model --- db/changes/235001/00-timecontrol.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/changes/235001/00-timecontrol.sql b/db/changes/235001/00-timecontrol.sql index ac7dc85d6..4e350b002 100644 --- a/db/changes/235001/00-timecontrol.sql +++ b/db/changes/235001/00-timecontrol.sql @@ -6,8 +6,8 @@ INSERT INTO `account`.`roleInherit` (role, inheritsFrom) INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) VALUES - ('workerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', '*'), - ('workerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', '*'), - ('workerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', '*'); + ('WorkerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', 'timeControl'), + ('WorkerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', 'timeControl'), + ('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); CALL `account`.`role_sync`(); From 9a3efdd6fe9e29cf0dd6ca97c8c384e26bd99a53 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 29 Nov 2023 13:55:44 +0100 Subject: [PATCH 19/87] refs #6085 model y back --- modules/account/back/models/mail-alias-acl.js | 70 +++++++++++++++++++ .../account/back/models/mail-alias-acl.json | 29 ++++++++ 2 files changed, 99 insertions(+) create mode 100644 modules/account/back/models/mail-alias-acl.js create mode 100644 modules/account/back/models/mail-alias-acl.json diff --git a/modules/account/back/models/mail-alias-acl.js b/modules/account/back/models/mail-alias-acl.js new file mode 100644 index 000000000..4a74472fe --- /dev/null +++ b/modules/account/back/models/mail-alias-acl.js @@ -0,0 +1,70 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + require('../methods/notification/getList')(Self); + + Self.observe('before save', async function(ctx) { + await checkModifyPermission(ctx); + }); + + Self.observe('before delete', async function(ctx) { + await checkModifyPermission(ctx); + }); + + async function checkModifyPermission(ctx) { + const models = Self.app.models; + const instance = ctx.instance; + const userId = ctx.options.accessToken.userId; + + let mailAliasFk; + let roleFk; + + if (instance) { + mailAliasFk = instance.mailAliasFk; + roleFk = instance.roleFk; + } else { + const mailAliasAcl = await models.MailAlias.findById(ctx.where.id); + mailAliasFk = mailAliasAcl.id; + roleFk = mailAliasAcl.roleFk; + } + + const role = await models.VnUser.findById(roleFk, {fields: ['id', 'role']}); + const available = await Self.getAvailable(roleFk); + const hasAcl = available.has(mailAliasFk); + + if (!hasAcl || (userId.role != role)) + throw new UserError('The alias cant be modified'); + } + + Self.getAvailable = async function(userId, options) { + const availableMailAliasMap = new Map(); + const models = Self.app.models; + + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const roles = await models.RoleMapping.find({ + fields: ['roleId'], + where: {principalId: userId} + }, myOptions); + + const availableMailAlias = await models.MailAliasAcl.find({ + fields: ['mailAliasFk', 'roleFk'], + include: {relation: 'roleFk'}, + where: { + roleFk: { + inq: roles.map(role => role.roleId), + }, + } + }, myOptions); + + for (available of availableMailAlias) { + availableMailAliasMap.set(available.mailAliasFk, { + mailAliasFk: available.mailAliasFk, + }); + } + return availableMailAliasMap; + }; +}; diff --git a/modules/account/back/models/mail-alias-acl.json b/modules/account/back/models/mail-alias-acl.json new file mode 100644 index 000000000..2e44f38eb --- /dev/null +++ b/modules/account/back/models/mail-alias-acl.json @@ -0,0 +1,29 @@ +{ + "name": "mailAliasACL", + "base": "VnModel", + "options": { + "mysql": { + "table": "account.mailAliasACL" + } + }, + "properties": { + "mailAliasFk": { + "type": "number" + }, + "roleFk": { + "type": "number" + } + }, + "relations": { + "mailAlias": { + "type": "belongsTo", + "model": "VnUser", + "foreignKey": "mailAliasFk" + }, + "role": { + "type": "belongsTo", + "model": "VnUser", + "foreignKey": "roleFk" + } + } +} From 16001099b61adc0d297f88c204e0748e5c3ee57f Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 30 Nov 2023 12:15:48 +0100 Subject: [PATCH 20/87] refs #5666 feat: update ACLs for role and vnRole --- db/changes/235001/00-updateACL_Role_VnRole.sql | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 db/changes/235001/00-updateACL_Role_VnRole.sql diff --git a/db/changes/235001/00-updateACL_Role_VnRole.sql b/db/changes/235001/00-updateACL_Role_VnRole.sql new file mode 100644 index 000000000..0b1083991 --- /dev/null +++ b/db/changes/235001/00-updateACL_Role_VnRole.sql @@ -0,0 +1,8 @@ +-- Auto-generated SQL script #202311301038 +INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) + VALUES ('VnRole','*','*','ALLOW','ROLE','$everyone'); +INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) + VALUES ('VnRole','*','*','ALLOW','ROLE','employee'); + +-- Auto-generated SQL script #202311301203 +UPDATE `salix`.`ACL` SET permission='DENY' WHERE model='Role'; From 01e713522415ac0710145f802eb0e8b9384cadbb Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 30 Nov 2023 12:20:05 +0100 Subject: [PATCH 21/87] refs #5666 feat: replace Role by VnRole in front --- modules/account/front/acl/create/index.html | 4 ++-- modules/account/front/acl/search-panel/index.html | 6 +++--- modules/account/front/create/index.html | 2 +- modules/account/front/privileges/index.html | 2 +- modules/account/front/role/basic-data/index.html | 8 ++++---- modules/account/front/role/card/index.js | 2 +- modules/account/front/role/create/index.html | 6 +++--- modules/account/front/role/descriptor/index.js | 2 +- modules/account/front/role/main/index.html | 4 ++-- modules/account/front/role/subroles/index.html | 6 +++--- modules/account/front/role/summary/index.js | 2 +- modules/account/front/search-panel/index.html | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/modules/account/front/acl/create/index.html b/modules/account/front/acl/create/index.html index 7f4fa9e46..14332f737 100644 --- a/modules/account/front/acl/create/index.html +++ b/modules/account/front/acl/create/index.html @@ -15,7 +15,7 @@ @@ -32,7 +32,7 @@ diff --git a/modules/account/front/acl/search-panel/index.html b/modules/account/front/acl/search-panel/index.html index b83b9c255..a3efab440 100644 --- a/modules/account/front/acl/search-panel/index.html +++ b/modules/account/front/acl/search-panel/index.html @@ -4,7 +4,7 @@ - \ No newline at end of file + diff --git a/modules/account/front/create/index.html b/modules/account/front/create/index.html index acc07d346..70a518885 100644 --- a/modules/account/front/create/index.html +++ b/modules/account/front/create/index.html @@ -30,7 +30,7 @@ + url="VnRoles"> diff --git a/modules/account/front/role/basic-data/index.html b/modules/account/front/role/basic-data/index.html index 749927186..a6d39f3e3 100644 --- a/modules/account/front/role/basic-data/index.html +++ b/modules/account/front/role/basic-data/index.html @@ -1,6 +1,6 @@ @@ -11,13 +11,13 @@ @@ -35,4 +35,4 @@ ng-click="watcher.loadOriginalData()"> - \ No newline at end of file + diff --git a/modules/account/front/role/card/index.js b/modules/account/front/role/card/index.js index 6f888211d..3c7c758ef 100644 --- a/modules/account/front/role/card/index.js +++ b/modules/account/front/role/card/index.js @@ -3,7 +3,7 @@ import ModuleCard from 'salix/components/module-card'; class Controller extends ModuleCard { reload() { - this.$http.get(`Roles/${this.$params.id}`) + this.$http.get(`VnRoles/${this.$params.id}`) .then(res => this.role = res.data); } } diff --git a/modules/account/front/role/create/index.html b/modules/account/front/role/create/index.html index 02900d580..b747f7d00 100644 --- a/modules/account/front/role/create/index.html +++ b/modules/account/front/role/create/index.html @@ -1,6 +1,6 @@ @@ -12,13 +12,13 @@ diff --git a/modules/account/front/role/descriptor/index.js b/modules/account/front/role/descriptor/index.js index a1b578133..17b585cb7 100644 --- a/modules/account/front/role/descriptor/index.js +++ b/modules/account/front/role/descriptor/index.js @@ -11,7 +11,7 @@ class Controller extends Descriptor { } onDelete() { - return this.$http.delete(`Roles/${this.id}`) + return this.$http.delete(`VnRoles/${this.id}`) .then(() => this.$state.go('account.role')) .then(() => this.vnApp.showSuccess(this.$t('Role removed'))); } diff --git a/modules/account/front/role/main/index.html b/modules/account/front/role/main/index.html index 9d7e6e053..cfef28e57 100644 --- a/modules/account/front/role/main/index.html +++ b/modules/account/front/role/main/index.html @@ -1,6 +1,6 @@ @@ -15,4 +15,4 @@ - \ No newline at end of file + diff --git a/modules/account/front/role/subroles/index.html b/modules/account/front/role/subroles/index.html index bc554b9f9..eba1002b0 100644 --- a/modules/account/front/role/subroles/index.html +++ b/modules/account/front/role/subroles/index.html @@ -33,14 +33,14 @@ ng-click="$ctrl.onAddClick()" fixed-bottom-right> - @@ -49,7 +49,7 @@ - this.$.summary = res.data); } diff --git a/modules/account/front/search-panel/index.html b/modules/account/front/search-panel/index.html index f80b537aa..a539d9657 100644 --- a/modules/account/front/search-panel/index.html +++ b/modules/account/front/search-panel/index.html @@ -19,7 +19,7 @@ vn-one label="Role" ng-model="filter.roleFk" - url="Roles" + url="VnRoles" value-field="id" show-field="name"> @@ -28,4 +28,4 @@ - \ No newline at end of file + From e634a5e2139d8f948d9478f668e12b7c97a5b884 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 30 Nov 2023 15:15:40 +0100 Subject: [PATCH 22/87] refs #5914 feat: create getTaxBases and use in negatives and positives procedures --- db/changes/235001/00-getTaxBases.sql | 33 +++++++++++++++++++ .../235001/01-newHasAnyPositiveBase.sql | 28 ++++++++++++++++ .../235001/01-refactorHasAnyNegativeBase.sql | 28 ++++++++++++++++ db/dump/fixtures.sql | 13 ++++---- 4 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 db/changes/235001/00-getTaxBases.sql create mode 100644 db/changes/235001/01-newHasAnyPositiveBase.sql create mode 100644 db/changes/235001/01-refactorHasAnyNegativeBase.sql diff --git a/db/changes/235001/00-getTaxBases.sql b/db/changes/235001/00-getTaxBases.sql new file mode 100644 index 000000000..fa43c32f7 --- /dev/null +++ b/db/changes/235001/00-getTaxBases.sql @@ -0,0 +1,33 @@ +DELIMITER $$ +$$ +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`getTaxBases`() +BEGIN + +/* Calcula y devuelve en número de bases imponibles postivas y negativas +* Requiere la tabla temporal tmp.ticketToInvoice(id) +* +* returns tmp.taxBases +*/ + + CREATE OR REPLACE TEMPORARY TABLE tmp.ticket + (KEY (ticketFk)) + ENGINE = MEMORY + SELECT id ticketFk + FROM tmp.ticketToInvoice; + + CALL ticket_getTax(NULL); + + DROP TEMPORARY TABLE IF EXISTS tmp.taxBases; + CREATE TEMPORARY TABLE tmp.taxBases + ENGINE = MEMORY + SELECT + SUM(CASE WHEN taxableBase > 0 THEN 1 ELSE 0 END) as positive, + SUM(CASE WHEN taxableBase < 0 THEN 1 ELSE 0 END) as negative + FROM( + SELECT SUM(taxableBase) as taxableBase + FROM tmp.ticketTax + GROUP BY pgcFk + ) t; + +END$$ +DELIMITER ; diff --git a/db/changes/235001/01-newHasAnyPositiveBase.sql b/db/changes/235001/01-newHasAnyPositiveBase.sql new file mode 100644 index 000000000..c9e7e8e05 --- /dev/null +++ b/db/changes/235001/01-newHasAnyPositiveBase.sql @@ -0,0 +1,28 @@ +DELIMITER $$ +$$ +CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`hasAnyPositiveBase`() RETURNS tinyint(1) + DETERMINISTIC +BEGIN + +/* Calcula si existe alguna base imponible positiva +* Requiere la tabla temporal tmp.ticketToInvoice(id) para getTaxBases() +* +* returns BOOLEAN +*/ + + DECLARE hasAnyPositiveBase BOOLEAN; + + CALL getTaxBases(); + + SELECT positive > 0 INTO hasAnyPositiveBase + FROM tmp.taxBases; + + DROP TEMPORARY TABLE + tmp.ticketTax, + tmp.ticket, + tmp.taxBases; + + RETURN hasAnyPositiveBase; + +END$$ +DELIMITER ; diff --git a/db/changes/235001/01-refactorHasAnyNegativeBase.sql b/db/changes/235001/01-refactorHasAnyNegativeBase.sql new file mode 100644 index 000000000..b6780e280 --- /dev/null +++ b/db/changes/235001/01-refactorHasAnyNegativeBase.sql @@ -0,0 +1,28 @@ +DELIMITER $$ +$$ +CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`hasAnyNegativeBase`() RETURNS tinyint(1) + DETERMINISTIC +BEGIN + +/* Calcula si existe alguna base imponible negativa +* Requiere la tabla temporal tmp.ticketToInvoice(id) para getTaxBases() +* +* returns BOOLEAN +*/ + + DECLARE hasAnyNegativeBase BOOLEAN; + + CALL getTaxBases(); + + SELECT negative > 0 INTO hasAnyNegativeBase + FROM tmp.taxBases; + + DROP TEMPORARY TABLE + tmp.ticketTax, + tmp.ticket, + tmp.taxBases; + + RETURN hasAnyNegativeBase; + +END$$ +DELIMITER ; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 788487ed0..ed0a30d14 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -598,18 +598,19 @@ INSERT INTO `vn`.`taxArea` (`code`, `claveOperacionFactura`, `CodigoTransaccion` INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaFk`, `isCEE`, `type`) VALUES - ('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'), - ('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'), - ('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'), - ('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'), - ('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick'); + ('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'), + ('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'), + ('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'), + ('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'), + ('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL), + ('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick'); INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) VALUES (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (4, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), + (4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0); UPDATE `vn`.`invoiceOut` SET ref = 'T1111111' WHERE id = 1; From b2e7ea3089b24acfbc1dfbde612cbe7ee36940b5 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 30 Nov 2023 15:16:41 +0100 Subject: [PATCH 23/87] refs #5914 feat: make invoice support rectificative --- loopback/locale/es.json | 3 ++- .../back/methods/client/canBeInvoiced.js | 2 +- .../back/methods/invoiceOut/invoiceClient.js | 1 + .../invoiceOut/specs/transferinvoice.spec.js | 23 +++++++++++----- .../methods/invoiceOut/transferInvoice.js | 8 +++--- .../invoiceOut/front/descriptor-menu/index.js | 2 +- .../back/methods/sale/specs/refund.spec.js | 8 +++--- .../back/methods/ticket/canBeInvoiced.js | 16 ++++++++---- .../back/methods/ticket/invoiceTickets.js | 1 - .../ticket/back/methods/ticket/makeInvoice.js | 26 +++++++++++-------- .../ticket/specs/canBeInvoiced.spec.js | 8 +++--- .../ticket/specs/invoiceTickets.spec.js | 10 +++---- .../methods/ticket/specs/makeInvoice.spec.js | 4 +-- modules/ticket/front/descriptor-menu/index.js | 2 +- .../front/descriptor-menu/index.spec.js | 5 ++-- modules/ticket/front/sale/index.js | 2 +- modules/ticket/front/sale/index.spec.js | 2 +- 17 files changed, 72 insertions(+), 51 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 41acc36c3..71e0dc6af 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -328,5 +328,6 @@ "User disabled": "Usuario desactivado", "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", "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" + "Cannot past travels with entries": "No se pueden pasar envíos con entradas", + "No tickets to invoice": "No hay tickets para facturar" } diff --git a/modules/client/back/methods/client/canBeInvoiced.js b/modules/client/back/methods/client/canBeInvoiced.js index 843e9549f..cdb865500 100644 --- a/modules/client/back/methods/client/canBeInvoiced.js +++ b/modules/client/back/methods/client/canBeInvoiced.js @@ -1,7 +1,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self) { - Self.remoteMethodCtx('canBeInvoiced', { + Self.remoteMethod('canBeInvoiced', { description: 'Change property isEqualizated in all client addresses', accessType: 'READ', accepts: [ diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index fa22dab1e..530b02353 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -80,6 +80,7 @@ module.exports = Self => { invoiceType, args.companyFk, args.invoiceDate, + null, options ); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js index dea4b6d00..b3bd17826 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js @@ -23,20 +23,29 @@ describe('InvoiceOut tranferInvoice()', () => { const tx = await models.InvoiceOut.beginTransaction({}); const options = {transaction: tx}; const args = { - id: '1', + id: '4', refFk: 'T4444444', newClientFk: 1, - cplusRectificationId: 1, - siiTypeInvoiceOutId: 1, - invoiceCorrectionTypeId: 1 + cplusRectificationTypeFk: 1, + siiTypeInvoiceOutFk: 1, + invoiceCorrectionTypeFk: 1 }; ctx.args = args; try { + const {clientFk: oldClient} = await models.InvoiceOut.findById(args.id, {fields: ['clientFk']}); + const invoicesBefore = await models.InvoiceOut.find({}, options); const result = await models.InvoiceOut.transferInvoice( ctx, options); + const invoicesAfter = await models.InvoiceOut.find({}, options); + const rectificativeInvoice = invoicesAfter[invoicesAfter.length - 2]; + const newInvoice = invoicesAfter[invoicesAfter.length - 1]; expect(result).toBeDefined(); + expect(invoicesAfter.length - invoicesBefore.length).toEqual(2); + expect(rectificativeInvoice.clientFk).toEqual(oldClient); + expect(newInvoice.clientFk).toEqual(args.newClientFk); + await tx.rollback(); } catch (e) { await tx.rollback(); @@ -51,9 +60,9 @@ describe('InvoiceOut tranferInvoice()', () => { id: '1', refFk: 'T1111111', newClientFk: 1101, - cplusRectificationId: 1, - siiTypeInvoiceOutId: 1, - invoiceCorrectionTypeId: 1 + cplusRectificationTypeFk: 1, + siiTypeInvoiceOutFk: 1, + invoiceCorrectionTypeFk: 1 }; ctx.args = args; try { diff --git a/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js index dcdd9b9b1..5f2428539 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js @@ -22,7 +22,7 @@ module.exports = Self => { required: true }, { - arg: 'cplusRectificationFk', + arg: 'cplusRectificationTypeFk', type: 'number', required: true }, @@ -50,7 +50,7 @@ module.exports = Self => { Self.transferInvoice = async(ctx, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; - const {id, refFk, newClientFk, cplusRectificationFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk} = ctx.args; + const {id, refFk, newClientFk, cplusRectificationTypeFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk} = ctx.args; let tx; if (typeof options == 'object') Object.assign(myOptions, options); @@ -87,11 +87,11 @@ module.exports = Self => { } const invoiceCorrection = - {correctedFk: id, cplusRectificationFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk}; + {correctedFk: id, cplusRectificationTypeFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk}; const refundTicketIds = refundTickets.map(ticket => ticket.id); await models.Ticket.invoiceTickets(ctx, refundTicketIds, invoiceCorrection, myOptions); - const [[invoiceId]] = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions); + const [invoiceId] = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, null, myOptions); if (tx) { await tx.commit(); diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js index f9d436092..aee323e39 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.js +++ b/modules/invoiceOut/front/descriptor-menu/index.js @@ -131,7 +131,7 @@ class Controller extends Section { id: this.invoiceOut.id, refFk: this.invoiceOut.ref, newClientFk: this.clientId, - cplusRectificationFk: this.cplusRectificationType, + cplusRectificationTypeFk: this.cplusRectificationType, siiTypeInvoiceOutFk: this.siiTypeInvoiceOut, invoiceCorrectionTypeFk: this.invoiceCorrectionType }; diff --git a/modules/ticket/back/methods/sale/specs/refund.spec.js b/modules/ticket/back/methods/sale/specs/refund.spec.js index 08eb1fabd..60f77e90c 100644 --- a/modules/ticket/back/methods/sale/specs/refund.spec.js +++ b/modules/ticket/back/methods/sale/specs/refund.spec.js @@ -23,9 +23,9 @@ describe('Sale refund()', () => { try { const options = {transaction: tx}; - const refundedTicket = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); + const refundedTickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); - expect(refundedTicket).toBeDefined(); + expect(refundedTickets).toBeDefined(); await tx.rollback(); } catch (e) { @@ -42,11 +42,11 @@ describe('Sale refund()', () => { const options = {transaction: tx}; const ticketsBefore = await models.Ticket.find({}, options); - const ticket = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); + const tickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); const refundedTicket = await models.Ticket.findOne({ where: { - id: ticket.id + id: tickets[0].id }, include: [ { diff --git a/modules/ticket/back/methods/ticket/canBeInvoiced.js b/modules/ticket/back/methods/ticket/canBeInvoiced.js index 348f02348..fe7223c17 100644 --- a/modules/ticket/back/methods/ticket/canBeInvoiced.js +++ b/modules/ticket/back/methods/ticket/canBeInvoiced.js @@ -10,6 +10,11 @@ module.exports = function(Self) { description: 'The tickets id', type: ['number'], required: true + }, + { + arg: 'isRectificative', + description: 'If it is rectificative', + type: 'boolean' } ], returns: { @@ -23,7 +28,7 @@ module.exports = function(Self) { } }); - Self.canBeInvoiced = async(ctx, ticketsIds, options) => { + Self.canBeInvoiced = async(ctx, ticketsIds, isRectificative, options) => { const myOptions = {}; const $t = ctx.req.__; // $translate @@ -48,10 +53,11 @@ module.exports = function(Self) { const [supplierCompany] = await Self.rawSql(query, [companyFk], options); const isSpanishCompany = supplierCompany?.isSpanishCompany; - - const [result] = await Self.rawSql('SELECT hasAnyNegativeBase() AS base', null, options); - const hasAnyNegativeBase = result?.base && isSpanishCompany; - if (hasAnyNegativeBase) + const taxBaseFunction = isRectificative ? 'hasAnyPositiveBase' : 'hasAnyNegativeBase'; + const [result] = + await Self.rawSql(`SELECT ?() AS hasBasesProblem`, [taxBaseFunction], options); + const hasAnyIncorrectBase = result?.hasBasesProblem && isSpanishCompany; + if (hasAnyIncorrectBase) throw new UserError($t('Negative basis of tickets', {ticketsIds: ticketsIds})); const today = Date.vnNew(); diff --git a/modules/ticket/back/methods/ticket/invoiceTickets.js b/modules/ticket/back/methods/ticket/invoiceTickets.js index 29fb1769b..212f6556a 100644 --- a/modules/ticket/back/methods/ticket/invoiceTickets.js +++ b/modules/ticket/back/methods/ticket/invoiceTickets.js @@ -93,7 +93,6 @@ module.exports = function(Self) { async function createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, invoiceCorrection, myOptions) { const models = Self.app.models; - console.log(ticketsIds, address); await models.Ticket.rawSql(` CREATE OR REPLACE TEMPORARY TABLE tmp.ticketToInvoice (PRIMARY KEY (id)) diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index 6f1586c2b..fe7e527c8 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -67,20 +67,24 @@ module.exports = function(Self) { fields: ['id', 'clientFk', 'addressFk'] }, myOptions); - await models.Ticket.canBeInvoiced(ctx, ticketsIds, myOptions); + await models.Ticket.canBeInvoiced(ctx, ticketsIds, !!invoiceCorrection, myOptions); const [firstTicket] = tickets; const clientId = firstTicket.clientFk; - const clientCanBeInvoiced = await models.Client.canBeInvoiced(clientId, companyFk, invoiceCorrection, myOptions); - if (!clientCanBeInvoiced && !invoiceCorrection) + const clientCanBeInvoiced = + await models.Client.canBeInvoiced(clientId, companyFk, myOptions); + + if (!clientCanBeInvoiced) throw new UserError(`This client can't be invoiced`); - const query = `SELECT vn.invoiceSerial(?, ?, ?) AS serial`; - const [{serial}] = await Self.rawSql(query, [ - clientId, - companyFk, - invoiceType, - ], myOptions); + const [{serial}] = invoiceCorrection ? [{serial: 'R'}] : await Self.rawSql( + `SELECT vn.invoiceSerial(?, ?, ?) AS serial`, + [ + clientId, + companyFk, + invoiceType + ], + myOptions); const invoiceOutSerial = await models.InvoiceOutSerial.findById(serial); if (invoiceOutSerial?.taxAreaFk == 'WORLD') { @@ -92,7 +96,7 @@ module.exports = function(Self) { await Self.rawSql('CALL invoiceOut_new(?, ?, null, @invoiceId)', [serial, invoiceDate], myOptions); const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions); - if (!resultInvoice) + if (!resultInvoice?.id) throw new UserError('No tickets to invoice', 'notInvoiced'); if (invoiceCorrection) { @@ -102,7 +106,7 @@ module.exports = function(Self) { ); } - if (serial != 'R' && resultInvoice.id) + if (resultInvoice.id) // serial != 'R' && await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions); if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js index 538dbc49f..e443ed6d3 100644 --- a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js +++ b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js @@ -27,7 +27,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(false); @@ -59,7 +59,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(false); @@ -95,7 +95,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(false); @@ -123,7 +123,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(true); diff --git a/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js b/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js index 8971fb24a..162dc066a 100644 --- a/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js +++ b/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js @@ -31,7 +31,7 @@ describe('ticket invoiceTickets()', () => { const options = {transaction: tx}; const ticketsIds = [11, 16]; - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); await tx.rollback(); } catch (e) { @@ -57,7 +57,7 @@ describe('ticket invoiceTickets()', () => { await client.updateAttribute('isTaxDataChecked', false, options); const ticketsIds = [11]; - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); await tx.rollback(); } catch (e) { @@ -80,8 +80,8 @@ describe('ticket invoiceTickets()', () => { const options = {transaction: tx}; const ticketsIds = [11]; - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); await tx.rollback(); } catch (e) { @@ -102,7 +102,7 @@ describe('ticket invoiceTickets()', () => { const options = {transaction: tx}; const ticketsIds = [11]; - const invoicesIds = await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + const invoicesIds = await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); expect(invoicesIds.length).toBeGreaterThan(0); diff --git a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js index 9b1fd8f6f..456303602 100644 --- a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js +++ b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js @@ -42,7 +42,7 @@ describe('ticket makeInvoice()', () => { WHERE id IN (?) `, [ticketsIds], options); - const invoiceId = await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, options); + const invoiceId = await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, null, options); expect(invoiceId).toBeDefined(); @@ -70,7 +70,7 @@ describe('ticket makeInvoice()', () => { WHERE id IN (?) `, [ticketsId], options); - await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, options); + await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, null, options); await tx.rollback(); } catch (e) { error = e; diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 18db8c147..cd819e623 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -292,7 +292,7 @@ class Controller extends Section { const query = 'Tickets/refund'; return this.$http.post(query, params) .then(res => { - const refundTicket = res.data; + const [refundTicket] = res.data; this.vnApp.showSuccess(this.$t('The following refund ticket have been created', { ticketId: refundTicket.id })); diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index 1bb270165..c755b14c3 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -262,11 +262,12 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { const params = { ticketsIds: [16] }; - $httpBackend.expectPOST('Tickets/refund', params).respond({id: 99}); + const response = {id: 99}; + $httpBackend.expectPOST('Tickets/refund', params).respond([response]); controller.refund(); $httpBackend.flush(); - expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', {id: 99}); + expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', response); }); }); diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index 4f6a9e757..ed6d9b10a 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -526,7 +526,7 @@ class Controller extends Section { const params = {salesIds: salesIds, withWarehouse: withWarehouse}; const query = 'Sales/refund'; this.$http.post(query, params).then(res => { - const refundTicket = res.data; + const [refundTicket] = res.data; this.vnApp.showSuccess(this.$t('The following refund ticket have been created', { ticketId: refundTicket.id })); diff --git a/modules/ticket/front/sale/index.spec.js b/modules/ticket/front/sale/index.spec.js index 70781eb58..36be32f52 100644 --- a/modules/ticket/front/sale/index.spec.js +++ b/modules/ticket/front/sale/index.spec.js @@ -729,7 +729,7 @@ describe('Ticket', () => { salesIds: [1, 4], }; const refundTicket = {id: 99}; - $httpBackend.expect('POST', 'Sales/refund', params).respond(200, refundTicket); + $httpBackend.expect('POST', 'Sales/refund', params).respond(200, [refundTicket]); controller.createRefund(); $httpBackend.flush(); From 6d486fbec99ae2b471882a2b24530b5b34453f06 Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 1 Dec 2023 13:58:45 +0100 Subject: [PATCH 24/87] refs #6085 trad, remove front, back test --- back/models/specs/mailAliasAccount.spec.js | 73 +++++++++++++++++++ db/changes/235001/00-aclsMails.sql | 3 +- db/dump/fixtures.sql | 7 ++ front/core/locale/es.yml | 1 + loopback/locale/es.json | 4 +- modules/account/back/model-config.json | 3 + .../account/back/models/mail-alias-account.js | 68 ++++++++--------- modules/account/back/models/mail-alias-acl.js | 59 ++++++--------- .../account/back/models/mail-alias-acl.json | 10 ++- .../account/front/alias/acl/create/index.js | 33 --------- modules/account/front/alias/acl/index.js | 4 - .../account/front/alias/acl/index/index.js | 15 ---- modules/account/front/alias/acl/main/index.js | 18 ----- .../front/alias/acl/search-panel/index.js | 26 ------- modules/account/front/alias/index.js | 1 - 15 files changed, 151 insertions(+), 174 deletions(-) create mode 100644 back/models/specs/mailAliasAccount.spec.js delete mode 100644 modules/account/front/alias/acl/create/index.js delete mode 100644 modules/account/front/alias/acl/index.js delete mode 100644 modules/account/front/alias/acl/index/index.js delete mode 100644 modules/account/front/alias/acl/main/index.js delete mode 100644 modules/account/front/alias/acl/search-panel/index.js diff --git a/back/models/specs/mailAliasAccount.spec.js b/back/models/specs/mailAliasAccount.spec.js new file mode 100644 index 000000000..46d447f90 --- /dev/null +++ b/back/models/specs/mailAliasAccount.spec.js @@ -0,0 +1,73 @@ +const models = require('vn-loopback/server/server').models; + +fdescribe('loopback model MailAliasAccount', () => { + it('should fail to add a mail Alias if the worker doesnt have ACLs', async() => { + const tx = await models.MailAliasAccount.beginTransaction({}); + let error; + + try { + const options = {transaction: tx, accessToken: {userId: 1}}; + await models.MailAliasAccount.create({mailAliasFk: 2, roleFk: 5}, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toEqual('The alias cant be modified'); + }); + + it('should add a mail Alias', async() => { + const tx = await models.MailAliasAccount.beginTransaction({}); + let error; + + try { + const options = {transaction: tx, accessToken: {userId: 9}}; + await models.MailAliasAccount.create({mailAliasFk: 2, roleFk: 5}, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).toBeUndefined(); + }); + + it('should add a mail Alias of an inherit role', async() => { + const tx = await models.MailAliasAccount.beginTransaction({}); + let error; + + try { + const options = {transaction: tx, accessToken: {userId: 9}}; + await models.MailAliasAccount.create({mailAliasFk: 3, roleFk: 5}, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).toBeUndefined(); + }); + + it('should delete a mail Alias', async() => { + const tx = await models.MailAliasAccount.beginTransaction({}); + let error; + + try { + const options = {transaction: tx, accessToken: {userId: 1}}; + const mailAclId = 2; + await models.MailAliasAccount.destroyAll({id: mailAclId}, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).toBeUndefined(); + }); +}); + diff --git a/db/changes/235001/00-aclsMails.sql b/db/changes/235001/00-aclsMails.sql index 92603aec4..5cfea4030 100644 --- a/db/changes/235001/00-aclsMails.sql +++ b/db/changes/235001/00-aclsMails.sql @@ -1,5 +1,6 @@ -- Definición de la tabla mailAliasACL -CREATE TABLE `account`.`mailAliasACL` ( + +CREATE OR REPLACE TABLE `account`.`mailAliasAcl` ( `mailAliasFk` int(10) unsigned NOT NULL, `roleFk` int(10) unsigned NOT NULL, FOREIGN KEY (`mailAliasFk`) REFERENCES `account`.`mailAlias` (`id`), diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 93b7b796f..62f96b459 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -3002,3 +3002,10 @@ INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`) (1, 'Error in VAT calculation'), (2, 'Error in sales details'), (3, 'Error in customer data'); + +INSERT INTO `account`.`mailAliasAcl` (`mailAliasFk`, `roleFk`) + VALUES + (1, 1), + (2, 9), + (3, 15); + diff --git a/front/core/locale/es.yml b/front/core/locale/es.yml index 96c34d98c..1b9bbb40b 100644 --- a/front/core/locale/es.yml +++ b/front/core/locale/es.yml @@ -68,3 +68,4 @@ Load more results: Cargar más resultados Send cau: Enviar cau By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc ExplainReason: Explique el motivo por el que no deberia aparecer este fallo +You already have the mailAlias: Ya tienes este mail diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 01384efb4..2e516bf12 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -329,5 +329,7 @@ "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", "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}}" + "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", + "You already have the mailAlias": "You already have the mailAlias", + "The alias cant be modified": "The alias cant be modified" } \ No newline at end of file diff --git a/modules/account/back/model-config.json b/modules/account/back/model-config.json index b4bd6dbaf..0cd43d0ce 100644 --- a/modules/account/back/model-config.json +++ b/modules/account/back/model-config.json @@ -14,6 +14,9 @@ "MailAliasAccount": { "dataSource": "vn" }, + "MailAliasAcl": { + "dataSource": "vn" + }, "MailConfig": { "dataSource": "vn" }, diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index 6f5213f24..a95189689 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -2,54 +2,54 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`You already have the mailAlias`); + return err; + }); + Self.observe('before save', async ctx => { const changes = ctx.currentInstance || ctx.instance; - await Self.hasGrant(ctx, changes.mailAlias); + await checkModifyPermission(ctx, changes.mailAlias); }); Self.observe('before delete', async ctx => { const mailAliasAccount = await Self.findById(ctx.where.id); - await Self.hasGrant(ctx, mailAliasAccount.mailAlias); + await checkModifyPermission(ctx, mailAliasAccount.mailAlias); }); - /** - * Checks if current user has - * grant to add/remove alias - * - * @param {Object} ctx - Request context - * @param {Interger} mailAlias - mailAlias id - * @return {Boolean} True for user with grant - */ - Self.hasGrant = async function(ctx, mailAlias) { + async function checkModifyPermission(ctx, mailAliasFk) { + const userId = ctx.options.accessToken.userId; + const available = await Self.getAvailable(userId); + if (!available.has(mailAliasFk)) + throw new UserError('The alias cant be modified'); + } + + Self.getAvailable = async function(userId, options) { const models = Self.app.models; - const accessToken = {req: {accessToken: ctx.options.accessToken}}; - const userId = accessToken.req.accessToken.userId; - const canEditAlias = await models.ACL.checkAccessAcl(accessToken, 'MailAliasAccount', 'canEditAlias', 'WRITE'); - if (canEditAlias) return true; + const myOptions = {}; - const user = await models.VnUser.findById(userId, {fields: ['hasGrant']}); - if (!user.hasGrant) - throw new UserError(`You don't have grant privilege`); + if (typeof options == 'object') + Object.assign(myOptions, options); - const account = await models.Account.findById(userId, { - fields: ['id'], - include: { - relation: 'aliases', - scope: { - fields: ['mailAlias'] - } + const roles = await models.RoleMapping.find({ + fields: ['roleId'], + where: {principalId: userId} + }, myOptions); + + const availableMailAlias = await models.MailAliasAcl.find({ + fields: ['mailAliasFk'], + include: {relation: 'mailAlias'}, + where: { + roleFk: { + inq: roles.map(role => role.roleId), + }, } - }); - - const aliases = account.aliases().map(alias => alias.mailAlias); - - const hasAlias = aliases.includes(mailAlias); - if (!hasAlias) - throw new UserError(`You cannot assign/remove an alias that you are not assigned to`); - - return true; + }, myOptions); + const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk); + return new Set(mailAliasArray); }; }; diff --git a/modules/account/back/models/mail-alias-acl.js b/modules/account/back/models/mail-alias-acl.js index 4a74472fe..a95189689 100644 --- a/modules/account/back/models/mail-alias-acl.js +++ b/modules/account/back/models/mail-alias-acl.js @@ -1,43 +1,33 @@ + const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - require('../methods/notification/getList')(Self); - - Self.observe('before save', async function(ctx) { - await checkModifyPermission(ctx); + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`You already have the mailAlias`); + return err; }); - Self.observe('before delete', async function(ctx) { - await checkModifyPermission(ctx); + Self.observe('before save', async ctx => { + const changes = ctx.currentInstance || ctx.instance; + + await checkModifyPermission(ctx, changes.mailAlias); }); - async function checkModifyPermission(ctx) { - const models = Self.app.models; - const instance = ctx.instance; + Self.observe('before delete', async ctx => { + const mailAliasAccount = await Self.findById(ctx.where.id); + + await checkModifyPermission(ctx, mailAliasAccount.mailAlias); + }); + + async function checkModifyPermission(ctx, mailAliasFk) { const userId = ctx.options.accessToken.userId; - - let mailAliasFk; - let roleFk; - - if (instance) { - mailAliasFk = instance.mailAliasFk; - roleFk = instance.roleFk; - } else { - const mailAliasAcl = await models.MailAlias.findById(ctx.where.id); - mailAliasFk = mailAliasAcl.id; - roleFk = mailAliasAcl.roleFk; - } - - const role = await models.VnUser.findById(roleFk, {fields: ['id', 'role']}); - const available = await Self.getAvailable(roleFk); - const hasAcl = available.has(mailAliasFk); - - if (!hasAcl || (userId.role != role)) + const available = await Self.getAvailable(userId); + if (!available.has(mailAliasFk)) throw new UserError('The alias cant be modified'); } Self.getAvailable = async function(userId, options) { - const availableMailAliasMap = new Map(); const models = Self.app.models; const myOptions = {}; @@ -51,20 +41,15 @@ module.exports = Self => { }, myOptions); const availableMailAlias = await models.MailAliasAcl.find({ - fields: ['mailAliasFk', 'roleFk'], - include: {relation: 'roleFk'}, + fields: ['mailAliasFk'], + include: {relation: 'mailAlias'}, where: { roleFk: { inq: roles.map(role => role.roleId), }, } }, myOptions); - - for (available of availableMailAlias) { - availableMailAliasMap.set(available.mailAliasFk, { - mailAliasFk: available.mailAliasFk, - }); - } - return availableMailAliasMap; + const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk); + return new Set(mailAliasArray); }; }; diff --git a/modules/account/back/models/mail-alias-acl.json b/modules/account/back/models/mail-alias-acl.json index 2e44f38eb..014b95d14 100644 --- a/modules/account/back/models/mail-alias-acl.json +++ b/modules/account/back/models/mail-alias-acl.json @@ -1,28 +1,30 @@ { - "name": "mailAliasACL", + "name": "MailAliasAcl", "base": "VnModel", "options": { "mysql": { - "table": "account.mailAliasACL" + "table": "account.mailAliasAcl" } }, "properties": { "mailAliasFk": { + "id": true, "type": "number" }, "roleFk": { + "id": true, "type": "number" } }, "relations": { "mailAlias": { "type": "belongsTo", - "model": "VnUser", + "model": "MailAlias", "foreignKey": "mailAliasFk" }, "role": { "type": "belongsTo", - "model": "VnUser", + "model": "Role", "foreignKey": "roleFk" } } diff --git a/modules/account/front/alias/acl/create/index.js b/modules/account/front/alias/acl/create/index.js deleted file mode 100644 index 58e70e4aa..000000000 --- a/modules/account/front/alias/acl/create/index.js +++ /dev/null @@ -1,33 +0,0 @@ -import ngModule from '../../../module'; -import Section from 'salix/components/section'; - -export default class Controller extends Section { - constructor(...args) { - super(...args); - this.accessTypes = [ - {name: '*'}, - {name: 'READ'}, - {name: 'WRITE'} - ]; - this.permissions = [ - {name: 'ALLOW'}, - {name: 'DENY'} - ]; - - this.models = []; - for (let model in window.validations) - this.models.push({name: model}); - - this.acl = { - property: '*', - principalType: 'ROLE', - accessType: 'READ', - permission: 'ALLOW' - }; - } -} - -ngModule.component('vnAclMailCreate', { - // template: require('./index.html'), - controller: Controller -}); diff --git a/modules/account/front/alias/acl/index.js b/modules/account/front/alias/acl/index.js deleted file mode 100644 index 8393859a5..000000000 --- a/modules/account/front/alias/acl/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import './main'; -import './index/'; -import './create'; -import './search-panel'; diff --git a/modules/account/front/alias/acl/index/index.js b/modules/account/front/alias/acl/index/index.js deleted file mode 100644 index 5d8d49574..000000000 --- a/modules/account/front/alias/acl/index/index.js +++ /dev/null @@ -1,15 +0,0 @@ -import ngModule from '../../../module'; -import Section from 'salix/components/section'; - -export default class Controller extends Section { - onDelete(row) { - return this.$http.delete(`ACLs/${row.id}`) - .then(() => this.$.model.refresh()) - .then(() => this.vnApp.showSuccess(this.$t('ACL removed'))); - } -} - -ngModule.component('vnAclMailIndex', { - // template: require('./index.html'), - controller: Controller -}); diff --git a/modules/account/front/alias/acl/main/index.js b/modules/account/front/alias/acl/main/index.js deleted file mode 100644 index 97f04ee50..000000000 --- a/modules/account/front/alias/acl/main/index.js +++ /dev/null @@ -1,18 +0,0 @@ -import ngModule from '../../../module'; -import ModuleMain from 'salix/components/module-main'; - -export default class ACL extends ModuleMain { - exprBuilder(param, value) { - switch (param) { - case 'search': - return {model: {like: `%${value}%`}}; - default: - return {[param]: value}; - } - } -} - -ngModule.vnComponent('vnAclMailComponent', { - controller: ACL - // template: require('./index.html') -}); diff --git a/modules/account/front/alias/acl/search-panel/index.js b/modules/account/front/alias/acl/search-panel/index.js deleted file mode 100644 index 67db33383..000000000 --- a/modules/account/front/alias/acl/search-panel/index.js +++ /dev/null @@ -1,26 +0,0 @@ -import ngModule from '../../../module'; -import SearchPanel from 'core/components/searchbar/search-panel'; - -export default class Controller extends SearchPanel { - constructor(...args) { - super(...args); - this.accessTypes = [ - {name: '*'}, - {name: 'READ'}, - {name: 'WRITE'} - ]; - this.permissions = [ - {name: 'ALLOW'}, - {name: 'DENY'} - ]; - - this.models = []; - for (let model in window.validations) - this.models.push({name: model}); - } -} - -ngModule.component('vnAclSearchPanel', { - // template: require('./index.html'), - controller: Controller -}); diff --git a/modules/account/front/alias/index.js b/modules/account/front/alias/index.js index 598421749..8eed3a3d3 100644 --- a/modules/account/front/alias/index.js +++ b/modules/account/front/alias/index.js @@ -7,4 +7,3 @@ import './descriptor'; import './create'; import './basic-data'; import './users'; -import './acl'; From c0ce7e542febf97895ad6ff14e9869f182407e05 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 4 Dec 2023 09:40:57 +0100 Subject: [PATCH 25/87] refs #6085 solve testback --- back/models/specs/mailAliasAccount.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/back/models/specs/mailAliasAccount.spec.js b/back/models/specs/mailAliasAccount.spec.js index 46d447f90..c07e16d60 100644 --- a/back/models/specs/mailAliasAccount.spec.js +++ b/back/models/specs/mailAliasAccount.spec.js @@ -24,7 +24,7 @@ fdescribe('loopback model MailAliasAccount', () => { try { const options = {transaction: tx, accessToken: {userId: 9}}; - await models.MailAliasAccount.create({mailAliasFk: 2, roleFk: 5}, options); + await models.MailAliasAccount.create({mailAlias: 2, account: 5}, options); await tx.rollback(); } catch (e) { @@ -41,7 +41,7 @@ fdescribe('loopback model MailAliasAccount', () => { try { const options = {transaction: tx, accessToken: {userId: 9}}; - await models.MailAliasAccount.create({mailAliasFk: 3, roleFk: 5}, options); + await models.MailAliasAccount.create({mailAlias: 3, account: 5}, options); await tx.rollback(); } catch (e) { From 051c93a42cdee0ab6403924c95cc1dd4771e6859 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 4 Dec 2023 09:41:24 +0100 Subject: [PATCH 26/87] remove fdescribe --- back/models/specs/mailAliasAccount.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/models/specs/mailAliasAccount.spec.js b/back/models/specs/mailAliasAccount.spec.js index c07e16d60..d26ed2313 100644 --- a/back/models/specs/mailAliasAccount.spec.js +++ b/back/models/specs/mailAliasAccount.spec.js @@ -1,6 +1,6 @@ const models = require('vn-loopback/server/server').models; -fdescribe('loopback model MailAliasAccount', () => { +describe('loopback model MailAliasAccount', () => { it('should fail to add a mail Alias if the worker doesnt have ACLs', async() => { const tx = await models.MailAliasAccount.beginTransaction({}); let error; From 2fe631f078bf2ca596e083ede0c015e3c1aec2d5 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 5 Dec 2023 07:15:22 +0100 Subject: [PATCH 27/87] refs #5666 feat: change models permissions --- back/model-config.json | 12 ++++++------ db/changes/235001/00-updateACL_Role_VnRole.sql | 14 +++++++++----- loopback/server/model-config.json | 8 -------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/back/model-config.json b/back/model-config.json index 84dd9eebd..27a94498c 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -139,12 +139,6 @@ "Warehouse": { "dataSource": "vn" }, - "VnUser": { - "dataSource": "vn" - }, - "VnRole": { - "dataSource": "vn" - }, "OsTicket": { "dataSource": "osticket" }, @@ -159,6 +153,12 @@ }, "ViaexpressConfig": { "dataSource": "vn" + }, + "VnUser": { + "dataSource": "vn" + }, + "VnRole": { + "dataSource": "vn" } } diff --git a/db/changes/235001/00-updateACL_Role_VnRole.sql b/db/changes/235001/00-updateACL_Role_VnRole.sql index 0b1083991..6fbec02a6 100644 --- a/db/changes/235001/00-updateACL_Role_VnRole.sql +++ b/db/changes/235001/00-updateACL_Role_VnRole.sql @@ -1,8 +1,12 @@ -- Auto-generated SQL script #202311301038 -INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) - VALUES ('VnRole','*','*','ALLOW','ROLE','$everyone'); -INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) - VALUES ('VnRole','*','*','ALLOW','ROLE','employee'); +-- INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) +-- VALUES ('VnRole','*','*','ALLOW','ROLE','$everyone'); +-- INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) +-- VALUES ('VnRole','*','*','ALLOW','ROLE','employee'); +INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) VALUES + ('VnRole','*','READ','ALLOW','ROLE','employee'), + ('VnRole','*','WRITE','ALLOW','ROLE','it'); -- Auto-generated SQL script #202311301203 -UPDATE `salix`.`ACL` SET permission='DENY' WHERE model='Role'; +DELETE FROM`salix`.`ACL` WHERE model='Role'; + diff --git a/loopback/server/model-config.json b/loopback/server/model-config.json index 33ef3797d..51874988d 100644 --- a/loopback/server/model-config.json +++ b/loopback/server/model-config.json @@ -25,14 +25,6 @@ "FieldAcl": { "dataSource": "vn" }, - "Role": { - "dataSource": "vn", - "options": { - "mysql": { - "table": "salix.Role" - } - } - }, "RoleMapping": { "dataSource": "vn", "options": { From 57add7abf016602c15786d719efd3f46142a549a Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 5 Dec 2023 07:16:12 +0100 Subject: [PATCH 28/87] refs #5666 perf: replace Role by VnRole --- back/methods/vn-user/privileges.js | 2 +- back/methods/vn-user/specs/privileges.spec.js | 2 +- modules/account/back/models/ldap-config.js | 2 +- modules/ticket/back/methods/sale/specs/canEdit.spec.js | 4 ++-- .../back/methods/worker/specs/activeWithInheritedRole.spec.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/back/methods/vn-user/privileges.js b/back/methods/vn-user/privileges.js index 08cfaaae8..9f936c29b 100644 --- a/back/methods/vn-user/privileges.js +++ b/back/methods/vn-user/privileges.js @@ -68,7 +68,7 @@ module.exports = Self => { userToUpdate.hasGrant = hasGrant; if (roleFk) { - const role = await models.Role.findById(roleFk, {fields: ['name']}, myOptions); + const role = await models.VnRole.findById(roleFk, {fields: ['name']}, myOptions); const hasRole = await Self.hasRole(userId, role.name, myOptions); if (!hasRole) diff --git a/back/methods/vn-user/specs/privileges.spec.js b/back/methods/vn-user/specs/privileges.spec.js index 3d25eecf9..04d9c09ff 100644 --- a/back/methods/vn-user/specs/privileges.spec.js +++ b/back/methods/vn-user/specs/privileges.spec.js @@ -70,7 +70,7 @@ describe('VnUser privileges()', () => { const tx = await models.VnUser.beginTransaction({}); const options = {transaction: tx}; - const agency = await models.Role.findOne({ + const agency = await models.VnRole.findOne({ where: { name: 'agency' } diff --git a/modules/account/back/models/ldap-config.js b/modules/account/back/models/ldap-config.js index b557d243c..89f0add48 100644 --- a/modules/account/back/models/ldap-config.js +++ b/modules/account/back/models/ldap-config.js @@ -239,7 +239,7 @@ module.exports = Self => { // Prepare data - let roles = await $.Role.find({ + let roles = await $.VnRole.find({ fields: ['id', 'name', 'description'] }); let roleRoles = await $.RoleRole.find({ diff --git a/modules/ticket/back/methods/sale/specs/canEdit.spec.js b/modules/ticket/back/methods/sale/specs/canEdit.spec.js index eef9136a8..200ea24cc 100644 --- a/modules/ticket/back/methods/sale/specs/canEdit.spec.js +++ b/modules/ticket/back/methods/sale/specs/canEdit.spec.js @@ -102,7 +102,7 @@ describe('sale canEdit()', () => { try { const options = {transaction: tx}; - const role = await models.Role.findOne({ + const role = await models.VnRole.findOne({ where: { name: roleEnabled.principalId } @@ -159,7 +159,7 @@ describe('sale canEdit()', () => { try { const options = {transaction: tx}; - const role = await models.Role.findOne({ + const role = await models.VnRole.findOne({ where: { name: roleEnabled.principalId } diff --git a/modules/worker/back/methods/worker/specs/activeWithInheritedRole.spec.js b/modules/worker/back/methods/worker/specs/activeWithInheritedRole.spec.js index da54f6adb..580e07351 100644 --- a/modules/worker/back/methods/worker/specs/activeWithInheritedRole.spec.js +++ b/modules/worker/back/methods/worker/specs/activeWithInheritedRole.spec.js @@ -3,7 +3,7 @@ const app = require('vn-loopback/server/server'); describe('Worker activeWithInheritedRole', () => { let allRolesCount; beforeAll(async() => { - allRolesCount = await app.models.Role.count(); + allRolesCount = await app.models.VnRole.count(); }); it('should return the workers with an inherited role of salesPerson', async() => { From b4f4714c0a9f6fae89c38b165e813582b37fc99f Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 5 Dec 2023 07:47:38 +0100 Subject: [PATCH 29/87] refs #5666 feat: remove loggable.json --- loopback/common/models/loggable.json | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 loopback/common/models/loggable.json diff --git a/loopback/common/models/loggable.json b/loopback/common/models/loggable.json deleted file mode 100644 index 62822d0af..000000000 --- a/loopback/common/models/loggable.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Loggable", - "base": "VnModel", - "validateUpsert": true, - "mixins": { - "Loggable": true - } -} From 1d92bbf4a21f24e30e4e51328e636b19ecc6a560 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 5 Dec 2023 07:48:56 +0100 Subject: [PATCH 30/87] refs #5666 feat: replace base value and add mixins --- modules/claim/back/models/claim-beginning.json | 5 ++++- modules/claim/back/models/claim-development.json | 5 ++++- modules/claim/back/models/claim-dms.json | 5 ++++- modules/claim/back/models/claim-end.json | 5 ++++- modules/claim/back/models/claim-observation.json | 5 ++++- modules/claim/back/models/claim-state.json | 5 ++++- modules/claim/back/models/claim.json | 5 ++++- modules/client/back/models/address.json | 5 ++++- modules/client/back/models/client-contact.json | 5 ++++- modules/client/back/models/client-dms.json | 5 ++++- modules/client/back/models/client-informa.json | 5 ++++- modules/client/back/models/client-observation.json | 5 ++++- modules/client/back/models/client-sample.json | 5 ++++- modules/client/back/models/client.json | 5 ++++- modules/client/back/models/greuge.json | 5 ++++- modules/client/back/models/recovery.json | 5 ++++- modules/entry/back/models/buy.json | 5 ++++- modules/entry/back/models/entry-observation.json | 5 ++++- modules/entry/back/models/entry.json | 5 ++++- modules/invoiceIn/back/models/invoice-in-tax.json | 5 ++++- modules/invoiceIn/back/models/invoice-in.json | 5 ++++- modules/item/back/models/item-barcode.json | 5 ++++- modules/item/back/models/item-botanical.json | 5 ++++- modules/item/back/models/item-shelving.json | 5 ++++- modules/item/back/models/item-tag.json | 5 ++++- modules/item/back/models/item-tax-country.json | 5 ++++- modules/item/back/models/item.json | 5 ++++- modules/route/back/models/route.json | 5 ++++- modules/shelving/back/models/shelving.json | 5 ++++- modules/supplier/back/models/supplier-account.json | 5 ++++- modules/supplier/back/models/supplier-address.json | 5 ++++- modules/supplier/back/models/supplier-contact.json | 5 ++++- modules/supplier/back/models/supplier.json | 5 ++++- modules/ticket/back/models/expedition.json | 5 ++++- modules/ticket/back/models/sale.json | 5 ++++- modules/ticket/back/models/ticket-dms.json | 5 ++++- modules/ticket/back/models/ticket-observation.json | 5 ++++- modules/ticket/back/models/ticket-packaging.json | 5 ++++- modules/ticket/back/models/ticket-refund.json | 5 ++++- modules/ticket/back/models/ticket-request.json | 5 ++++- modules/ticket/back/models/ticket-service.json | 5 ++++- modules/ticket/back/models/ticket-tracking.json | 5 ++++- modules/ticket/back/models/ticket-weekly.json | 5 ++++- modules/ticket/back/models/ticket.json | 5 ++++- modules/travel/back/models/travel-thermograph.json | 5 ++++- modules/travel/back/models/travel.json | 5 ++++- modules/worker/back/models/device-production-user.json | 5 ++++- modules/worker/back/models/device-production.json | 5 ++++- modules/worker/back/models/worker-dms.json | 5 ++++- modules/worker/back/models/worker.json | 5 ++++- modules/zone/back/models/zone-event.json | 5 ++++- modules/zone/back/models/zone-exclusion.json | 5 ++++- modules/zone/back/models/zone-included.json | 5 ++++- modules/zone/back/models/zone-warehouse.json | 5 ++++- modules/zone/back/models/zone.json | 5 ++++- 55 files changed, 220 insertions(+), 55 deletions(-) diff --git a/modules/claim/back/models/claim-beginning.json b/modules/claim/back/models/claim-beginning.json index d355881e8..d224586da 100644 --- a/modules/claim/back/models/claim-beginning.json +++ b/modules/claim/back/models/claim-beginning.json @@ -1,6 +1,9 @@ { "name": "ClaimBeginning", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "claimBeginning" diff --git a/modules/claim/back/models/claim-development.json b/modules/claim/back/models/claim-development.json index b0f352f50..732955660 100644 --- a/modules/claim/back/models/claim-development.json +++ b/modules/claim/back/models/claim-development.json @@ -1,6 +1,9 @@ { "name": "ClaimDevelopment", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "claimDevelopment" diff --git a/modules/claim/back/models/claim-dms.json b/modules/claim/back/models/claim-dms.json index 26c90fd69..ed12c925b 100644 --- a/modules/claim/back/models/claim-dms.json +++ b/modules/claim/back/models/claim-dms.json @@ -1,6 +1,9 @@ { "name": "ClaimDms", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "claimDms" diff --git a/modules/claim/back/models/claim-end.json b/modules/claim/back/models/claim-end.json index 9f12ff93a..ef5477f50 100644 --- a/modules/claim/back/models/claim-end.json +++ b/modules/claim/back/models/claim-end.json @@ -1,6 +1,9 @@ { "name": "ClaimEnd", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "claimEnd" diff --git a/modules/claim/back/models/claim-observation.json b/modules/claim/back/models/claim-observation.json index 2d418b76e..1e4cb6a0f 100644 --- a/modules/claim/back/models/claim-observation.json +++ b/modules/claim/back/models/claim-observation.json @@ -1,6 +1,9 @@ { "name": "ClaimObservation", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "claimObservation" diff --git a/modules/claim/back/models/claim-state.json b/modules/claim/back/models/claim-state.json index 3ee932f16..c50fdebdf 100644 --- a/modules/claim/back/models/claim-state.json +++ b/modules/claim/back/models/claim-state.json @@ -1,6 +1,9 @@ { "name": "ClaimState", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "claimState" diff --git a/modules/claim/back/models/claim.json b/modules/claim/back/models/claim.json index a7db1f3e1..b85b9e073 100644 --- a/modules/claim/back/models/claim.json +++ b/modules/claim/back/models/claim.json @@ -1,6 +1,9 @@ { "name": "Claim", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "claim" diff --git a/modules/client/back/models/address.json b/modules/client/back/models/address.json index 5f962677d..e8bf8d8a0 100644 --- a/modules/client/back/models/address.json +++ b/modules/client/back/models/address.json @@ -1,7 +1,10 @@ { "name": "Address", "description": "Client addresses", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "address" diff --git a/modules/client/back/models/client-contact.json b/modules/client/back/models/client-contact.json index 3f71ab79e..55cc9d436 100644 --- a/modules/client/back/models/client-contact.json +++ b/modules/client/back/models/client-contact.json @@ -1,7 +1,10 @@ { "name": "ClientContact", "description": "Client phone contacts", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "clientContact" diff --git a/modules/client/back/models/client-dms.json b/modules/client/back/models/client-dms.json index 14b19498e..6dbcd0140 100644 --- a/modules/client/back/models/client-dms.json +++ b/modules/client/back/models/client-dms.json @@ -1,6 +1,9 @@ { "name": "ClientDms", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "clientDms" diff --git a/modules/client/back/models/client-informa.json b/modules/client/back/models/client-informa.json index 0c652484e..5e536faff 100644 --- a/modules/client/back/models/client-informa.json +++ b/modules/client/back/models/client-informa.json @@ -1,6 +1,9 @@ { "name": "ClientInforma", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "log": { "model":"ClientLog", "relation": "client", diff --git a/modules/client/back/models/client-observation.json b/modules/client/back/models/client-observation.json index 95d00d374..b204ebeb4 100644 --- a/modules/client/back/models/client-observation.json +++ b/modules/client/back/models/client-observation.json @@ -1,7 +1,10 @@ { "name": "ClientObservation", "description": "Client notes", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "clientObservation" diff --git a/modules/client/back/models/client-sample.json b/modules/client/back/models/client-sample.json index a32f308ab..4cd55d9df 100644 --- a/modules/client/back/models/client-sample.json +++ b/modules/client/back/models/client-sample.json @@ -1,6 +1,9 @@ { "name": "ClientSample", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "clientSample" diff --git a/modules/client/back/models/client.json b/modules/client/back/models/client.json index f32915bb5..bfde05162 100644 --- a/modules/client/back/models/client.json +++ b/modules/client/back/models/client.json @@ -1,6 +1,9 @@ { "name": "Client", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "client" diff --git a/modules/client/back/models/greuge.json b/modules/client/back/models/greuge.json index 884cbd34e..f57744f8a 100644 --- a/modules/client/back/models/greuge.json +++ b/modules/client/back/models/greuge.json @@ -1,6 +1,9 @@ { "name": "Greuge", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "greuge" diff --git a/modules/client/back/models/recovery.json b/modules/client/back/models/recovery.json index 5ea89197d..89ec54494 100644 --- a/modules/client/back/models/recovery.json +++ b/modules/client/back/models/recovery.json @@ -1,6 +1,9 @@ { "name": "Recovery", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "recovery" diff --git a/modules/entry/back/models/buy.json b/modules/entry/back/models/buy.json index 30379eaf6..fa804f4d8 100644 --- a/modules/entry/back/models/buy.json +++ b/modules/entry/back/models/buy.json @@ -1,6 +1,9 @@ { "name": "Buy", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "buy" diff --git a/modules/entry/back/models/entry-observation.json b/modules/entry/back/models/entry-observation.json index cdf0c5e6e..6a1592037 100644 --- a/modules/entry/back/models/entry-observation.json +++ b/modules/entry/back/models/entry-observation.json @@ -1,6 +1,9 @@ { "name": "EntryObservation", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "entryObservation" diff --git a/modules/entry/back/models/entry.json b/modules/entry/back/models/entry.json index a7508b4e8..0f3e389b6 100644 --- a/modules/entry/back/models/entry.json +++ b/modules/entry/back/models/entry.json @@ -1,6 +1,9 @@ { "name": "Entry", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "entry" diff --git a/modules/invoiceIn/back/models/invoice-in-tax.json b/modules/invoiceIn/back/models/invoice-in-tax.json index 5bfbbe2a8..53b5548b6 100644 --- a/modules/invoiceIn/back/models/invoice-in-tax.json +++ b/modules/invoiceIn/back/models/invoice-in-tax.json @@ -1,6 +1,9 @@ { "name": "InvoiceInTax", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "invoiceInTax" diff --git a/modules/invoiceIn/back/models/invoice-in.json b/modules/invoiceIn/back/models/invoice-in.json index 5be55c851..59c179e76 100644 --- a/modules/invoiceIn/back/models/invoice-in.json +++ b/modules/invoiceIn/back/models/invoice-in.json @@ -1,6 +1,9 @@ { "name": "InvoiceIn", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "invoiceIn" diff --git a/modules/item/back/models/item-barcode.json b/modules/item/back/models/item-barcode.json index 12068a65f..6726900ea 100644 --- a/modules/item/back/models/item-barcode.json +++ b/modules/item/back/models/item-barcode.json @@ -1,6 +1,9 @@ { "name": "ItemBarcode", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "itemBarcode" diff --git a/modules/item/back/models/item-botanical.json b/modules/item/back/models/item-botanical.json index 8a8bba870..ff1410615 100644 --- a/modules/item/back/models/item-botanical.json +++ b/modules/item/back/models/item-botanical.json @@ -1,6 +1,9 @@ { "name": "ItemBotanical", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "itemBotanical" diff --git a/modules/item/back/models/item-shelving.json b/modules/item/back/models/item-shelving.json index bb1a141c4..f3be98fc4 100644 --- a/modules/item/back/models/item-shelving.json +++ b/modules/item/back/models/item-shelving.json @@ -1,6 +1,9 @@ { "name": "ItemShelving", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "itemShelving" diff --git a/modules/item/back/models/item-tag.json b/modules/item/back/models/item-tag.json index 0742f8d3f..5702cf6cf 100644 --- a/modules/item/back/models/item-tag.json +++ b/modules/item/back/models/item-tag.json @@ -1,6 +1,9 @@ { "name": "ItemTag", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "itemTag" diff --git a/modules/item/back/models/item-tax-country.json b/modules/item/back/models/item-tax-country.json index 002be97d8..795a1b950 100644 --- a/modules/item/back/models/item-tax-country.json +++ b/modules/item/back/models/item-tax-country.json @@ -1,6 +1,9 @@ { "name": "ItemTaxCountry", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "itemTaxCountry" diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json index 097fe7708..595fb537d 100644 --- a/modules/item/back/models/item.json +++ b/modules/item/back/models/item.json @@ -1,6 +1,9 @@ { "name": "Item", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "item" diff --git a/modules/route/back/models/route.json b/modules/route/back/models/route.json index cdb64dd71..f8be9023c 100644 --- a/modules/route/back/models/route.json +++ b/modules/route/back/models/route.json @@ -1,6 +1,9 @@ { "name": "Route", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "route" diff --git a/modules/shelving/back/models/shelving.json b/modules/shelving/back/models/shelving.json index 3103b5a4a..46fce31e8 100644 --- a/modules/shelving/back/models/shelving.json +++ b/modules/shelving/back/models/shelving.json @@ -1,6 +1,9 @@ { "name": "Shelving", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "shelving" diff --git a/modules/supplier/back/models/supplier-account.json b/modules/supplier/back/models/supplier-account.json index bc9cf0e24..460c435e2 100644 --- a/modules/supplier/back/models/supplier-account.json +++ b/modules/supplier/back/models/supplier-account.json @@ -1,6 +1,9 @@ { "name": "SupplierAccount", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "supplierAccount" diff --git a/modules/supplier/back/models/supplier-address.json b/modules/supplier/back/models/supplier-address.json index 001b3a31f..fcd599287 100644 --- a/modules/supplier/back/models/supplier-address.json +++ b/modules/supplier/back/models/supplier-address.json @@ -1,7 +1,10 @@ { "name": "SupplierAddress", "description": "Supplier addresses", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "supplierAddress" diff --git a/modules/supplier/back/models/supplier-contact.json b/modules/supplier/back/models/supplier-contact.json index f928cd204..4ea1b8c2a 100644 --- a/modules/supplier/back/models/supplier-contact.json +++ b/modules/supplier/back/models/supplier-contact.json @@ -1,6 +1,9 @@ { "name": "SupplierContact", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "supplierContact" diff --git a/modules/supplier/back/models/supplier.json b/modules/supplier/back/models/supplier.json index b6245ef32..59d23f106 100644 --- a/modules/supplier/back/models/supplier.json +++ b/modules/supplier/back/models/supplier.json @@ -1,6 +1,9 @@ { "name": "Supplier", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "supplier" diff --git a/modules/ticket/back/models/expedition.json b/modules/ticket/back/models/expedition.json index 069c6e281..2dcca1e87 100644 --- a/modules/ticket/back/models/expedition.json +++ b/modules/ticket/back/models/expedition.json @@ -1,6 +1,9 @@ { "name": "Expedition", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "expedition" diff --git a/modules/ticket/back/models/sale.json b/modules/ticket/back/models/sale.json index 72ca1f5e0..96a36bbc9 100644 --- a/modules/ticket/back/models/sale.json +++ b/modules/ticket/back/models/sale.json @@ -1,6 +1,9 @@ { "name": "Sale", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "sale" diff --git a/modules/ticket/back/models/ticket-dms.json b/modules/ticket/back/models/ticket-dms.json index 071999be7..a3e697506 100644 --- a/modules/ticket/back/models/ticket-dms.json +++ b/modules/ticket/back/models/ticket-dms.json @@ -1,6 +1,9 @@ { "name": "TicketDms", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketDms" diff --git a/modules/ticket/back/models/ticket-observation.json b/modules/ticket/back/models/ticket-observation.json index 64e49b217..26d6f7586 100644 --- a/modules/ticket/back/models/ticket-observation.json +++ b/modules/ticket/back/models/ticket-observation.json @@ -1,6 +1,9 @@ { "name": "TicketObservation", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketObservation" diff --git a/modules/ticket/back/models/ticket-packaging.json b/modules/ticket/back/models/ticket-packaging.json index 6c94c810e..0cf494809 100644 --- a/modules/ticket/back/models/ticket-packaging.json +++ b/modules/ticket/back/models/ticket-packaging.json @@ -1,6 +1,9 @@ { "name": "TicketPackaging", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketPackaging" diff --git a/modules/ticket/back/models/ticket-refund.json b/modules/ticket/back/models/ticket-refund.json index d344a3f1c..249270c8b 100644 --- a/modules/ticket/back/models/ticket-refund.json +++ b/modules/ticket/back/models/ticket-refund.json @@ -1,6 +1,9 @@ { "name": "TicketRefund", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketRefund" diff --git a/modules/ticket/back/models/ticket-request.json b/modules/ticket/back/models/ticket-request.json index f8407792e..2cfcd30a1 100644 --- a/modules/ticket/back/models/ticket-request.json +++ b/modules/ticket/back/models/ticket-request.json @@ -1,6 +1,9 @@ { "name": "TicketRequest", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketRequest" diff --git a/modules/ticket/back/models/ticket-service.json b/modules/ticket/back/models/ticket-service.json index f1dbede13..4dfbd2fbd 100644 --- a/modules/ticket/back/models/ticket-service.json +++ b/modules/ticket/back/models/ticket-service.json @@ -1,6 +1,9 @@ { "name": "TicketService", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketService" diff --git a/modules/ticket/back/models/ticket-tracking.json b/modules/ticket/back/models/ticket-tracking.json index 8b5ce0b64..472bdb966 100644 --- a/modules/ticket/back/models/ticket-tracking.json +++ b/modules/ticket/back/models/ticket-tracking.json @@ -1,6 +1,9 @@ { "name": "TicketTracking", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketTracking" diff --git a/modules/ticket/back/models/ticket-weekly.json b/modules/ticket/back/models/ticket-weekly.json index c5e485aa2..7494cac79 100644 --- a/modules/ticket/back/models/ticket-weekly.json +++ b/modules/ticket/back/models/ticket-weekly.json @@ -1,6 +1,9 @@ { "name": "TicketWeekly", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticketWeekly" diff --git a/modules/ticket/back/models/ticket.json b/modules/ticket/back/models/ticket.json index ec4193bed..c55cd82bb 100644 --- a/modules/ticket/back/models/ticket.json +++ b/modules/ticket/back/models/ticket.json @@ -1,6 +1,9 @@ { "name": "Ticket", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "ticket" diff --git a/modules/travel/back/models/travel-thermograph.json b/modules/travel/back/models/travel-thermograph.json index 08eec2847..cc8e60aaf 100644 --- a/modules/travel/back/models/travel-thermograph.json +++ b/modules/travel/back/models/travel-thermograph.json @@ -1,6 +1,9 @@ { "name": "TravelThermograph", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "travelThermograph" diff --git a/modules/travel/back/models/travel.json b/modules/travel/back/models/travel.json index 95d458121..701894a76 100644 --- a/modules/travel/back/models/travel.json +++ b/modules/travel/back/models/travel.json @@ -1,6 +1,9 @@ { "name": "Travel", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "travel" diff --git a/modules/worker/back/models/device-production-user.json b/modules/worker/back/models/device-production-user.json index 3eeaae137..35a90fb50 100644 --- a/modules/worker/back/models/device-production-user.json +++ b/modules/worker/back/models/device-production-user.json @@ -1,6 +1,9 @@ { "name": "DeviceProductionUser", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "log": { "model": "DeviceProductionLog", "relation": "deviceProduction" diff --git a/modules/worker/back/models/device-production.json b/modules/worker/back/models/device-production.json index 35787cccc..f6e5105ad 100644 --- a/modules/worker/back/models/device-production.json +++ b/modules/worker/back/models/device-production.json @@ -1,6 +1,9 @@ { "name": "DeviceProduction", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "log": { "model": "DeviceProductionLog" }, diff --git a/modules/worker/back/models/worker-dms.json b/modules/worker/back/models/worker-dms.json index e9a9f1773..a5c0f30b2 100644 --- a/modules/worker/back/models/worker-dms.json +++ b/modules/worker/back/models/worker-dms.json @@ -1,6 +1,9 @@ { "name": "WorkerDms", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "workerDocument" diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 1a777fffe..ed430f133 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -1,7 +1,10 @@ { "name": "Worker", "description": "Company employees", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "worker" diff --git a/modules/zone/back/models/zone-event.json b/modules/zone/back/models/zone-event.json index e477dad6a..366bdec9d 100644 --- a/modules/zone/back/models/zone-event.json +++ b/modules/zone/back/models/zone-event.json @@ -1,6 +1,9 @@ { "name": "ZoneEvent", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "zoneEvent" diff --git a/modules/zone/back/models/zone-exclusion.json b/modules/zone/back/models/zone-exclusion.json index 00c9145cd..6e91a0a01 100644 --- a/modules/zone/back/models/zone-exclusion.json +++ b/modules/zone/back/models/zone-exclusion.json @@ -1,6 +1,9 @@ { "name": "ZoneExclusion", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "zoneExclusion" diff --git a/modules/zone/back/models/zone-included.json b/modules/zone/back/models/zone-included.json index deba73f34..a34e51091 100644 --- a/modules/zone/back/models/zone-included.json +++ b/modules/zone/back/models/zone-included.json @@ -1,6 +1,9 @@ { "name": "ZoneIncluded", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "zoneIncluded" diff --git a/modules/zone/back/models/zone-warehouse.json b/modules/zone/back/models/zone-warehouse.json index b222e95e7..c2cc989f0 100644 --- a/modules/zone/back/models/zone-warehouse.json +++ b/modules/zone/back/models/zone-warehouse.json @@ -1,6 +1,9 @@ { "name": "ZoneWarehouse", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "zoneWarehouse" diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json index c86da3d3e..cf7371053 100644 --- a/modules/zone/back/models/zone.json +++ b/modules/zone/back/models/zone.json @@ -1,6 +1,9 @@ { "name": "Zone", - "base": "Loggable", + "base": "VnModel", + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "zone" From 6f32a588bbc9faacdb5182cf01477f779af19219 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 5 Dec 2023 07:49:10 +0100 Subject: [PATCH 31/87] refs #5666 feat: add role relation to RoleMapping --- loopback/server/model-config.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/loopback/server/model-config.json b/loopback/server/model-config.json index 51874988d..56b5360e8 100644 --- a/loopback/server/model-config.json +++ b/loopback/server/model-config.json @@ -31,6 +31,13 @@ "mysql": { "table": "salix.RoleMapping" } + }, + "relations": { + "role": { + "type": "belongsTo", + "model": "VnRole", + "foreignKey": "roleId" + } } }, "Schema": { From 7a63e527a5298b05028c7721eddbefcfe597f695 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 5 Dec 2023 07:50:52 +0100 Subject: [PATCH 32/87] refs #5666 perf: remove comments --- db/changes/235001/00-updateACL_Role_VnRole.sql | 6 ------ 1 file changed, 6 deletions(-) diff --git a/db/changes/235001/00-updateACL_Role_VnRole.sql b/db/changes/235001/00-updateACL_Role_VnRole.sql index 6fbec02a6..b08a44138 100644 --- a/db/changes/235001/00-updateACL_Role_VnRole.sql +++ b/db/changes/235001/00-updateACL_Role_VnRole.sql @@ -1,12 +1,6 @@ --- Auto-generated SQL script #202311301038 --- INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) --- VALUES ('VnRole','*','*','ALLOW','ROLE','$everyone'); --- INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) --- VALUES ('VnRole','*','*','ALLOW','ROLE','employee'); INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) VALUES ('VnRole','*','READ','ALLOW','ROLE','employee'), ('VnRole','*','WRITE','ALLOW','ROLE','it'); --- Auto-generated SQL script #202311301203 DELETE FROM`salix`.`ACL` WHERE model='Role'; From 419ab418160579a6fa8f420a4fe098199d1f0a8e Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 5 Dec 2023 09:55:22 +0100 Subject: [PATCH 33/87] refs #6276 Acl addTimeEntry --- db/changes/235001/00-timecontrol.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/changes/235001/00-timecontrol.sql b/db/changes/235001/00-timecontrol.sql index 4e350b002..8b59c1cac 100644 --- a/db/changes/235001/00-timecontrol.sql +++ b/db/changes/235001/00-timecontrol.sql @@ -8,6 +8,6 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalTyp VALUES ('WorkerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', 'timeControl'), ('WorkerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', 'timeControl'), - ('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); + ('WorkerTimeControl', 'addTimeEntry', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); CALL `account`.`role_sync`(); From 25006a938be9214bcd62690d5c3c1709053a0e26 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 5 Dec 2023 11:53:27 +0100 Subject: [PATCH 34/87] refs #6274 refactor clockIn --- db/changes/235001/00-timecontrol.sql | 2 +- .../methods/worker-time-control/addTimeEntry.js | 5 +---- .../back/methods/worker-time-control/clockIn.js | 16 +++++++++++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/db/changes/235001/00-timecontrol.sql b/db/changes/235001/00-timecontrol.sql index 8b59c1cac..4e350b002 100644 --- a/db/changes/235001/00-timecontrol.sql +++ b/db/changes/235001/00-timecontrol.sql @@ -8,6 +8,6 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalTyp VALUES ('WorkerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', 'timeControl'), ('WorkerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', 'timeControl'), - ('WorkerTimeControl', 'addTimeEntry', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); + ('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); CALL `account`.`role_sync`(); diff --git a/modules/worker/back/methods/worker-time-control/addTimeEntry.js b/modules/worker/back/methods/worker-time-control/addTimeEntry.js index cc652fb90..f3b0127c4 100644 --- a/modules/worker/back/methods/worker-time-control/addTimeEntry.js +++ b/modules/worker/back/methods/worker-time-control/addTimeEntry.js @@ -46,10 +46,7 @@ module.exports = Self => { if (!isSubordinate || (isSubordinate && isHimself && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - query = `CALL vn.workerTimeControl_clockIn(?,?,?)`; - const [response] = await Self.rawSql(query, [workerId, args.timed, args.direction], myOptions); - if (response[0] && response[0].error) - throw new UserError(response[0].error); + const response = await Self.clockIn(workerId, args.timed, args.direction, myOptions); await models.WorkerTimeControl.resendWeeklyHourEmail(ctx, workerId, args.timed, myOptions); diff --git a/modules/worker/back/methods/worker-time-control/clockIn.js b/modules/worker/back/methods/worker-time-control/clockIn.js index 3cc57d341..6ed742778 100644 --- a/modules/worker/back/methods/worker-time-control/clockIn.js +++ b/modules/worker/back/methods/worker-time-control/clockIn.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = Self => { Self.remoteMethod('clockIn', { description: 'Check if the employee can clock in', @@ -8,6 +10,10 @@ module.exports = Self => { type: 'integer', required: true, }, + { + arg: 'timed', + type: 'date' + }, { arg: 'direction', type: 'string' @@ -24,12 +30,16 @@ module.exports = Self => { } }); - Self.clockIn = async(workerFk, direction, options) => { + Self.clockIn = async(workerFk, timed, direction, options) => { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - const query = 'CALL vn.workerTimeControl_clockIn(?, NULL, ?)'; - return await Self.rawSql(query, [workerFk, direction], myOptions); + const query = 'CALL vn.workerTimeControl_clockIn(?, ?, ?)'; + const [response] = await Self.rawSql(query, [workerFk, timed, direction], myOptions); + if (response[0] && response[0].error) + throw new UserError(response[0].error); + + return response; }; }; From 035b31d878cb989e64f3dc06cd75ff539aad6f74 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Tue, 5 Dec 2023 12:00:31 +0100 Subject: [PATCH 35/87] refs #5666 test: fix e2e tests --- front/core/directives/rule.js | 6 +++++- modules/account/front/role/basic-data/index.html | 10 +++++++--- modules/account/front/role/create/index.html | 4 ++-- modules/account/front/role/descriptor/index.html | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/front/core/directives/rule.js b/front/core/directives/rule.js index f65efe176..d944e13ed 100644 --- a/front/core/directives/rule.js +++ b/front/core/directives/rule.js @@ -23,7 +23,7 @@ export function directive($translate, $window) { let rule = $attrs.rule.split('.'); let modelName = rule.shift(); let fieldName = rule.shift(); - + let modelAlias = $attrs.ruleAlias; let split = $attrs.ngModel.split('.'); if (!fieldName) fieldName = split.pop() || null; if (!modelName) modelName = firstUpper(split.pop() || ''); @@ -31,8 +31,12 @@ export function directive($translate, $window) { if (!modelName || !fieldName) throw new Error(`rule: Cannot retrieve model or field attribute`); + let modelValidations = vnValidations[modelName]; + if (!modelValidations) + modelValidations = vnValidations[modelAlias]; + if (!modelValidations) throw new Error(`rule: Model '${modelName}' doesn't exist`); diff --git a/modules/account/front/role/basic-data/index.html b/modules/account/front/role/basic-data/index.html index a6d39f3e3..46cb080b7 100644 --- a/modules/account/front/role/basic-data/index.html +++ b/modules/account/front/role/basic-data/index.html @@ -7,6 +7,7 @@
@@ -14,12 +15,15 @@ label="Name" ng-model="$ctrl.role.name" rule + rule-alias="VnRole" vn-focus> + label="Description" + ng-model="$ctrl.role.description" + rule + rule-alias="VnRole" + > diff --git a/modules/account/front/role/create/index.html b/modules/account/front/role/create/index.html index b747f7d00..ee43484d7 100644 --- a/modules/account/front/role/create/index.html +++ b/modules/account/front/role/create/index.html @@ -13,13 +13,13 @@ diff --git a/modules/account/front/role/descriptor/index.html b/modules/account/front/role/descriptor/index.html index 4cd4ac822..d8bf4857a 100644 --- a/modules/account/front/role/descriptor/index.html +++ b/modules/account/front/role/descriptor/index.html @@ -24,4 +24,4 @@ on-accept="$ctrl.onDelete()" question="Are you sure you want to continue?" message="Role will be removed"> - \ No newline at end of file + From b50a6add0d5e7cc2678a35ff9707f20457dec769 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 5 Dec 2023 15:57:42 +0100 Subject: [PATCH 36/87] refs #6274 merge renewToken --- db/changes/235001/00-timecontrol.sql | 3 ++- db/changes/{234601 => 235001}/00-updateCourtesyTime.sql | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename db/changes/{234601 => 235001}/00-updateCourtesyTime.sql (100%) diff --git a/db/changes/235001/00-timecontrol.sql b/db/changes/235001/00-timecontrol.sql index 4e350b002..0d3bd59b2 100644 --- a/db/changes/235001/00-timecontrol.sql +++ b/db/changes/235001/00-timecontrol.sql @@ -8,6 +8,7 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalTyp VALUES ('WorkerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', 'timeControl'), ('WorkerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', 'timeControl'), - ('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); + ('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'), + ('VnUser', 'renewToken', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); CALL `account`.`role_sync`(); diff --git a/db/changes/234601/00-updateCourtesyTime.sql b/db/changes/235001/00-updateCourtesyTime.sql similarity index 100% rename from db/changes/234601/00-updateCourtesyTime.sql rename to db/changes/235001/00-updateCourtesyTime.sql From 968dc6523132aab070131880afe6bdad55c0931f Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 7 Dec 2023 14:47:22 +0100 Subject: [PATCH 37/87] refs #6274 tests created --- .../worker-time-control/addTimeEntry.js | 8 ++---- .../methods/worker-time-control/clockIn.js | 2 +- .../methods/worker-time-control/getClockIn.js | 4 +-- .../resendWeeklyHourEmail.js | 2 +- .../worker-time-control/specs/clockIn.spec.js | 28 +++++++++++++++++++ .../specs/getClockIn.spec.js | 16 +++++++++++ .../worker-time-control/specs/login.spec.js | 20 +++++++++++++ 7 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js create mode 100644 modules/worker/back/methods/worker-time-control/specs/getClockIn.spec.js create mode 100644 modules/worker/back/methods/worker-time-control/specs/login.spec.js diff --git a/modules/worker/back/methods/worker-time-control/addTimeEntry.js b/modules/worker/back/methods/worker-time-control/addTimeEntry.js index f3b0127c4..96e3a47d9 100644 --- a/modules/worker/back/methods/worker-time-control/addTimeEntry.js +++ b/modules/worker/back/methods/worker-time-control/addTimeEntry.js @@ -43,13 +43,9 @@ module.exports = Self => { const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE'); const isHimself = userId == workerId; - if (!isSubordinate || (isSubordinate && isHimself && !isTeamBoss)) + if (!isSubordinate || (isHimself && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - const response = await Self.clockIn(workerId, args.timed, args.direction, myOptions); - - await models.WorkerTimeControl.resendWeeklyHourEmail(ctx, workerId, args.timed, myOptions); - - return response; + return await Self.clockIn(workerId, args.timed, args.direction, myOptions); }; }; diff --git a/modules/worker/back/methods/worker-time-control/clockIn.js b/modules/worker/back/methods/worker-time-control/clockIn.js index 6ed742778..2e2441cc2 100644 --- a/modules/worker/back/methods/worker-time-control/clockIn.js +++ b/modules/worker/back/methods/worker-time-control/clockIn.js @@ -7,7 +7,7 @@ module.exports = Self => { accepts: [ { arg: 'workerFk', - type: 'integer', + type: 'number', required: true, }, { diff --git a/modules/worker/back/methods/worker-time-control/getClockIn.js b/modules/worker/back/methods/worker-time-control/getClockIn.js index bc0675db8..470700643 100644 --- a/modules/worker/back/methods/worker-time-control/getClockIn.js +++ b/modules/worker/back/methods/worker-time-control/getClockIn.js @@ -25,8 +25,8 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const query = `CALL vn.workerTimeControl_getClockIn(?, CURDATE())`; - const [result] = await Self.rawSql(query, [workerFk], myOptions); + const query = `CALL vn.workerTimeControl_getClockIn(?, ?)`; + const [result] = await Self.rawSql(query, [workerFk, Date.vnNew()], myOptions); return result; }; }; diff --git a/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js b/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js index 2452a29f9..896458455 100644 --- a/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js +++ b/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethodCtx('resendWeeklyHourEmail', { - description: 'Adds a new hour registry', + description: 'Send the records for the week of the date provided', accessType: 'WRITE', accepts: [{ arg: 'id', diff --git a/modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js b/modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js new file mode 100644 index 000000000..970fd2fe2 --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js @@ -0,0 +1,28 @@ +const models = require('vn-loopback/server/server').models; + +describe('workerTimeControl clockIn()', () => { + const workerId = 9; + const inTime = '2001-01-01T00:00:00.000Z'; + + it('should correctly clock in', async() => { + const tx = await models.WorkerTimeControl.beginTransaction({}); + + try { + const options = {transaction: tx}; + await models.WorkerTimeControl.clockIn(workerId, inTime, 'in', options); + const isClockIn = await models.WorkerTimeControl.findOne({ + where: { + userFk: workerId + } + }, options); + + expect(isClockIn).toBeDefined(); + expect(isClockIn.direction).toBe('in'); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); + diff --git a/modules/worker/back/methods/worker-time-control/specs/getClockIn.spec.js b/modules/worker/back/methods/worker-time-control/specs/getClockIn.spec.js new file mode 100644 index 000000000..d75ffac70 --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/specs/getClockIn.spec.js @@ -0,0 +1,16 @@ +const models = require('vn-loopback/server/server').models; + +describe('workerTimeControl getClockIn()', () => { + it('should correctly get the timetable of a worker', async() => { + const response = await models.WorkerTimeControl.getClockIn(1106, {}); + + expect(response.length).toEqual(4); + const [inHrs, middleOutHrs, middleInHrs, outHrs] = response; + + expect(inHrs['0daysAgo']).toEqual('07:00'); + expect(middleOutHrs['0daysAgo']).toEqual('10:00'); + expect(middleInHrs['0daysAgo']).toEqual('10:20'); + expect(outHrs['0daysAgo']).toEqual('14:50'); + }); +}); + diff --git a/modules/worker/back/methods/worker-time-control/specs/login.spec.js b/modules/worker/back/methods/worker-time-control/specs/login.spec.js new file mode 100644 index 000000000..88596f297 --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/specs/login.spec.js @@ -0,0 +1,20 @@ +const UserError = require('vn-loopback/util/user-error'); +const models = require('vn-loopback/server/server').models; + +describe('workerTimeControl login()', () => { + it('should correctly login', async() => { + const response = await models.WorkerTimeControl.login(9, {}); + + expect(response.name).toBe('developer'); + }); + + it('should throw UserError if pin is not provided', async() => { + try { + await models.WorkerTimeControl.login(); + } catch (error) { + expect(error).toBeInstanceOf(UserError); + expect(error.message).toBe('Indique el pin.'); + } + }); +}); + From ec66386b442a292329819041dca82b2c2677b2b6 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 11 Dec 2023 07:49:44 +0100 Subject: [PATCH 38/87] refs #5914 fix: correct sql folder --- db/changes/{235001 => 235201}/00-getTaxBases.sql | 0 db/changes/{235001 => 235201}/01-newHasAnyPositiveBase.sql | 0 db/changes/{235001 => 235201}/01-refactorHasAnyNegativeBase.sql | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename db/changes/{235001 => 235201}/00-getTaxBases.sql (100%) rename db/changes/{235001 => 235201}/01-newHasAnyPositiveBase.sql (100%) rename db/changes/{235001 => 235201}/01-refactorHasAnyNegativeBase.sql (100%) diff --git a/db/changes/235001/00-getTaxBases.sql b/db/changes/235201/00-getTaxBases.sql similarity index 100% rename from db/changes/235001/00-getTaxBases.sql rename to db/changes/235201/00-getTaxBases.sql diff --git a/db/changes/235001/01-newHasAnyPositiveBase.sql b/db/changes/235201/01-newHasAnyPositiveBase.sql similarity index 100% rename from db/changes/235001/01-newHasAnyPositiveBase.sql rename to db/changes/235201/01-newHasAnyPositiveBase.sql diff --git a/db/changes/235001/01-refactorHasAnyNegativeBase.sql b/db/changes/235201/01-refactorHasAnyNegativeBase.sql similarity index 100% rename from db/changes/235001/01-refactorHasAnyNegativeBase.sql rename to db/changes/235201/01-refactorHasAnyNegativeBase.sql From 584f3264edc86712c840998d5794c9b34c7fd632 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 11 Dec 2023 08:54:58 +0100 Subject: [PATCH 39/87] refs #6085 refactor sql trad --- .../{235001 => 235201}/00-aclsMails.sql | 0 front/core/locale/es.yml | 2 +- loopback/locale/es.json | 6 +- .../account/back/models/mail-alias-account.js | 14 ++--- modules/account/back/models/mail-alias-acl.js | 55 ------------------- 5 files changed, 9 insertions(+), 68 deletions(-) rename db/changes/{235001 => 235201}/00-aclsMails.sql (100%) delete mode 100644 modules/account/back/models/mail-alias-acl.js diff --git a/db/changes/235001/00-aclsMails.sql b/db/changes/235201/00-aclsMails.sql similarity index 100% rename from db/changes/235001/00-aclsMails.sql rename to db/changes/235201/00-aclsMails.sql diff --git a/front/core/locale/es.yml b/front/core/locale/es.yml index 1b9bbb40b..17e955ff5 100644 --- a/front/core/locale/es.yml +++ b/front/core/locale/es.yml @@ -68,4 +68,4 @@ Load more results: Cargar más resultados Send cau: Enviar cau By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc ExplainReason: Explique el motivo por el que no deberia aparecer este fallo -You already have the mailAlias: Ya tienes este mail +You already have the mailAlias: Ya tienes este alias de correo diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 2e516bf12..c26bf3ebc 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -330,6 +330,6 @@ "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}}", - "You already have the mailAlias": "You already have the mailAlias", - "The alias cant be modified": "The alias cant be modified" -} \ No newline at end of file + "You already have the mailAlias": "Ya tienes este alias de correo", + "The alias cant be modified": "Este alias de correo no puede ser modificado" +} diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index a95189689..91fc43008 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -22,12 +22,6 @@ module.exports = Self => { async function checkModifyPermission(ctx, mailAliasFk) { const userId = ctx.options.accessToken.userId; - const available = await Self.getAvailable(userId); - if (!available.has(mailAliasFk)) - throw new UserError('The alias cant be modified'); - } - - Self.getAvailable = async function(userId, options) { const models = Self.app.models; const myOptions = {}; @@ -47,9 +41,11 @@ module.exports = Self => { roleFk: { inq: roles.map(role => role.roleId), }, + mailAliasFk } }, myOptions); - const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk); - return new Set(mailAliasArray); - }; + + console.log(availableMailAlias); + if (!availableMailAlias.length) throw new UserError('The alias cant be modified'); + } }; diff --git a/modules/account/back/models/mail-alias-acl.js b/modules/account/back/models/mail-alias-acl.js deleted file mode 100644 index a95189689..000000000 --- a/modules/account/back/models/mail-alias-acl.js +++ /dev/null @@ -1,55 +0,0 @@ - -const UserError = require('vn-loopback/util/user-error'); - -module.exports = Self => { - Self.rewriteDbError(function(err) { - if (err.code === 'ER_DUP_ENTRY') - return new UserError(`You already have the mailAlias`); - return err; - }); - - Self.observe('before save', async ctx => { - const changes = ctx.currentInstance || ctx.instance; - - await checkModifyPermission(ctx, changes.mailAlias); - }); - - Self.observe('before delete', async ctx => { - const mailAliasAccount = await Self.findById(ctx.where.id); - - await checkModifyPermission(ctx, mailAliasAccount.mailAlias); - }); - - async function checkModifyPermission(ctx, mailAliasFk) { - const userId = ctx.options.accessToken.userId; - const available = await Self.getAvailable(userId); - if (!available.has(mailAliasFk)) - throw new UserError('The alias cant be modified'); - } - - Self.getAvailable = async function(userId, options) { - const models = Self.app.models; - - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const roles = await models.RoleMapping.find({ - fields: ['roleId'], - where: {principalId: userId} - }, myOptions); - - const availableMailAlias = await models.MailAliasAcl.find({ - fields: ['mailAliasFk'], - include: {relation: 'mailAlias'}, - where: { - roleFk: { - inq: roles.map(role => role.roleId), - }, - } - }, myOptions); - const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk); - return new Set(mailAliasArray); - }; -}; From 57ed36cdfc3a0015da94a0eacc74bb0bbcef1505 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 11 Dec 2023 09:43:38 +0100 Subject: [PATCH 40/87] ref #6085 remove console options --- modules/account/back/models/mail-alias-account.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index 91fc43008..cf9c73f3b 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -26,8 +26,7 @@ module.exports = Self => { const myOptions = {}; - if (typeof options == 'object') - Object.assign(myOptions, options); + Object.assign(myOptions); const roles = await models.RoleMapping.find({ fields: ['roleId'], @@ -45,7 +44,6 @@ module.exports = Self => { } }, myOptions); - console.log(availableMailAlias); if (!availableMailAlias.length) throw new UserError('The alias cant be modified'); } }; From 6ac5d28c4003cd7a192955d5538e5074e45d8b11 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 11 Dec 2023 09:59:09 +0100 Subject: [PATCH 41/87] refs #6085 fix back --- back/models/specs/mailAliasAccount.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/back/models/specs/mailAliasAccount.spec.js b/back/models/specs/mailAliasAccount.spec.js index d26ed2313..c13cc7ae8 100644 --- a/back/models/specs/mailAliasAccount.spec.js +++ b/back/models/specs/mailAliasAccount.spec.js @@ -6,8 +6,8 @@ describe('loopback model MailAliasAccount', () => { let error; try { - const options = {transaction: tx, accessToken: {userId: 1}}; - await models.MailAliasAccount.create({mailAliasFk: 2, roleFk: 5}, options); + const options = {transaction: tx, accessToken: {userId: 57}}; + await models.MailAliasAccount.create({mailAlias: 2, account: 5}, options); await tx.rollback(); } catch (e) { From 53ff8784ffd8c388b3f3607a1d09977980fa4cf3 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 11 Dec 2023 10:16:46 +0100 Subject: [PATCH 42/87] refs #6085 remove myOptions --- modules/account/back/models/mail-alias-account.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index cf9c73f3b..8f8e45ae8 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -24,14 +24,10 @@ module.exports = Self => { const userId = ctx.options.accessToken.userId; const models = Self.app.models; - const myOptions = {}; - - Object.assign(myOptions); - const roles = await models.RoleMapping.find({ fields: ['roleId'], where: {principalId: userId} - }, myOptions); + }); const availableMailAlias = await models.MailAliasAcl.find({ fields: ['mailAliasFk'], @@ -42,7 +38,7 @@ module.exports = Self => { }, mailAliasFk } - }, myOptions); + }); if (!availableMailAlias.length) throw new UserError('The alias cant be modified'); } From d1f0557923efb2fa1e774ad1b6a3a590fb94f27d Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Mon, 11 Dec 2023 12:40:16 +0100 Subject: [PATCH 43/87] refs #5666 perf: remove ruleAlias property --- front/core/directives/rule.js | 5 ----- modules/account/front/role/basic-data/index.html | 6 ++---- modules/account/front/role/card/index.spec.js | 4 ++-- modules/account/front/role/descriptor/index.spec.js | 4 ++-- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/front/core/directives/rule.js b/front/core/directives/rule.js index d944e13ed..34781c2aa 100644 --- a/front/core/directives/rule.js +++ b/front/core/directives/rule.js @@ -23,7 +23,6 @@ export function directive($translate, $window) { let rule = $attrs.rule.split('.'); let modelName = rule.shift(); let fieldName = rule.shift(); - let modelAlias = $attrs.ruleAlias; let split = $attrs.ngModel.split('.'); if (!fieldName) fieldName = split.pop() || null; if (!modelName) modelName = firstUpper(split.pop() || ''); @@ -31,12 +30,8 @@ export function directive($translate, $window) { if (!modelName || !fieldName) throw new Error(`rule: Cannot retrieve model or field attribute`); - let modelValidations = vnValidations[modelName]; - if (!modelValidations) - modelValidations = vnValidations[modelAlias]; - if (!modelValidations) throw new Error(`rule: Model '${modelName}' doesn't exist`); diff --git a/modules/account/front/role/basic-data/index.html b/modules/account/front/role/basic-data/index.html index 46cb080b7..846f8b455 100644 --- a/modules/account/front/role/basic-data/index.html +++ b/modules/account/front/role/basic-data/index.html @@ -14,15 +14,13 @@ diff --git a/modules/account/front/role/card/index.spec.js b/modules/account/front/role/card/index.spec.js index f39840e5f..f02c08f28 100644 --- a/modules/account/front/role/card/index.spec.js +++ b/modules/account/front/role/card/index.spec.js @@ -1,6 +1,6 @@ import './index'; -describe('component vnRoleCard', () => { +fdescribe('component vnRoleCard', () => { let controller; let $httpBackend; @@ -15,7 +15,7 @@ describe('component vnRoleCard', () => { it('should reload the controller data', () => { controller.$params.id = 1; - $httpBackend.expectGET('Roles/1').respond('foo'); + $httpBackend.expectGET('VnRoles/1').respond('foo'); controller.reload(); $httpBackend.flush(); diff --git a/modules/account/front/role/descriptor/index.spec.js b/modules/account/front/role/descriptor/index.spec.js index e2761c639..eafb96727 100644 --- a/modules/account/front/role/descriptor/index.spec.js +++ b/modules/account/front/role/descriptor/index.spec.js @@ -1,6 +1,6 @@ import './index'; -describe('component vnRoleDescriptor', () => { +fdescribe('component vnRoleDescriptor', () => { let controller; let $httpBackend; @@ -18,7 +18,7 @@ describe('component vnRoleDescriptor', () => { controller.$state.go = jest.fn(); jest.spyOn(controller.vnApp, 'showSuccess'); - $httpBackend.expectDELETE('Roles/1').respond(); + $httpBackend.expectDELETE('VnRoles/1').respond(); controller.onDelete(); $httpBackend.flush(); From 2beb1f65f09847b78ec5e486af4f359a36887cb0 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 11 Dec 2023 12:45:55 +0100 Subject: [PATCH 44/87] refs #6085 findOne --- modules/account/back/models/mail-alias-account.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/account/back/models/mail-alias-account.js b/modules/account/back/models/mail-alias-account.js index 8f8e45ae8..5eb561408 100644 --- a/modules/account/back/models/mail-alias-account.js +++ b/modules/account/back/models/mail-alias-account.js @@ -29,7 +29,7 @@ module.exports = Self => { where: {principalId: userId} }); - const availableMailAlias = await models.MailAliasAcl.find({ + const availableMailAlias = await models.MailAliasAcl.findOne({ fields: ['mailAliasFk'], include: {relation: 'mailAlias'}, where: { @@ -40,6 +40,6 @@ module.exports = Self => { } }); - if (!availableMailAlias.length) throw new UserError('The alias cant be modified'); + if (!availableMailAlias) throw new UserError('The alias cant be modified'); } }; From f817551a57f1e9b04682d642dfb4d5b7a926d84e Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Mon, 11 Dec 2023 12:59:02 +0100 Subject: [PATCH 45/87] refs #5666 perf: remove ruleAlias property --- modules/account/front/role/create/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/account/front/role/create/index.html b/modules/account/front/role/create/index.html index ee43484d7..77d6fc2c1 100644 --- a/modules/account/front/role/create/index.html +++ b/modules/account/front/role/create/index.html @@ -13,14 +13,14 @@ + ng-model="$ctrl.role.description" + rule="VnRole.description"> From 84270587cb8beeeab9db0aa56a5af1c1e26250d2 Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 11 Dec 2023 13:42:19 +0100 Subject: [PATCH 46/87] refs #6274 refactor --- modules/worker/back/methods/worker-time-control/addTimeEntry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/back/methods/worker-time-control/addTimeEntry.js b/modules/worker/back/methods/worker-time-control/addTimeEntry.js index 96e3a47d9..5dbac51ca 100644 --- a/modules/worker/back/methods/worker-time-control/addTimeEntry.js +++ b/modules/worker/back/methods/worker-time-control/addTimeEntry.js @@ -46,6 +46,6 @@ module.exports = Self => { if (!isSubordinate || (isHimself && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - return await Self.clockIn(workerId, args.timed, args.direction, myOptions); + return Self.clockIn(workerId, args.timed, args.direction, myOptions); }; }; From 412cac7e94114a891fc66111133de27eb29e8e40 Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 12 Dec 2023 14:42:36 +0100 Subject: [PATCH 47/87] refs #5925 models table docuware --- back/methods/docuware/upload.js | 5 +++++ back/models/docuwareTablet.json | 20 ++++++++++++++++++++ back/models/user-config.json | 10 +++++++++- db/changes/235201/00-tabletDocuware.sql | 24 ++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 back/models/docuwareTablet.json create mode 100644 db/changes/235201/00-tabletDocuware.sql diff --git a/back/methods/docuware/upload.js b/back/methods/docuware/upload.js index 7055bf8d5..a587079a2 100644 --- a/back/methods/docuware/upload.js +++ b/back/methods/docuware/upload.js @@ -103,6 +103,11 @@ module.exports = Self => { 'FieldName': 'FILTRO_TABLET', 'ItemElementName': 'string', 'Item': 'Tablet1', + }, + { + 'FieldName': 'ID_TABLET', + 'ItemElementName': 'integer', + 'Item': userConfig.tabletFk, } ] }; diff --git a/back/models/docuwareTablet.json b/back/models/docuwareTablet.json new file mode 100644 index 000000000..dde336bca --- /dev/null +++ b/back/models/docuwareTablet.json @@ -0,0 +1,20 @@ +{ + "name": "docuwareTablet", + "base": "VnModel", + "options": { + "mysql": { + "table": "vn.docuwareTablet" + } + }, + "properties": { + "id": { + "type": "number" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + } +} diff --git a/back/models/user-config.json b/back/models/user-config.json index 52125dc01..35f6aa1e6 100644 --- a/back/models/user-config.json +++ b/back/models/user-config.json @@ -26,6 +26,9 @@ }, "darkMode": { "type": "boolean" + }, + "tabletFk": { + "type": "number" } }, "relations": { @@ -43,6 +46,11 @@ "type": "belongsTo", "model": "VnUser", "foreignKey": "userFk" - } + }, + "Tablet": { + "type": "belongsTo", + "model": "docuwareTablet", + "foreignKey": "tabletFk" + } } } diff --git a/db/changes/235201/00-tabletDocuware.sql b/db/changes/235201/00-tabletDocuware.sql new file mode 100644 index 000000000..c480c1001 --- /dev/null +++ b/db/changes/235201/00-tabletDocuware.sql @@ -0,0 +1,24 @@ +-- vn.docuwareTablet definition + +CREATE TABLE `vn`.`docuwareTablet` ( + `id` int(3) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `description` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +-- Auto-generated SQL script. Actual values for binary/complex data types may differ - what you see is the default string representation of values. +INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) + VALUES (1,'tabletRRHH','tablet de recursos humanos'); +INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) + VALUES (2,'tabletIT','tablet de IT'); +INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) + VALUES (3,'tabletCompradores','tablet de compradores'); +INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) + VALUES (4,'tabletComerciales','tablet de comerciales'); +INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) + VALUES (5,'tabletAdministracion','tablet de administracion'); + +ALTER TABLE `vn`.`userConfig` +ADD COLUMN tabletFk int(3), +ADD FOREIGN KEY (tabletFk) REFERENCES `vn`.`docuwareTablet`(id); From 5f4adab017696ece18a9a94094567a58dfc1f631 Mon Sep 17 00:00:00 2001 From: robert Date: Tue, 12 Dec 2023 18:03:09 +0100 Subject: [PATCH 48/87] refs #5854 --- modules/item/back/locale/item-shelving/es.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/item/back/locale/item-shelving/es.yml b/modules/item/back/locale/item-shelving/es.yml index a64b23bfa..3aedcd0bf 100644 --- a/modules/item/back/locale/item-shelving/es.yml +++ b/modules/item/back/locale/item-shelving/es.yml @@ -5,8 +5,8 @@ columns: shelvingFk: matrícula carro visible: visible created: creado - grouping: agrupación - packing: embalaje + grouping: grouping + packing: packing packagingFk: paquete userFk: usuario isChecked: está revisado From 2393625a48ddbaf72f33be6420212fa3b8e3d232 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 13 Dec 2023 08:22:58 +0100 Subject: [PATCH 49/87] refs #5925 Tablet --- back/methods/docuware/upload.js | 17 +++++++++++------ back/models/docuwareTablet.json | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/back/methods/docuware/upload.js b/back/methods/docuware/upload.js index a587079a2..0af20b8ac 100644 --- a/back/methods/docuware/upload.js +++ b/back/methods/docuware/upload.js @@ -56,6 +56,16 @@ module.exports = Self => { }] }); + // get tablet + const tablet = await models.userConfig.findById(id, { + include: [{ + relation: 'Tablet', + scope: { + fields: ['id'] + } + }] + }); + // upload file const templateJson = { 'Fields': [ @@ -102,12 +112,7 @@ module.exports = Self => { { 'FieldName': 'FILTRO_TABLET', 'ItemElementName': 'string', - 'Item': 'Tablet1', - }, - { - 'FieldName': 'ID_TABLET', - 'ItemElementName': 'integer', - 'Item': userConfig.tabletFk, + 'Item': tablet.id, } ] }; diff --git a/back/models/docuwareTablet.json b/back/models/docuwareTablet.json index dde336bca..e9e3b6bad 100644 --- a/back/models/docuwareTablet.json +++ b/back/models/docuwareTablet.json @@ -3,7 +3,7 @@ "base": "VnModel", "options": { "mysql": { - "table": "vn.docuwareTablet" + "table": "docuwareTablet" } }, "properties": { From 5b3645a6419e765cf186b4280d22594f83acfb7d Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 13 Dec 2023 11:59:00 +0100 Subject: [PATCH 50/87] refs #6434 fix: bad merge --- back/models/vn-user.js | 27 +++++++++++++++++++ db/changes/234801/00-createSignInLogTable.sql | 19 ------------- 2 files changed, 27 insertions(+), 19 deletions(-) delete mode 100644 db/changes/234801/00-createSignInLogTable.sql diff --git a/back/models/vn-user.js b/back/models/vn-user.js index d840e34e8..7b1471e5c 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -125,6 +125,33 @@ module.exports = function(Self) { return email.send(); }); + /** + * Sign-in validate + * @param {String} user The user + * @param {Object} userToken Options + * @param {Object} token accessToken + * @param {Object} ctx context + */ + Self.signInValidate = async(user, userToken, token, ctx) => { + const [[key, value]] = Object.entries(Self.userUses(user)); + const isOwner = Self.rawSql(`SELECT ? = ? `, [userToken[key], value]); + await Self.app.models.SignInLog.create({ + userName: user, + token: token.id, + userFk: userToken.id, + ip: ctx.req.ip, + owner: isOwner + }); + if (!isOwner) + throw new UserError('Try again'); + }; + + /** + * Validate login params + * @param {String} user The user + * @param {String} password + * @param {Object} ctx context + */ Self.validateLogin = async function(user, password) { let loginInfo = Object.assign({password}, Self.userUses(user)); token = await Self.login(loginInfo, 'user'); diff --git a/db/changes/234801/00-createSignInLogTable.sql b/db/changes/234801/00-createSignInLogTable.sql deleted file mode 100644 index 977de4646..000000000 --- a/db/changes/234801/00-createSignInLogTable.sql +++ /dev/null @@ -1,19 +0,0 @@ - - --- --- Table structure for table `signInLog` --- - -DROP TABLE IF EXISTS `account`.`signInLog`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `account`.`signInLog` ( - `id` varchar(10) NOT NULL , - `userFk` int(10) unsigned DEFAULT NULL, - `creationDate` timestamp NULL DEFAULT current_timestamp(), - `ip` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, - PRIMARY KEY (`id`), - KEY `userFk` (`userFk`), - CONSTRAINT `signInLog_ibfk_1` FOREIGN KEY (`userFk`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -); - From 5f93b8c44032a4b982d23383b8c5158f721e9817 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 13 Dec 2023 12:01:18 +0100 Subject: [PATCH 51/87] refs #6434 fix: bad merge --- back/models/vn-user.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 7b1471e5c..e14cd30ea 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -152,9 +152,9 @@ module.exports = function(Self) { * @param {String} password * @param {Object} ctx context */ - Self.validateLogin = async function(user, password) { - let loginInfo = Object.assign({password}, Self.userUses(user)); - token = await Self.login(loginInfo, 'user'); + Self.validateLogin = async function(user, password, ctx) { + const loginInfo = Object.assign({password}, Self.userUses(user)); + const token = await Self.login(loginInfo, 'user'); const userToken = await token.user.get(); From 4e8bec5684935258b23f2d30c568f0ad745c36d8 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 13 Dec 2023 12:03:04 +0100 Subject: [PATCH 52/87] refs #5925 user error --- back/methods/docuware/upload.js | 2 ++ loopback/locale/es.json | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/back/methods/docuware/upload.js b/back/methods/docuware/upload.js index 0af20b8ac..5f44e9382 100644 --- a/back/methods/docuware/upload.js +++ b/back/methods/docuware/upload.js @@ -120,6 +120,8 @@ module.exports = Self => { if (process.env.NODE_ENV != 'production') throw new UserError('Action not allowed on the test environment'); + if (!tablet.id) + throw new UserError('This user does not have an assigned tablet.'); // delete old const docuwareFile = await models.Docuware.checkFile(id, fileCabinet, false); if (docuwareFile) { diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 01384efb4..4a2e9a794 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -329,5 +329,6 @@ "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", "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 + "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", + "This user does not have an assigned tablet.": "Este usuario no tiene tablet asignada" +} From 6af99b7669f0ff0ac8a5b4110993686968d11dd5 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 13 Dec 2023 12:07:41 +0100 Subject: [PATCH 53/87] refs #6434 feat: delete records whe !owner --- db/changes/235201/00-truncate-where-signInLog.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 db/changes/235201/00-truncate-where-signInLog.sql diff --git a/db/changes/235201/00-truncate-where-signInLog.sql b/db/changes/235201/00-truncate-where-signInLog.sql new file mode 100644 index 000000000..93d80d716 --- /dev/null +++ b/db/changes/235201/00-truncate-where-signInLog.sql @@ -0,0 +1 @@ +DELETE FROM `account`.`signInLog` where owner <> FALSE From 5a36fabf058153792cda778c7e0e01c3b52588d1 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 13 Dec 2023 12:07:57 +0100 Subject: [PATCH 54/87] refs #6434 feat: insert record just when fail --- back/models/vn-user.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/back/models/vn-user.js b/back/models/vn-user.js index e14cd30ea..1134df363 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -135,15 +135,16 @@ module.exports = function(Self) { Self.signInValidate = async(user, userToken, token, ctx) => { const [[key, value]] = Object.entries(Self.userUses(user)); const isOwner = Self.rawSql(`SELECT ? = ? `, [userToken[key], value]); - await Self.app.models.SignInLog.create({ - userName: user, - token: token.id, - userFk: userToken.id, - ip: ctx.req.ip, - owner: isOwner - }); - if (!isOwner) - throw new UserError('Try again'); + if (!isOwner) { + await Self.app.models.SignInLog.create({ + userName: user, + token: token.id, + userFk: userToken.id, + ip: ctx.req.ip, + owner: isOwner + }); + } + throw new UserError('Try again'); }; /** From 11b54d66af6f77158441e0627186c128d3c5234c Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 13 Dec 2023 13:31:32 +0100 Subject: [PATCH 55/87] refs #6434 fix: bad merge --- back/methods/vn-user/sign-in.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/back/methods/vn-user/sign-in.js b/back/methods/vn-user/sign-in.js index 9626e2e79..782046641 100644 --- a/back/methods/vn-user/sign-in.js +++ b/back/methods/vn-user/sign-in.js @@ -40,14 +40,11 @@ module.exports = Self => { const validCredentials = vnUser && await vnUser.hasPassword(password); - if (!validCredentials) - throw new UserError('Invalid credentials'); - - if (!vnUser.active) - throw new UserError('User disabled'); - - await Self.sendTwoFactor(ctx, vnUser, myOptions); - await Self.passExpired(vnUser, myOptions); + if (validCredentials) { + if (!vnUser.active) + throw new UserError('User disabled'); + await Self.sendTwoFactor(ctx, vnUser, myOptions); + await Self.passExpired(vnUser, myOptions); if (vnUser.twoFactor) throw new ForbiddenError(null, 'REQUIRES_2FA'); From b9efbc7d4413c363bca6431f6ba7423ff55cc993 Mon Sep 17 00:00:00 2001 From: robert Date: Wed, 13 Dec 2023 14:30:29 +0100 Subject: [PATCH 56/87] refs #5854 --- modules/item/back/locale/item-shelving/en.yml | 10 +++++----- modules/item/back/locale/item-shelving/es.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/item/back/locale/item-shelving/en.yml b/modules/item/back/locale/item-shelving/en.yml index 062d4db3f..997815b2c 100644 --- a/modules/item/back/locale/item-shelving/en.yml +++ b/modules/item/back/locale/item-shelving/en.yml @@ -1,13 +1,13 @@ name: itemShelving columns: id: id - itemFk: itemFk - shelvingFk: shelvingFk + itemFk: item + shelvingFk: shelving visible: visible created: created grouping: grouping packing: packing - packagingFk: packagingFk - userFk: userFk + packagingFk: package + userFk: user isChecked: isChecked - buyFk: buyFk + buyFk: buy diff --git a/modules/item/back/locale/item-shelving/es.yml b/modules/item/back/locale/item-shelving/es.yml index 3aedcd0bf..f00dfd6c5 100644 --- a/modules/item/back/locale/item-shelving/es.yml +++ b/modules/item/back/locale/item-shelving/es.yml @@ -7,7 +7,7 @@ columns: created: creado grouping: grouping packing: packing - packagingFk: paquete + packagingFk: embalaje userFk: usuario isChecked: está revisado buyFk: compra \ No newline at end of file From 21a1dbeae7fe4a9d9fe75ef910efbdb0fd023dde Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 14 Dec 2023 15:56:49 +0100 Subject: [PATCH 57/87] refs #5914 fix: ticket canBeInvoiced and optimized invoiceTickets --- .../235201/01-refactorHasAnyNegativeBase.sql | 1 + db/dump/fixtures.sql | 2 +- e2e/paths/05-ticket/18_index_payout.spec.js | 2 +- e2e/paths/09-invoice-out/01_summary.spec.js | 4 +-- loopback/locale/en.json | 6 ++-- loopback/locale/es.json | 9 +++-- .../methods/client/specs/consumption.spec.js | 4 +-- .../invoiceOut/specs/transferinvoice.spec.js | 26 ++++++++++++++- .../front/descriptor-menu/index.html | 2 +- .../invoiceOut/front/index/manual/index.html | 1 + .../back/methods/ticket/canBeInvoiced.js | 23 +++---------- .../back/methods/ticket/invoiceTickets.js | 33 ++++++++----------- .../ticket/back/methods/ticket/makeInvoice.js | 2 +- 13 files changed, 64 insertions(+), 51 deletions(-) diff --git a/db/changes/235201/01-refactorHasAnyNegativeBase.sql b/db/changes/235201/01-refactorHasAnyNegativeBase.sql index b6780e280..65822fc95 100644 --- a/db/changes/235201/01-refactorHasAnyNegativeBase.sql +++ b/db/changes/235201/01-refactorHasAnyNegativeBase.sql @@ -26,3 +26,4 @@ BEGIN END$$ DELIMITER ; + diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 874e42787..127bf5ef0 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -720,7 +720,7 @@ INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agen INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`) VALUES (1 , 3, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 121, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1), - (2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2), + (2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 1, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2), (3 , 1, 7, 1, 6, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL), (4 , 3, 2, 1, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 9, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL), (5 , 3, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL), diff --git a/e2e/paths/05-ticket/18_index_payout.spec.js b/e2e/paths/05-ticket/18_index_payout.spec.js index 7e5201d11..9c5518424 100644 --- a/e2e/paths/05-ticket/18_index_payout.spec.js +++ b/e2e/paths/05-ticket/18_index_payout.spec.js @@ -35,7 +35,7 @@ describe('Ticket index payout path', () => { await page.waitToClick(selectors.ticketsIndex.openAdvancedSearchButton); await page.write(selectors.ticketsIndex.advancedSearchClient, '1101'); await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketsIndex.anySearchResult, 9); + await page.waitForNumberOfElements(selectors.ticketsIndex.anySearchResult, 10); await page.waitToClick(selectors.ticketsIndex.firstTicketCheckbox); await page.waitToClick(selectors.ticketsIndex.secondTicketCheckbox); diff --git a/e2e/paths/09-invoice-out/01_summary.spec.js b/e2e/paths/09-invoice-out/01_summary.spec.js index 728f0130a..09ac66ffc 100644 --- a/e2e/paths/09-invoice-out/01_summary.spec.js +++ b/e2e/paths/09-invoice-out/01_summary.spec.js @@ -28,7 +28,6 @@ describe('InvoiceOut summary path', () => { it('should contain the tax breakdown', async() => { const firstTax = await page.waitToGetProperty(selectors.invoiceOutSummary.taxOne, 'innerText'); - const secondTax = await page.waitToGetProperty(selectors.invoiceOutSummary.taxTwo, 'innerText'); expect(firstTax).toContain('10%'); @@ -37,10 +36,9 @@ describe('InvoiceOut summary path', () => { it('should contain the tickets info', async() => { const firstTicket = await page.waitToGetProperty(selectors.invoiceOutSummary.ticketOne, 'innerText'); - const secondTicket = await page.waitToGetProperty(selectors.invoiceOutSummary.ticketTwo, 'innerText'); expect(firstTicket).toContain('Bat cave'); - expect(secondTicket).toContain('Stark tower'); + expect(secondTicket).toContain('Bat cave'); }); }); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 7d5b5ed47..962e1ea13 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -45,6 +45,7 @@ "Extension format is invalid": "Extension format is invalid", "NO_ZONE_FOR_THIS_PARAMETERS": "NO_ZONE_FOR_THIS_PARAMETERS", "This client can't be invoiced": "This client can't be invoiced", + "You must provide the correction information to generate a corrective invoice": "You must provide the correction information to generate a corrective invoice", "The introduced hour already exists": "The introduced hour already exists", "Invalid parameters to create a new ticket": "Invalid parameters to create a new ticket", "Concept cannot be blank": "Concept cannot be blank", @@ -178,7 +179,8 @@ "The renew period has not been exceeded": "The renew period has not been exceeded", "You can not use the same password": "You can not use the same password", "Valid priorities": "Valid priorities: %d", - "Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}", + "hasAnyNegativeBase": "Negative basis of tickets: {{ticketsIds}}", + "hasAnyPositiveBase": "Positive basis of tickets: {{ticketsIds}}", "This ticket cannot be left empty.": "This ticket cannot be left empty. %s", "Social name should be uppercase": "Social name should be uppercase", "Street should be uppercase": "Street should be uppercase", @@ -201,4 +203,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 e544be0e6..0c2ad3238 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -72,6 +72,7 @@ "The secret can't be blank": "La contraseña no puede estar en blanco", "We weren't able to send this SMS": "No hemos podido enviar el SMS", "This client can't be invoiced": "Este cliente no puede ser facturado", + "You must provide the correction information to generate a corrective invoice": "Debes informar la información de corrección para generar una factura rectificativa", "This ticket can't be invoiced": "Este ticket no puede ser facturado", "You cannot add or modify services to an invoiced ticket": "No puedes añadir o modificar servicios a un ticket facturado", "This ticket can not be modified": "Este ticket no puede ser modificado", @@ -305,7 +306,8 @@ "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico", "The renew period has not been exceeded": "El periodo de renovación no ha sido superado", "Valid priorities": "Prioridades válidas: %d", - "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}", + "hasAnyNegativeBase": "Base negativa para los tickets: {{ticketsIds}}", + "hasAnyPositiveBase": "Base positivas para los tickets: {{ticketsIds}}", "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado", "This ticket cannot be left empty.": "Este ticket no se puede dejar vacío. %s", "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias", @@ -330,5 +332,8 @@ "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", "No tickets to invoice": "No hay tickets para facturar", - "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}" + "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", + "Base negativa para los tickets: 39": "Base negativa para los tickets: 39", + "Base negativa para los tickets: 41": "Base negativa para los tickets: 41", + "keepPrice": "keepPrice" } diff --git a/modules/client/back/methods/client/specs/consumption.spec.js b/modules/client/back/methods/client/specs/consumption.spec.js index 47a495d79..85dbb7422 100644 --- a/modules/client/back/methods/client/specs/consumption.spec.js +++ b/modules/client/back/methods/client/specs/consumption.spec.js @@ -16,7 +16,7 @@ describe('client consumption() filter', () => { }; const result = await models.Client.consumption(ctx, filter, options); - expect(result.length).toEqual(10); + expect(result.length).toEqual(11); await tx.rollback(); } catch (e) { @@ -49,7 +49,7 @@ describe('client consumption() filter', () => { const thirdRow = result[2]; expect(result.length).toEqual(3); - expect(firstRow.quantity).toEqual(10); + expect(firstRow.quantity).toEqual(11); expect(secondRow.quantity).toEqual(15); expect(thirdRow.quantity).toEqual(20); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js index b3bd17826..11575999a 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js @@ -2,7 +2,7 @@ const models = require('vn-loopback/server/server').models; const LoopBackContext = require('loopback-context'); -describe('InvoiceOut tranferInvoice()', () => { +describe('InvoiceOut transferInvoice()', () => { const activeCtx = { accessToken: {userId: 5}, http: { @@ -69,9 +69,33 @@ describe('InvoiceOut tranferInvoice()', () => { await models.InvoiceOut.transferInvoice( ctx, options); + await tx.rollback(); } catch (e) { expect(e.message).toBe(`Select a different client`); await tx.rollback(); } }); + + it('should throw an UserError when it is refund', async() => { + const tx = await models.InvoiceOut.beginTransaction({}); + const options = {transaction: tx}; + const args = { + id: '1', + refFk: 'T1111111', + newClientFk: 1102, + cplusRectificationTypeFk: 1, + siiTypeInvoiceOutFk: 1, + invoiceCorrectionTypeFk: 1 + }; + ctx.args = args; + try { + await models.InvoiceOut.transferInvoice( + ctx, + options); + await tx.rollback(); + } catch (e) { + expect(e.message).toContain(`This ticket is already a refund`); + await tx.rollback(); + } + }); }); diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html index 267aa0b15..435db3612 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.html +++ b/modules/invoiceOut/front/descriptor-menu/index.html @@ -227,7 +227,7 @@ vn-one vn-id="siiTypeInvoiceOut" data="siiTypeInvoiceOuts" - show-field="code" + show-field="description" value-field="id" fields="['id','code','description']" required="true" diff --git a/modules/invoiceOut/front/index/manual/index.html b/modules/invoiceOut/front/index/manual/index.html index c3362a319..5872911e4 100644 --- a/modules/invoiceOut/front/index/manual/index.html +++ b/modules/invoiceOut/front/index/manual/index.html @@ -6,6 +6,7 @@ auto-load="true" url="InvoiceOutSerials" data="invoiceOutSerials" + where="{code: {neq: 'R'}}" order="code"> { diff --git a/modules/ticket/back/methods/ticket/invoiceTickets.js b/modules/ticket/back/methods/ticket/invoiceTickets.js index 212f6556a..f1793773b 100644 --- a/modules/ticket/back/methods/ticket/invoiceTickets.js +++ b/modules/ticket/back/methods/ticket/invoiceTickets.js @@ -47,10 +47,10 @@ module.exports = function(Self) { let invoicesIds = []; try { const tickets = await models.Ticket.find({ + fields: ['id', 'clientFk', 'companyFk', 'addressFk'], where: { id: {inq: ticketsIds} - }, - fields: ['id', 'clientFk', 'companyFk'] + } }, myOptions); const [firstTicket] = tickets; @@ -65,18 +65,17 @@ module.exports = function(Self) { fields: ['id', 'hasToInvoiceByAddress'] }, myOptions); + let ticketsByAddress = {[firstTicket.addressFk]: ticketsIds}; if (client.hasToInvoiceByAddress) { - const query = ` - SELECT DISTINCT addressFk - FROM ticket t - WHERE id IN (?)`; - const result = await Self.rawSql(query, [ticketsIds], myOptions); - - const addressIds = result.map(address => address.addressFk); - for (const address of addressIds) - await createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, invoiceCorrection, myOptions); - } else - await createInvoice(ctx, companyId, ticketsIds, null, invoicesIds, invoiceCorrection, myOptions); + ticketsByAddress = tickets.reduce((group, ticket) => { + const {addressFk} = ticket; + group[addressFk] = group[addressFk] ?? []; + group[addressFk].push(ticket.id); + return group; + }, {}); + } + for (const ticketIds of Object.values(ticketsByAddress)) + invoicesIds.push(await createInvoice(ctx, companyId, ticketIds, invoiceCorrection, myOptions)); if (tx) await tx.commit(); } catch (e) { @@ -91,7 +90,7 @@ module.exports = function(Self) { return invoicesIds; }; - async function createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, invoiceCorrection, myOptions) { + async function createInvoice(ctx, companyId, ticketsIds, invoiceCorrection, myOptions) { const models = Self.app.models; await models.Ticket.rawSql(` CREATE OR REPLACE TEMPORARY TABLE tmp.ticketToInvoice @@ -100,12 +99,8 @@ module.exports = function(Self) { SELECT id FROM vn.ticket WHERE id IN (?) - ${address ? `AND addressFk = ${address}` : ''} `, [ticketsIds], myOptions); - - const invoiceId = - await models.Ticket.makeInvoice(ctx, 'R', companyId, Date.vnNew(), invoiceCorrection, myOptions); - invoicesIds.push(invoiceId); + return models.Ticket.makeInvoice(ctx, 'R', companyId, Date.vnNew(), invoiceCorrection, myOptions); } }; diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index fe7e527c8..32aa03f9d 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -106,7 +106,7 @@ module.exports = function(Self) { ); } - if (resultInvoice.id) // serial != 'R' && + if (resultInvoice.id) await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions); if (tx) await tx.commit(); From c755b1e6fa7f948b78d9de47e6fad5c43f14a198 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 15 Dec 2023 08:50:22 +0100 Subject: [PATCH 58/87] refs #5914 fix: correct sql version --- db/changes/{235201 => 235001}/00-getTaxBases.sql | 0 db/changes/{235201 => 235001}/01-newHasAnyPositiveBase.sql | 0 db/changes/{235201 => 235001}/01-refactorHasAnyNegativeBase.sql | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename db/changes/{235201 => 235001}/00-getTaxBases.sql (100%) rename db/changes/{235201 => 235001}/01-newHasAnyPositiveBase.sql (100%) rename db/changes/{235201 => 235001}/01-refactorHasAnyNegativeBase.sql (100%) diff --git a/db/changes/235201/00-getTaxBases.sql b/db/changes/235001/00-getTaxBases.sql similarity index 100% rename from db/changes/235201/00-getTaxBases.sql rename to db/changes/235001/00-getTaxBases.sql diff --git a/db/changes/235201/01-newHasAnyPositiveBase.sql b/db/changes/235001/01-newHasAnyPositiveBase.sql similarity index 100% rename from db/changes/235201/01-newHasAnyPositiveBase.sql rename to db/changes/235001/01-newHasAnyPositiveBase.sql diff --git a/db/changes/235201/01-refactorHasAnyNegativeBase.sql b/db/changes/235001/01-refactorHasAnyNegativeBase.sql similarity index 100% rename from db/changes/235201/01-refactorHasAnyNegativeBase.sql rename to db/changes/235001/01-refactorHasAnyNegativeBase.sql From 59f2e3d0e62c16c1822210bb7a71730bd3625025 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 15 Dec 2023 08:54:41 +0100 Subject: [PATCH 59/87] refs #5914 fix: remove unnecessary --- db/dump/structure.sql | 30 ------------------------------ loopback/locale/es.json | 3 +-- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 4e1695185..1db4252f4 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -26391,36 +26391,6 @@ CREATE TABLE `cplusCorrectingType` ( ) ENGINE=InnoDBDEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `cplusInvoiceType472` --- - -DROP TABLE IF EXISTS `cplusInvoiceType472`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `cplusInvoiceType472` ( - `id` int(10) unsigned NOT NULL, - `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='(*18) TIPO FACTURA (Asientos)SOPORTADO – DEDUCIBLE (472)'; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `siiTypeInvoiceOut` --- - -DROP TABLE IF EXISTS `siiTypeInvoiceOut`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `siiTypeInvoiceOut` ( - `id` int(10) unsigned NOT NULL, - `code` varchar(2) NOT NULL, - `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `code_UNIQUE` (`code`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Tipo de Factura Emitidas en el suministro de inmediato'; -/*!40101 SET character_set_client = @saved_cs_client */; - -- -- Table structure for table `cplusRectificationType` -- diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 0c2ad3238..3a1cdfe99 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -334,6 +334,5 @@ "No tickets to invoice": "No hay tickets para facturar", "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", "Base negativa para los tickets: 39": "Base negativa para los tickets: 39", - "Base negativa para los tickets: 41": "Base negativa para los tickets: 41", - "keepPrice": "keepPrice" + "Base negativa para los tickets: 41": "Base negativa para los tickets: 41" } From 356fe6869635c241b897e8531b202aebe46b563c Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 15 Dec 2023 08:57:09 +0100 Subject: [PATCH 60/87] refs #5914 fix: remove unnecessary translation --- loopback/locale/es.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 3a1cdfe99..e137beb2d 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -332,7 +332,5 @@ "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", "No tickets to invoice": "No hay tickets para facturar", - "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", - "Base negativa para los tickets: 39": "Base negativa para los tickets: 39", - "Base negativa para los tickets: 41": "Base negativa para los tickets: 41" + "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}" } From 7777696cf75d7ce20c18bdc48f40ad251a0a5b6f Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 19 Dec 2023 13:58:08 +0100 Subject: [PATCH 61/87] refs #6589 fix(worker_absences): fix started hours --- modules/worker/back/methods/calendar/absences.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/worker/back/methods/calendar/absences.js b/modules/worker/back/methods/calendar/absences.js index 8420ed770..8a5d18987 100644 --- a/modules/worker/back/methods/calendar/absences.js +++ b/modules/worker/back/methods/calendar/absences.js @@ -39,6 +39,7 @@ module.exports = Self => { started.setFullYear(year); started.setMonth(0); started.setDate(1); + started.setHours(0, 0, 0, 0); const ended = Date.vnNew(); ended.setFullYear(year); From 57b3d96628ff5a1d7618d3741373ab84d061e4a4 Mon Sep 17 00:00:00 2001 From: JAVIER SEGARRA MARTINEZ Date: Wed, 20 Dec 2023 09:27:25 +0000 Subject: [PATCH 62/87] refs #6434 fix: bad throw error --- back/models/vn-user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 7b8a308c2..b1d09f0c0 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -142,8 +142,8 @@ module.exports = function(Self) { ip: ctx.req.ip, owner: isOwner }); - } throw new UserError('Try again'); + } }; /** From cb35c3632802ea9b94d41f8bb9fa321ed4b5c10f Mon Sep 17 00:00:00 2001 From: JAVIER SEGARRA MARTINEZ Date: Wed, 20 Dec 2023 10:59:36 +0000 Subject: [PATCH 63/87] refs #6434 test: update tests --- back/methods/vn-user/specs/sign-in.spec.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/back/methods/vn-user/specs/sign-in.spec.js b/back/methods/vn-user/specs/sign-in.spec.js index 1c4b4af51..a14dd301e 100644 --- a/back/methods/vn-user/specs/sign-in.spec.js +++ b/back/methods/vn-user/specs/sign-in.spec.js @@ -20,10 +20,7 @@ describe('VnUser Sign-in()', () => { let ctx = {req: {accessToken: accessToken}}; let signInLog = await SignInLog.find({where: {token: accessToken.id}}); - expect(signInLog.length).toEqual(1); - expect(signInLog[0].userFk).toEqual(accessToken.userId); - expect(signInLog[0].owner).toEqual(true); - expect(login.token).toBeDefined(); + expect(signInLog.length).toEqual(0); await VnUser.logout(ctx.req.accessToken.id); }); From 542b09073e627bd4cc442c2a98979e370cdedf54 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 20 Dec 2023 14:02:05 +0100 Subject: [PATCH 64/87] changes moved: refs #6274 --- db/changes/{235001 => 235201}/00-timecontrol.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{235001 => 235201}/00-timecontrol.sql (100%) diff --git a/db/changes/235001/00-timecontrol.sql b/db/changes/235201/00-timecontrol.sql similarity index 100% rename from db/changes/235001/00-timecontrol.sql rename to db/changes/235201/00-timecontrol.sql From f384616d693ae5c3121effb1baa815e4388c9865 Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 21 Dec 2023 08:57:46 +0100 Subject: [PATCH 65/87] move changes: refs #6274 --- db/changes/{235001 => 240201}/00-updateCourtesyTime.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{235001 => 240201}/00-updateCourtesyTime.sql (100%) diff --git a/db/changes/235001/00-updateCourtesyTime.sql b/db/changes/240201/00-updateCourtesyTime.sql similarity index 100% rename from db/changes/235001/00-updateCourtesyTime.sql rename to db/changes/240201/00-updateCourtesyTime.sql From 0f20f95dc581f9454f84f8f944812735083a411b Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 21 Dec 2023 10:08:17 +0100 Subject: [PATCH 66/87] refactor: refs #6433 Deleted isPreviousPrepared* columns in model --- modules/shelving/back/models/sector.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/modules/shelving/back/models/sector.json b/modules/shelving/back/models/sector.json index 47d66bd8d..5ff67491b 100644 --- a/modules/shelving/back/models/sector.json +++ b/modules/shelving/back/models/sector.json @@ -20,18 +20,10 @@ "type": "number", "required": true }, - "isPreviousPreparedByPacking": { - "type": "boolean", - "required": true - }, "code": { "type": "string", "required": false }, - "isPreviousPrepared": { - "type": "boolean", - "required": true - }, "isPackagingArea": { "type": "boolean", "required": true From dc661f298bfe6c8f4f858bbee0097472435c7379 Mon Sep 17 00:00:00 2001 From: JAVIER SEGARRA MARTINEZ Date: Thu, 21 Dec 2023 09:10:18 +0000 Subject: [PATCH 67/87] refs #6434 test: update tests --- back/methods/vn-user/specs/renew-token.spec.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/back/methods/vn-user/specs/renew-token.spec.js b/back/methods/vn-user/specs/renew-token.spec.js index 674ce36f4..146f6eb0c 100644 --- a/back/methods/vn-user/specs/renew-token.spec.js +++ b/back/methods/vn-user/specs/renew-token.spec.js @@ -27,8 +27,10 @@ describe('Renew Token', () => { jasmine.clock().uninstall(); }); - it('should renew process', async() => { - jasmine.clock().mockDate(new Date(startingTime + 21600000)); + it('should renew token', async() => { + const mockDate = new Date(startingTime + 26600000); + jasmine.clock().mockDate(mockDate); + console.log(startingTime, mockDate) const {id} = await models.VnUser.renewToken(ctx); expect(id).not.toEqual(ctx.req.accessToken.id); From 9951e911ae302e09c08813cbb98ceb038bfbd3c2 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 21 Dec 2023 10:39:46 +0100 Subject: [PATCH 68/87] refs #5925 feat(docuware_upload): use userConfig.tabletFk --- .vscode/settings.json | 2 +- back/methods/docuware/specs/upload.spec.js | 31 +++++++++++++-- back/methods/docuware/upload.js | 46 +++++++++++----------- back/models/docuwareTablet.json | 5 +-- back/models/user-config.json | 2 +- db/changes/235201/00-tabletDocuware.sql | 24 ----------- db/changes/240201/00-tabletDocuware.sql | 10 +++++ db/dump/fixtures.sql | 5 +++ loopback/locale/es.json | 2 +- 9 files changed, 70 insertions(+), 57 deletions(-) delete mode 100644 db/changes/235201/00-tabletDocuware.sql create mode 100644 db/changes/240201/00-tabletDocuware.sql diff --git a/.vscode/settings.json b/.vscode/settings.json index 40ec5c0d3..36b7e21d8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,7 @@ // Carácter predeterminado de final de línea. "files.eol": "\n", "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "search.useIgnoreFiles": false, "editor.defaultFormatter": "dbaeumer.vscode-eslint", diff --git a/back/methods/docuware/specs/upload.spec.js b/back/methods/docuware/specs/upload.spec.js index 3b8c55a50..2577fa42d 100644 --- a/back/methods/docuware/specs/upload.spec.js +++ b/back/methods/docuware/specs/upload.spec.js @@ -24,15 +24,40 @@ describe('docuware upload()', () => { }); it('should try upload file', async() => { + const tx = await models.Docuware.beginTransaction({}); spyOn(ticketModel, 'deliveryNotePdf').and.returnValue(new Promise(resolve => resolve({}))); let error; try { - await models.Docuware.upload(ctx, ticketIds, fileCabinetName); + const options = {transaction: tx}; + const user = await models.UserConfig.findById(userId, null, options); + await user.updateAttribute('tabletFk', 'Tablet1'); + await models.Docuware.upload(ctx, ticketIds, fileCabinetName, options); + + await tx.rollback(); } catch (e) { - error = e.message; + error = e; + await tx.rollback(); } - expect(error).toEqual('Action not allowed on the test environment'); + expect(error.message).toEqual('Action not allowed on the test environment'); + }); + + it('should throw error when not have tablet assigned', async() => { + const tx = await models.Docuware.beginTransaction({}); + spyOn(ticketModel, 'deliveryNotePdf').and.returnValue(new Promise(resolve => resolve({}))); + + let error; + try { + const options = {transaction: tx}; + await models.Docuware.upload(ctx, ticketIds, fileCabinetName, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual('This user does not have an assigned tablet'); }); }); diff --git a/back/methods/docuware/upload.js b/back/methods/docuware/upload.js index 5f44e9382..27be72295 100644 --- a/back/methods/docuware/upload.js +++ b/back/methods/docuware/upload.js @@ -29,12 +29,24 @@ module.exports = Self => { } }); - Self.upload = async function(ctx, ticketIds, fileCabinet) { + Self.upload = async function(ctx, ticketIds, fileCabinet, options) { delete ctx.args.ticketIds; const models = Self.app.models; const action = 'store'; - const options = await Self.getOptions(); + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const userConfig = await models.UserConfig.findById(ctx.req.accessToken.userId, { + fields: ['tabletFk'] + }, myOptions); + + if (!userConfig?.tabletFk) + throw new UserError('This user does not have an assigned tablet'); + + const docuwareOptions = await Self.getOptions(); const fileCabinetId = await Self.getFileCabinet(fileCabinet); const dialogId = await Self.getDialog(fileCabinet, action, fileCabinetId); @@ -45,7 +57,7 @@ module.exports = Self => { const deliveryNote = await models.Ticket.deliveryNotePdf(ctx, { id, type: 'deliveryNote' - }); + }, myOptions); // get ticket data const ticket = await models.Ticket.findById(id, { include: [{ @@ -54,17 +66,7 @@ module.exports = Self => { fields: ['id', 'name', 'fi'] } }] - }); - - // get tablet - const tablet = await models.userConfig.findById(id, { - include: [{ - relation: 'Tablet', - scope: { - fields: ['id'] - } - }] - }); + }, myOptions); // upload file const templateJson = { @@ -112,7 +114,7 @@ module.exports = Self => { { 'FieldName': 'FILTRO_TABLET', 'ItemElementName': 'string', - 'Item': tablet.id, + 'Item': userConfig.tabletFk, } ] }; @@ -120,19 +122,17 @@ module.exports = Self => { if (process.env.NODE_ENV != 'production') throw new UserError('Action not allowed on the test environment'); - if (!tablet.id) - throw new UserError('This user does not have an assigned tablet.'); // delete old const docuwareFile = await models.Docuware.checkFile(id, fileCabinet, false); if (docuwareFile) { const deleteJson = { 'Field': [{'FieldName': 'ESTADO', 'Item': 'Pendiente eliminar', 'ItemElementName': 'String'}] }; - const deleteUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/Fields`; - await axios.put(deleteUri, deleteJson, options.headers); + const deleteUri = `${docuwareOptions.url}/FileCabinets/${fileCabinetId}/Documents/${docuwareFile.id}/Fields`; + await axios.put(deleteUri, deleteJson, docuwareOptions.headers); } - const uploadUri = `${options.url}/FileCabinets/${fileCabinetId}/Documents?StoreDialogId=${dialogId}`; + const uploadUri = `${docuwareOptions.url}/FileCabinets/${fileCabinetId}/Documents?StoreDialogId=${dialogId}`; const FormData = require('form-data'); const data = new FormData(); @@ -142,7 +142,7 @@ module.exports = Self => { headers: { 'Content-Type': 'multipart/form-data', 'X-File-ModifiedDate': Date.vnNew(), - 'Cookie': options.headers.headers.Cookie, + 'Cookie': docuwareOptions.headers.headers.Cookie, ...data.getHeaders() }, }; @@ -153,11 +153,11 @@ module.exports = Self => { const $t = ctx.req.__; const message = $t('Failed to upload delivery note', {id}); if (uploaded.length) - await models.TicketTracking.setDelivered(ctx, uploaded); + await models.TicketTracking.setDelivered(ctx, uploaded, myOptions); throw new UserError(message); } uploaded.push(id); } - return models.TicketTracking.setDelivered(ctx, ticketIds); + return models.TicketTracking.setDelivered(ctx, ticketIds, myOptions); }; }; diff --git a/back/models/docuwareTablet.json b/back/models/docuwareTablet.json index e9e3b6bad..dbbf62f56 100644 --- a/back/models/docuwareTablet.json +++ b/back/models/docuwareTablet.json @@ -7,10 +7,7 @@ } }, "properties": { - "id": { - "type": "number" - }, - "name": { + "tablet": { "type": "string" }, "description": { diff --git a/back/models/user-config.json b/back/models/user-config.json index 35f6aa1e6..5c5df1b9e 100644 --- a/back/models/user-config.json +++ b/back/models/user-config.json @@ -28,7 +28,7 @@ "type": "boolean" }, "tabletFk": { - "type": "number" + "type": "string" } }, "relations": { diff --git a/db/changes/235201/00-tabletDocuware.sql b/db/changes/235201/00-tabletDocuware.sql deleted file mode 100644 index c480c1001..000000000 --- a/db/changes/235201/00-tabletDocuware.sql +++ /dev/null @@ -1,24 +0,0 @@ --- vn.docuwareTablet definition - -CREATE TABLE `vn`.`docuwareTablet` ( - `id` int(3) NOT NULL AUTO_INCREMENT, - `name` varchar(100) NOT NULL, - `description` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; - --- Auto-generated SQL script. Actual values for binary/complex data types may differ - what you see is the default string representation of values. -INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) - VALUES (1,'tabletRRHH','tablet de recursos humanos'); -INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) - VALUES (2,'tabletIT','tablet de IT'); -INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) - VALUES (3,'tabletCompradores','tablet de compradores'); -INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) - VALUES (4,'tabletComerciales','tablet de comerciales'); -INSERT INTO `vn`.`docuwareTablet` (`id`,`name`,`description`) - VALUES (5,'tabletAdministracion','tablet de administracion'); - -ALTER TABLE `vn`.`userConfig` -ADD COLUMN tabletFk int(3), -ADD FOREIGN KEY (tabletFk) REFERENCES `vn`.`docuwareTablet`(id); diff --git a/db/changes/240201/00-tabletDocuware.sql b/db/changes/240201/00-tabletDocuware.sql new file mode 100644 index 000000000..ffa0226b3 --- /dev/null +++ b/db/changes/240201/00-tabletDocuware.sql @@ -0,0 +1,10 @@ +-- vn.docuwareTablet definition + +CREATE TABLE `vn`.`docuwareTablet` ( + `tablet` varchar(100) NOT NULL PRIMARY KEY, + `description` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +ALTER TABLE `vn`.`userConfig` +ADD COLUMN tabletFk varchar(100) DEFAULT NULL, +ADD FOREIGN KEY (tabletFk) REFERENCES `vn`.`docuwareTablet`(tablet); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 8997e40b1..479704dd9 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -3009,3 +3009,8 @@ INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`) (1, 'Error in VAT calculation'), (2, 'Error in sales details'), (3, 'Error in customer data'); + +INSERT INTO `vn`.`docuwareTablet` (`tablet`,`description`) + VALUES + ('Tablet1','Jarvis tablet'), + ('Tablet2','Avengers tablet'); diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 94bc29a86..a197197ba 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -330,5 +330,5 @@ "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}}", - "This user does not have an assigned tablet.": "Este usuario no tiene tablet asignada" + "This user does not have an assigned tablet": "Este usuario no tiene tablet asignada" } From 0998b5bf2cfb59d4864cc24f8d6b1aceab9f2495 Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 21 Dec 2023 13:58:33 +0100 Subject: [PATCH 69/87] add locale and refactor: refs #6274 --- loopback/locale/es.json | 5 +++-- .../worker/back/methods/worker-time-control/clockIn.js | 6 +++--- modules/worker/back/methods/worker-time-control/login.js | 9 ++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index a8134909e..185212d51 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -329,5 +329,6 @@ "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", "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}}" -} + "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", + "Incorrect pin.": "Pin incorrecto." +} \ No newline at end of file diff --git a/modules/worker/back/methods/worker-time-control/clockIn.js b/modules/worker/back/methods/worker-time-control/clockIn.js index 2e2441cc2..44e0c547a 100644 --- a/modules/worker/back/methods/worker-time-control/clockIn.js +++ b/modules/worker/back/methods/worker-time-control/clockIn.js @@ -36,9 +36,9 @@ module.exports = Self => { Object.assign(myOptions, options); const query = 'CALL vn.workerTimeControl_clockIn(?, ?, ?)'; - const [response] = await Self.rawSql(query, [workerFk, timed, direction], myOptions); - if (response[0] && response[0].error) - throw new UserError(response[0].error); + const [[response]] = await Self.rawSql(query, [workerFk, timed, direction], myOptions); + if (response && response.error) + throw new UserError(response.error); return response; }; diff --git a/modules/worker/back/methods/worker-time-control/login.js b/modules/worker/back/methods/worker-time-control/login.js index 894b5ba17..b2a17b4e4 100644 --- a/modules/worker/back/methods/worker-time-control/login.js +++ b/modules/worker/back/methods/worker-time-control/login.js @@ -8,7 +8,7 @@ module.exports = Self => { { arg: 'pin', type: 'string', - required: true, + required: true }, ], returns: { @@ -27,9 +27,8 @@ module.exports = Self => { Object.assign(myOptions, options); const query = `CALL vn.workerTimeControl_login(?)`; - const user = await Self.rawSql(query, [pin], myOptions); - - if (!user) throw new UserError('Indique el pin.'); - return user[0][0]; + const [[user]] = await Self.rawSql(query, [pin], myOptions); + if (!user) throw new UserError('Incorrect pin.'); + return user; }; }; From 27a369bef4aa176fc4d43c5efb2a7f20239995ec Mon Sep 17 00:00:00 2001 From: pablone Date: Thu, 21 Dec 2023 18:34:22 +0100 Subject: [PATCH 70/87] refactor(ticketSms): refs #6259 merge ticksms to clientsms --- db/changes/235201/00-ticketSmsToClientSms.sql | 25 +++++++++++++++++ db/dump/fixtures.sql | 14 ++++++++++ modules/client/back/model-config.json | 3 -- modules/client/back/models/client-sms.json | 5 ++++ modules/client/back/models/ticket-sms.json | 28 ------------------- modules/ticket/back/methods/ticket/sendSms.js | 4 ++- .../back/methods/ticket/specs/sendSms.spec.js | 4 +-- 7 files changed, 49 insertions(+), 34 deletions(-) create mode 100644 db/changes/235201/00-ticketSmsToClientSms.sql delete mode 100644 modules/client/back/models/ticket-sms.json diff --git a/db/changes/235201/00-ticketSmsToClientSms.sql b/db/changes/235201/00-ticketSmsToClientSms.sql new file mode 100644 index 000000000..f2aa73863 --- /dev/null +++ b/db/changes/235201/00-ticketSmsToClientSms.sql @@ -0,0 +1,25 @@ +ALTER TABLE `vn`.`clientSms` ADD `ticketFk` int(11) NULL; +ALTER TABLE `vn`.`clientSms` ADD CONSTRAINT `clientSms_FK_2` FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +INSERT INTO`vn`.`clientSms` (`clientFk`, `smsFk`, `ticketFk`) + SELECT `t`.`clientFk`, `s`.`smsFk`, `s`.`ticketFk` + FROM `vn`.`clientSms` `s` + JOIN `vn`.`ticket` `t` ON `t`.`id` = `s`.`ticketFk`; + +RENAME TABLE `vn`.`ticketSms` TO `vn`.`ticketSms__`; + +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`clientSms_beforeInsert` + BEFORE INSERT ON `clientSms` + FOR EACH ROW +BEGIN + DECLARE vTicketOwner INT; + + SELECT clientFk INTO vTicketOwner + FROM ticket + WHERE id = NEW.ticketFk; + + IF NOT NEW.clientFk = vTicketOwner THEN + CALL util.throw('Unable to send an SMS ticket to a client who is not the owner'); + END IF; +END$$ \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 8997e40b1..7ea766d61 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -3009,3 +3009,17 @@ INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`) (1, 'Error in VAT calculation'), (2, 'Error in sales details'), (3, 'Error in customer data'); + +INSERT INTO `vn`.`sms` (`id`, `senderFk`, `sender`, `destination`, `message`, `statusCode`, `status`, `created`) + VALUES (1, 66, '111111111', '0001111111111', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'OK', util.VN_CURDATE()), + (2, 66, '222222222', '0002222222222', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'PENDING', util.VN_CURDATE()), + (3, 66, '333333333', '0003333333333', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'ERROR', util.VN_CURDATE()), + (4, 66, '444444444', '0004444444444', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'OK', util.VN_CURDATE()); + +INSERT INTO `vn`.`clientSms` (`id`, `clientFk`, `smsFk`, `ticketFk`) + VALUES(1, 1103, 1, NULL), + (2, 1103, 2, NULL), + (3, 1103, 3, 32), + (4, 1103, 4, 32), + (13, 1101, 1, NULL), + (14, 1101, 4, 27); \ No newline at end of file diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json index a21407732..fc1254dd8 100644 --- a/modules/client/back/model-config.json +++ b/modules/client/back/model-config.json @@ -113,9 +113,6 @@ "SageTransactionType": { "dataSource": "vn" }, - "TicketSms": { - "dataSource": "vn" - }, "TpvError": { "dataSource": "vn" }, diff --git a/modules/client/back/models/client-sms.json b/modules/client/back/models/client-sms.json index b2244ebbb..df1b58737 100644 --- a/modules/client/back/models/client-sms.json +++ b/modules/client/back/models/client-sms.json @@ -21,6 +21,11 @@ "type": "belongsTo", "model": "Sms", "foreignKey": "smsFk" + }, + "ticket": { + "type": "belongsTo", + "model": "Ticket", + "foreignKey": "ticketFk" } } } diff --git a/modules/client/back/models/ticket-sms.json b/modules/client/back/models/ticket-sms.json deleted file mode 100644 index 03f592f51..000000000 --- a/modules/client/back/models/ticket-sms.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "TicketSms", - "base": "VnModel", - "options": { - "mysql": { - "table": "ticketSms" - } - }, - "properties": { - "smsFk": { - "type": "number", - "id": true, - "description": "Identifier" - } - }, - "relations": { - "ticket": { - "type": "belongsTo", - "model": "Ticket", - "foreignKey": "ticketFk" - }, - "sms": { - "type": "belongsTo", - "model": "Sms", - "foreignKey": "smsFk" - } - } -} diff --git a/modules/ticket/back/methods/ticket/sendSms.js b/modules/ticket/back/methods/ticket/sendSms.js index ffc95c6b4..36e52fe3d 100644 --- a/modules/ticket/back/methods/ticket/sendSms.js +++ b/modules/ticket/back/methods/ticket/sendSms.js @@ -33,7 +33,9 @@ module.exports = Self => { Self.sendSms = async(ctx, id, destination, message) => { const models = Self.app.models; const sms = await models.Sms.send(ctx, destination, message); - await models.TicketSms.create({ + const {clientFk} = await models.Ticket.findById(id); + await models.ClientSms.create({ + clientFk, ticketFk: id, smsFk: sms.id }); diff --git a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js index 3f93198d1..43507ec56 100644 --- a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js +++ b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js @@ -17,9 +17,9 @@ describe('ticket sendSms()', () => { const filter = { ticketFk: id }; - const ticketSms = await models.TicketSms.findOne(filter, options); + const clientSms = await models.ClientSms.findOne(filter, options); - expect(ticketSms.ticketFk).toEqual(id); + expect(clientSms.ticketFk).toEqual(id); await tx.rollback(); } catch (e) { From 86db5a931d8b047fb55ca0c2139599737deb74b5 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 22 Dec 2023 10:44:21 +0100 Subject: [PATCH 71/87] arrange test suites: refs #6274 --- .../worker-time-control/specs/clockIn.spec.js | 553 +++++++++++++++++ .../worker-time-control/specs/login.spec.js | 2 +- .../specs/timeEntry.spec.js | 578 +----------------- 3 files changed, 555 insertions(+), 578 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js b/modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js index 970fd2fe2..9cd3ed1c0 100644 --- a/modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/clockIn.spec.js @@ -1,8 +1,29 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('workerTimeControl clockIn()', () => { const workerId = 9; + const salesBossId = 19; + const hankPymId = 1107; + const jessicaJonesId = 1110; + const HHRRId = 37; + const teamBossId = 13; + const monday = 1; + const tuesday = 2; + const thursday = 4; + const friday = 5; + const sunday = 7; const inTime = '2001-01-01T00:00:00.000Z'; + const activeCtx = { + accessToken: {userId: 50}, + }; + const ctx = {req: activeCtx}; + + beforeAll(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); it('should correctly clock in', async() => { const tx = await models.WorkerTimeControl.beginTransaction({}); @@ -24,5 +45,537 @@ describe('workerTimeControl clockIn()', () => { throw e; } }); + + describe('as Role errors', () => { + it('should add if the current user is team boss and the target user is himself', async() => { + activeCtx.accessToken.userId = teamBossId; + const workerId = teamBossId; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + + const todayAtOne = Date.vnNew(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, direction: 'in'}; + const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + expect(createdTimeEntry.id).toBeDefined(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should delete the created time entry for the team boss as himself', async() => { + activeCtx.accessToken.userId = teamBossId; + const workerId = teamBossId; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + + const todayAtOne = Date.vnNew(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, direction: 'in'}; + const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + expect(createdTimeEntry.id).toBeDefined(); + + await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); + + const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options); + + expect(deletedTimeEntry).toBeNull(); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should edit the created time entry for the team boss as HHRR', async() => { + activeCtx.accessToken.userId = HHRRId; + const workerId = teamBossId; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + + const todayAtOne = Date.vnNew(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, direction: 'in'}; + const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + expect(createdTimeEntry.id).toBeDefined(); + + ctx.args = {direction: 'out'}; + const updatedTimeEntry = await models.WorkerTimeControl.updateTimeEntry( + ctx, createdTimeEntry.id, options + ); + + expect(updatedTimeEntry.direction).toEqual('out'); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + }); + + describe('as saleBoss editor', () => { + let workerId; + beforeEach(() => { + activeCtx.accessToken.userId = salesBossId; + workerId = hankPymId; + }); + + it('should fail to add a time entry if the target user has an absence that day', async() => { + const date = Date.vnNew(); + date.setHours(8, 0, 0); + date.setDate(date.getDate() - 16); + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + try { + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`No está permitido trabajar`); + }); + + it('should fail to add a time entry for a worker without an existing contract', async() => { + const date = Date.vnNew(); + date.setFullYear(date.getFullYear() - 2); + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + try { + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`No hay un contrato en vigor`); + }); + + it('should fail to add a time entry for a worker without an existing contract and exceeding time', async() => { + let date = Date.vnNew(); + date.setDate(date.getDate() - 2); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + date.setHours(0, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date.setHours(20, 0, 1); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Superado el tiempo máximo entre entrada y salida`); + }); + + describe('direction errors', () => { + let date = Date.vnNew(); + date.setDate(date.getDate() - 1); + let error; + it('should throw an error when trying "in" direction twice', async() => { + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Dirección incorrecta`); + }); + + it('should throw an error when trying "in" direction after insert "in" and "middle"', async() => { + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'middle'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Dirección incorrecta`); + }); + + it('Should throw an error when trying "out" before closing a "middle" couple', async() => { + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'middle'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Dirección incorrecta`); + }); + + it('should throw an error when trying "middle" after "out"', async() => { + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'middle'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Dirección incorrecta`); + }); + + it('should throw an error when trying "out" direction twice', async() => { + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Dirección incorrecta`); + }); + }); + + describe('12h rest', () => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + it('should throw an error when the 12h rest is not fulfilled yet', async() => { + let date = Date.vnNew(); + date.setDate(date.getDate() - 2); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(4, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso diario`); + }); + + it('should not fail as the 12h rest is fulfilled', async() => { + let date = Date.vnNew(); + date.setDate(date.getDate() - 2); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(4, 1, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).not.toBeDefined; + }); + }); + + describe('for 3500kg drivers with enforced 9h rest', () => { + activeCtx.accessToken.userId = salesBossId; + const workerId = jessicaJonesId; + it('should throw an error when the 9h enforced rest is not fulfilled', async() => { + let date = Date.vnNew(); + date.setDate(date.getDate() - 2); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(1, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso diario`); + }); + + it('should not fail when the 9h enforced rest is fulfilled', async() => { + let date = Date.vnNew(); + date.setDate(date.getDate() - 2); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(1, 1, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).not.toBeDefined; + }); + }); + + describe('for 72h weekly rest', () => { + + it('should throw an error when work 11 consecutive days', async() => { + let date = Date.vnNew(); + date.setMonth(date.getMonth() - 1); + date.setDate(1); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + await populateWeek(date, monday, sunday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, thursday, ctx, workerId, options); + try { + date = weekDay(date, friday); + date.setHours(10, 0, 1); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso semanal`); + }); + + it('should throw an error when the 72h weekly rest is not fulfilled', async() => { + + let date = Date.vnNew(); + date.setMonth(date.getMonth() - 1); + date.setDate(1); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + await populateWeek(date, monday, sunday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, thursday, ctx, workerId, options); + + try { + date = weekDay(date, sunday); + date.setHours(17, 59, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso semanal`); + }); + + it('should throw an error when the 72h weekly rest is fulfilled', async() => { + + let date = Date.vnNew(); + date.setMonth(date.getMonth() - 1); + date.setDate(1); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + await populateWeek(date, monday, sunday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, thursday, ctx, workerId, options); + + try { + date = weekDay(date, sunday); + date.setHours(18, 00, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).not.toBeDefined; + }); + }); + }); }); +function weekDay(date, dayToSet) { + const currentDay = date.getDay(); + const distance = dayToSet - currentDay; + + date.setDate(date.getDate() + distance); + return date; +} + +function nextWeek(date) { + const sunday = 7; + const currentDay = date.getDay(); + let newDate = date; + if (currentDay != 0) + newDate = weekDay(date, sunday); + + newDate.setDate(newDate.getDate() + 1); + return newDate; +} + +async function populateWeek(date, dayStart, dayEnd, ctx, workerId, options) { + const dateStart = new Date(weekDay(date, dayStart)); + const dateEnd = new Date(dateStart); + dateEnd.setDate(dateStart.getDate() + dayEnd); + + for (let i = dayStart; i <= dayEnd; i++) { + dateStart.setHours(10, 0, 0); + ctx.args = {timed: dateStart, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + dateStart.setHours(18, 0, 0); + ctx.args = {timed: dateStart, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + dateStart.setDate(dateStart.getDate() + 1); + } +} diff --git a/modules/worker/back/methods/worker-time-control/specs/login.spec.js b/modules/worker/back/methods/worker-time-control/specs/login.spec.js index 88596f297..392d9a66b 100644 --- a/modules/worker/back/methods/worker-time-control/specs/login.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/login.spec.js @@ -13,7 +13,7 @@ describe('workerTimeControl login()', () => { await models.WorkerTimeControl.login(); } catch (error) { expect(error).toBeInstanceOf(UserError); - expect(error.message).toBe('Indique el pin.'); + expect(error.message).toBe('Incorrect pin.'); } }); }); diff --git a/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js index 42ec6290a..92c01792f 100644 --- a/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js @@ -3,18 +3,10 @@ const models = require('vn-loopback/server/server').models; const LoopBackContext = require('loopback-context'); describe('workerTimeControl add/delete timeEntry()', () => { - const HHRRId = 37; - const teamBossId = 13; const employeeId = 1; - const salesPersonId = 1106; const salesBossId = 19; const hankPymId = 1107; - const jessicaJonesId = 1110; const monday = 1; - const tuesday = 2; - const thursday = 4; - const friday = 5; - const sunday = 7; const activeCtx = { accessToken: {userId: 50}, }; @@ -61,560 +53,11 @@ describe('workerTimeControl add/delete timeEntry()', () => { expect(error.statusCode).toBe(400); expect(error.message).toBe(`You don't have enough privileges`); }); - - it('should add if the current user is team boss and the target user is himself', async() => { - activeCtx.accessToken.userId = teamBossId; - const workerId = teamBossId; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; - - const todayAtOne = Date.vnNew(); - todayAtOne.setHours(1, 0, 0, 0); - - ctx.args = {timed: todayAtOne, direction: 'in'}; - const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - expect(createdTimeEntry.id).toBeDefined(); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should try but fail to delete his own time entry', async() => { - activeCtx.accessToken.userId = salesBossId; - const workerId = salesBossId; - - let error; - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; - - const todayAtOne = Date.vnNew(); - todayAtOne.setHours(1, 0, 0, 0); - - ctx.args = {timed: todayAtOne, direction: 'in'}; - const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - activeCtx.accessToken.userId = salesPersonId; - await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error).toBeDefined(); - expect(error.statusCode).toBe(400); - expect(error.message).toBe(`You don't have enough privileges`); - }); - - it('should delete the created time entry for the team boss as himself', async() => { - activeCtx.accessToken.userId = teamBossId; - const workerId = teamBossId; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; - - const todayAtOne = Date.vnNew(); - todayAtOne.setHours(1, 0, 0, 0); - - ctx.args = {timed: todayAtOne, direction: 'in'}; - const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - expect(createdTimeEntry.id).toBeDefined(); - - await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); - - const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options); - - expect(deletedTimeEntry).toBeNull(); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should delete the created time entry for the team boss as HHRR', async() => { - activeCtx.accessToken.userId = HHRRId; - const workerId = teamBossId; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; - - const todayAtOne = Date.vnNew(); - todayAtOne.setHours(1, 0, 0, 0); - - ctx.args = {timed: todayAtOne, direction: 'in'}; - const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - expect(createdTimeEntry.id).toBeDefined(); - - await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); - - const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options); - - expect(deletedTimeEntry).toBeNull(); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should edit the created time entry for the team boss as HHRR', async() => { - activeCtx.accessToken.userId = HHRRId; - const workerId = teamBossId; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; - - const todayAtOne = Date.vnNew(); - todayAtOne.setHours(1, 0, 0, 0); - - ctx.args = {timed: todayAtOne, direction: 'in'}; - const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - expect(createdTimeEntry.id).toBeDefined(); - - ctx.args = {direction: 'out'}; - const updatedTimeEntry = await models.WorkerTimeControl.updateTimeEntry(ctx, createdTimeEntry.id, options); - - expect(updatedTimeEntry.direction).toEqual('out'); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); }); describe('WorkerTimeControl_clockIn calls', () => { - let workerId; - beforeEach(() => { - activeCtx.accessToken.userId = salesBossId; - workerId = hankPymId; - }); - it('should fail to add a time entry if the target user has an absence that day', async() => { - const date = Date.vnNew(); - date.setHours(8, 0, 0); - date.setDate(date.getDate() - 16); - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - try { - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + beforeEach(() => activeCtx.accessToken.userId = salesBossId); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`No está permitido trabajar`); - }); - - it('should fail to add a time entry for a worker without an existing contract', async() => { - const date = Date.vnNew(); - date.setFullYear(date.getFullYear() - 2); - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - try { - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`No hay un contrato en vigor`); - }); - - it('should fail to add a time entry for a worker without an existing contract', async() => { - let date = Date.vnNew(); - date.setDate(date.getDate() - 2); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - date.setHours(0, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date.setHours(20,0, 1); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Superado el tiempo máximo entre entrada y salida`); - }); - - describe('direction errors', () => { - let date = Date.vnNew(); - date.setDate(date.getDate() - 1); - let error; - it('should throw an error when trying "in" direction twice', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date.setHours(10, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Dirección incorrecta`); - }); - - it('should throw an error when trying "in" direction after insert "in" and "middle"', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - date.setHours(9, 0, 0); - ctx.args = {timed: date, direction: 'middle'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date.setHours(10, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Dirección incorrecta`); - }); - - it('Should throw an error when trying "out" before closing a "middle" couple', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - date.setHours(9, 0, 0); - ctx.args = {timed: date, direction: 'middle'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date.setHours(10, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Dirección incorrecta`); - }); - - it('should throw an error when trying "middle" after "out"', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - date.setHours(9, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date.setHours(10, 0, 0); - ctx.args = {timed: date, direction: 'middle'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Dirección incorrecta`); - }); - - it('should throw an error when trying "out" direction twice', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - date.setHours(9, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date.setHours(10, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Dirección incorrecta`); - }); - }); - - describe('12h rest', () => { - activeCtx.accessToken.userId = salesBossId; - const workerId = hankPymId; - it('should throw an error when the 12h rest is not fulfilled yet', async() => { - - let date = Date.vnNew(); - date.setDate(date.getDate() - 2); - date = weekDay(date, monday); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - date.setHours(16, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date = weekDay(date, tuesday); - date.setHours(4, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Descanso diario`); - }); - - it('should not fail as the 12h rest is fulfilled', async() => { - let date = Date.vnNew(); - date.setDate(date.getDate() - 2); - date = weekDay(date, monday); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - date.setHours(16, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date = weekDay(date, tuesday); - date.setHours(4, 1, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error).not.toBeDefined; - }); - }); - - describe('for 3500kg drivers with enforced 9h rest', () => { - activeCtx.accessToken.userId = salesBossId; - const workerId = jessicaJonesId; - it('should throw an error when the 9h enforced rest is not fulfilled', async() => { - - let date = Date.vnNew(); - date.setDate(date.getDate() - 2); - date = weekDay(date, monday); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - date.setHours(16, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date = weekDay(date, tuesday); - date.setHours(1, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Descanso diario`); - }); - - it('should not fail when the 9h enforced rest is fulfilled', async() => { - - let date = Date.vnNew(); - date.setDate(date.getDate() - 2); - date = weekDay(date, monday); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - date.setHours(8, 0, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - date.setHours(16, 0, 0); - ctx.args = {timed: date, direction: 'out'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - try { - date = weekDay(date, tuesday); - date.setHours(1, 1, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error).not.toBeDefined; - }); - }); - - describe('for 72h weekly rest', () => { - - it('should throw an error when work 11 consecutive days', async() => { - let date = Date.vnNew(); - date.setMonth(date.getMonth() - 1); - date.setDate(1); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - await populateWeek(date, monday, sunday, ctx, workerId, options); - date = nextWeek(date); - await populateWeek(date, monday, thursday, ctx, workerId, options); - try { - date = weekDay(date, friday); - date.setHours(10, 0, 1); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Descanso semanal`); - }); - - it('should throw an error when the 72h weekly rest is not fulfilled', async() => { - - let date = Date.vnNew(); - date.setMonth(date.getMonth() - 1); - date.setDate(1); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - await populateWeek(date, monday, sunday, ctx, workerId, options); - date = nextWeek(date); - await populateWeek(date, monday, thursday, ctx, workerId, options); - - try { - date = weekDay(date, sunday); - date.setHours(17, 59, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error.message).toBe(`Descanso semanal`); - }); - - it('should throw an error when the 72h weekly rest is fulfilled', async() => { - - let date = Date.vnNew(); - date.setMonth(date.getMonth() - 1); - date.setDate(1); - let error; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - const options = {transaction: tx}; - - await populateWeek(date, monday, sunday, ctx, workerId, options); - date = nextWeek(date); - await populateWeek(date, monday, thursday, ctx, workerId, options); - - try { - date = weekDay(date, sunday); - date.setHours(18, 00, 0); - ctx.args = {timed: date, direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error).not.toBeDefined; - }); - }); - describe('WorkerTimeControl_calculate calls', () => { let dated = Date.vnNew(); dated.setDate(dated.getDate() - 7); @@ -836,25 +279,6 @@ function weekDay(date, dayToSet) { return date; } -function nextWeek(date) { - const sunday = 7; - const currentDay = date.getDay(); - let newDate = date; - if (currentDay != 0) - newDate = weekDay(date, sunday); - - newDate.setDate(newDate.getDate() + 1); - return newDate; -} - -function lastWeek(date) { - const monday = 1; - newDate = weekDay(date, monday); - - newDate.setDate(newDate.getDate() - 1); - return newDate; -} - async function populateWeek(date, dayStart, dayEnd, ctx, workerId, options) { const dateStart = new Date(weekDay(date, dayStart)); const dateEnd = new Date(dateStart); From 2e1715a968fdfac0977952d3939cfe1b3f34190a Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 22 Dec 2023 15:19:45 +0100 Subject: [PATCH 72/87] refactor renewToken & replace ACL: refs #6274 --- back/methods/vn-user/renew-token.js | 41 ++++++++----------- .../methods/vn-user/specs/renew-token.spec.js | 1 - back/models/vn-user.json | 27 ++++++------ db/changes/240201/00-timecontrol.sql | 7 +++- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/back/methods/vn-user/renew-token.js b/back/methods/vn-user/renew-token.js index 194747949..d00085d8a 100644 --- a/back/methods/vn-user/renew-token.js +++ b/back/methods/vn-user/renew-token.js @@ -1,14 +1,5 @@ -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', @@ -28,14 +19,26 @@ module.exports = Self => { const {accessToken: token} = ctx.req; // Check if current token is valid - const isValid = await validateToken(token); - if (isValid) + + const {renewPeriod, courtesyTime} = await models.AccessTokenConfig.findOne({ + fields: ['renewPeriod', 'courtesyTime'] + }); + const now = Date.now(); + const differenceMilliseconds = now - token.created; + const differenceSeconds = Math.floor(differenceMilliseconds / 1000); + const isNotExceeded = differenceSeconds < renewPeriod - courtesyTime; + if (isNotExceeded) return token; - const {courtesyTime} = await models.AccessTokenConfig.findOne({fields: ['courtesyTime']}); - // Schedule to remove current token - handlePromiseLogout(Self, token, courtesyTime); + setTimeout(async() => { + try { + await Self.logout(token.id); + } catch (err) { + // eslint-disable-next-line no-console + console.error(err); + } + }, courtesyTime * 1000); // Create new accessToken const user = await Self.findById(token.userId); @@ -43,14 +46,4 @@ module.exports = Self => { 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 index 146f6eb0c..8d9bbf11c 100644 --- a/back/methods/vn-user/specs/renew-token.spec.js +++ b/back/methods/vn-user/specs/renew-token.spec.js @@ -30,7 +30,6 @@ describe('Renew Token', () => { it('should renew token', async() => { const mockDate = new Date(startingTime + 26600000); jasmine.clock().mockDate(mockDate); - console.log(startingTime, mockDate) const {id} = await models.VnUser.renewToken(ctx); expect(id).not.toEqual(ctx.req.accessToken.id); diff --git a/back/models/vn-user.json b/back/models/vn-user.json index 86ffac2bb..d0687098d 100644 --- a/back/models/vn-user.json +++ b/back/models/vn-user.json @@ -95,27 +95,30 @@ "principalType": "ROLE", "principalId": "$everyone", "permission": "ALLOW" - }, - { - "property": "recoverPassword", - "accessType": "EXECUTE", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" - }, - { - "property": "validateAuth", + }, { + "property": "recoverPassword", "accessType": "EXECUTE", "principalType": "ROLE", "principalId": "$everyone", "permission": "ALLOW" - }, - { + }, { + "property": "validateAuth", + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + }, { "property": "privileges", "accessType": "*", "principalType": "ROLE", "principalId": "$authenticated", "permission": "ALLOW" + }, { + "property": "renewToken", + "accessType": "WRITE", + "principalType": "ROLE", + "principalId": "$authenticated", + "permission": "ALLOW" } ], "scopes": { diff --git a/db/changes/240201/00-timecontrol.sql b/db/changes/240201/00-timecontrol.sql index 0d3bd59b2..c3ddf5d96 100644 --- a/db/changes/240201/00-timecontrol.sql +++ b/db/changes/240201/00-timecontrol.sql @@ -1,3 +1,7 @@ +DELETE FROM `salix`.`ACL` + WHERE model = 'VnUser' + AND property = 'renewToken'; + INSERT INTO `account`.`role` (name, description) VALUES ('timeControl','Tablet para fichar'); @@ -8,7 +12,6 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalTyp VALUES ('WorkerTimeControl', 'login', 'READ', 'ALLOW', 'ROLE', 'timeControl'), ('WorkerTimeControl', 'getClockIn', 'READ', 'ALLOW', 'ROLE', 'timeControl'), - ('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'), - ('VnUser', 'renewToken', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); + ('WorkerTimeControl', 'clockIn', 'WRITE', 'ALLOW', 'ROLE', 'timeControl'); CALL `account`.`role_sync`(); From 5a1c4ddea02f52c6e836246b70c1a5d0d459e082 Mon Sep 17 00:00:00 2001 From: pablone Date: Tue, 26 Dec 2023 08:20:13 +0100 Subject: [PATCH 73/87] refactor(ticketSms): refs #6259 ticketSmsToClientSms --- .../00-ticketSmsToClientSms.sql | 16 ---------------- .../back/methods/ticket/specs/sendSms.spec.js | 8 ++++---- 2 files changed, 4 insertions(+), 20 deletions(-) rename db/changes/{240001 => 240201}/00-ticketSmsToClientSms.sql (52%) diff --git a/db/changes/240001/00-ticketSmsToClientSms.sql b/db/changes/240201/00-ticketSmsToClientSms.sql similarity index 52% rename from db/changes/240001/00-ticketSmsToClientSms.sql rename to db/changes/240201/00-ticketSmsToClientSms.sql index f2aa73863..cd3cf7dd3 100644 --- a/db/changes/240001/00-ticketSmsToClientSms.sql +++ b/db/changes/240201/00-ticketSmsToClientSms.sql @@ -7,19 +7,3 @@ INSERT INTO`vn`.`clientSms` (`clientFk`, `smsFk`, `ticketFk`) JOIN `vn`.`ticket` `t` ON `t`.`id` = `s`.`ticketFk`; RENAME TABLE `vn`.`ticketSms` TO `vn`.`ticketSms__`; - -DELIMITER $$ -CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`clientSms_beforeInsert` - BEFORE INSERT ON `clientSms` - FOR EACH ROW -BEGIN - DECLARE vTicketOwner INT; - - SELECT clientFk INTO vTicketOwner - FROM ticket - WHERE id = NEW.ticketFk; - - IF NOT NEW.clientFk = vTicketOwner THEN - CALL util.throw('Unable to send an SMS ticket to a client who is not the owner'); - END IF; -END$$ \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js index 43507ec56..afc1ada54 100644 --- a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js +++ b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js @@ -14,10 +14,10 @@ describe('ticket sendSms()', () => { await models.Ticket.sendSms(ctx, id, destination, message, options); - const filter = { - ticketFk: id - }; - const clientSms = await models.ClientSms.findOne(filter, options); + const clientSms = await models.ClientSms.findOne( + {where: {ticketFk: id}}, + options + ); expect(clientSms.ticketFk).toEqual(id); From 1b8461034e12fce15f4918e517f9cbe7ff40a896 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Dec 2023 12:40:48 +0100 Subject: [PATCH 74/87] using hasAnyNegative: refs #6515 --- .../back/methods/invoiceOut/createManualInvoice.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js index 18e6903d6..043dfbead 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js @@ -85,7 +85,7 @@ module.exports = Self => { throw new UserError(`A ticket with an amount of zero can't be invoiced`); // Validates ticket nagative base - const hasNegativeBase = await getNegativeBase(ticketId, myOptions); + const hasNegativeBase = await getNegativeBase(maxShipped, clientId, companyId, myOptions); if (hasNegativeBase && company.code == 'VNL') throw new UserError(`A ticket with a negative base can't be invoiced`); } else { @@ -162,10 +162,13 @@ module.exports = Self => { return result.invoiceable; } - async function getNegativeBase(ticketId, options) { + async function getNegativeBase(maxShipped, clientId, companyId, options) { const models = Self.app.models; - const query = 'SELECT vn.hasSomeNegativeBase(?) AS base'; - const [result] = await models.InvoiceOut.rawSql(query, [ticketId], options); + await models.InvoiceOut.rawSql('CALL invoiceOut_exportationFromClient(?,?,?)', + [maxShipped, clientId, companyId], options + ); + const query = 'SELECT vn.hasAnyNegativeBase() AS base'; + const [result] = await models.InvoiceOut.rawSql(query, [], options); return result.base; } From 15ec91ec790fbe18191262127a20b402ce824d70 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Dec 2023 14:05:01 +0100 Subject: [PATCH 75/87] fix query: refs #6369 --- modules/invoiceOut/back/methods/invoiceOut/negativeBases.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js b/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js index ae9c404af..96c789316 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js +++ b/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js @@ -90,7 +90,7 @@ module.exports = Self => { AND t.refFk IS NULL AND c.typeFk IN ('normal','trust') GROUP BY t.clientFk, negativeBase.taxableBase - HAVING amount <> 0`, [args.from, args.to])); + HAVING amount < 0`, [args.from, args.to])); stmt = new ParameterizedSQL(` SELECT f.* From 318761185bbf1172657002f2adfde77b895c7118 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 2 Jan 2024 08:07:16 +0100 Subject: [PATCH 76/87] refs #6434 fix: remove console.log --- back/methods/vn-user/specs/renew-token.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/back/methods/vn-user/specs/renew-token.spec.js b/back/methods/vn-user/specs/renew-token.spec.js index 146f6eb0c..8d9bbf11c 100644 --- a/back/methods/vn-user/specs/renew-token.spec.js +++ b/back/methods/vn-user/specs/renew-token.spec.js @@ -30,7 +30,6 @@ describe('Renew Token', () => { it('should renew token', async() => { const mockDate = new Date(startingTime + 26600000); jasmine.clock().mockDate(mockDate); - console.log(startingTime, mockDate) const {id} = await models.VnUser.renewToken(ctx); expect(id).not.toEqual(ctx.req.accessToken.id); From 0101dcda3ac950c1add6c3c426c4f745389805c1 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 2 Jan 2024 08:12:45 +0100 Subject: [PATCH 77/87] refs #5925 fix: add options --- back/methods/docuware/specs/upload.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/docuware/specs/upload.spec.js b/back/methods/docuware/specs/upload.spec.js index 2577fa42d..866499b66 100644 --- a/back/methods/docuware/specs/upload.spec.js +++ b/back/methods/docuware/specs/upload.spec.js @@ -31,7 +31,7 @@ describe('docuware upload()', () => { try { const options = {transaction: tx}; const user = await models.UserConfig.findById(userId, null, options); - await user.updateAttribute('tabletFk', 'Tablet1'); + await user.updateAttribute('tabletFk', 'Tablet1', options); await models.Docuware.upload(ctx, ticketIds, fileCabinetName, options); await tx.rollback(); From 801037da64bf3c02d8017ba29e2dc7cf698448b6 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 2 Jan 2024 08:47:12 +0100 Subject: [PATCH 78/87] fix changes: refs #6274 --- db/changes/{240201 => 234601}/00-updateCourtesyTime.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{240201 => 234601}/00-updateCourtesyTime.sql (100%) diff --git a/db/changes/240201/00-updateCourtesyTime.sql b/db/changes/234601/00-updateCourtesyTime.sql similarity index 100% rename from db/changes/240201/00-updateCourtesyTime.sql rename to db/changes/234601/00-updateCourtesyTime.sql From 763af7da2d17c14ec49d34f4455b6a2de95f111a Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 2 Jan 2024 08:58:41 +0100 Subject: [PATCH 79/87] fix test: refs #6274 --- .../worker/back/methods/worker-time-control/specs/login.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/back/methods/worker-time-control/specs/login.spec.js b/modules/worker/back/methods/worker-time-control/specs/login.spec.js index 392d9a66b..8e992de96 100644 --- a/modules/worker/back/methods/worker-time-control/specs/login.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/login.spec.js @@ -3,7 +3,7 @@ const models = require('vn-loopback/server/server').models; describe('workerTimeControl login()', () => { it('should correctly login', async() => { - const response = await models.WorkerTimeControl.login(9, {}); + const response = await models.WorkerTimeControl.login(9); expect(response.name).toBe('developer'); }); From 6b8a4a512bc58067c2efd00b141e8a45a0d99e8c Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 2 Jan 2024 10:42:50 +0100 Subject: [PATCH 80/87] adding filter: refs #6606 --- .../back/methods/invoiceOut/negativeBasesCsv.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js b/modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js index d70a8fce5..87e9a67ea 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js +++ b/modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js @@ -10,13 +10,17 @@ module.exports = Self => { type: 'date', description: 'From date', required: true - }, - { + }, { arg: 'to', type: 'date', description: 'To date', required: true - }], + }, { + arg: 'filter', + type: 'object', + description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string' + }, + ], returns: [ { arg: 'body', From 1e3a7e5f9113aac0beb95b052c2b8be745934995 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 2 Jan 2024 13:17:10 +0100 Subject: [PATCH 81/87] refs #5914 refactor: invoiceTickets --- ...00-fixInvoiceCorrectionConstraintsName.sql | 7 +++++ .../{235001 => 240001}/00-getTaxBases.sql | 0 .../01-newHasAnyPositiveBase.sql | 2 +- .../01-refactorHasAnyNegativeBase.sql | 2 +- .../back/models/invoice-correction.json | 27 +++++++++++++++++++ .../back/methods/ticket/canBeInvoiced.js | 7 ----- .../back/methods/ticket/invoiceTickets.js | 19 +++++++------ .../ticket/back/methods/ticket/makeInvoice.js | 3 +-- .../ticket/specs/canBeInvoiced.spec.js | 20 +++----------- 9 files changed, 50 insertions(+), 37 deletions(-) create mode 100644 db/changes/240001/00-fixInvoiceCorrectionConstraintsName.sql rename db/changes/{235001 => 240001}/00-getTaxBases.sql (100%) rename db/changes/{235001 => 240001}/01-newHasAnyPositiveBase.sql (91%) rename db/changes/{235001 => 240001}/01-refactorHasAnyNegativeBase.sql (91%) diff --git a/db/changes/240001/00-fixInvoiceCorrectionConstraintsName.sql b/db/changes/240001/00-fixInvoiceCorrectionConstraintsName.sql new file mode 100644 index 000000000..426afea90 --- /dev/null +++ b/db/changes/240001/00-fixInvoiceCorrectionConstraintsName.sql @@ -0,0 +1,7 @@ +ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `cplusInvoiceTyoeFk`; +ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `invoiceCorrectionType_Fk33`; +ALTER TABLE `vn`.`invoiceCorrection` DROP FOREIGN KEY `invoiceCorrection_ibfk_1`; + +ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `siiTypeInvoiceOut_FK` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `vn`.`siiTypeInvoiceOut`(id) ON UPDATE CASCADE; +ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `invoiceCorrectionType_FK` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `vn`.`invoiceCorrectionType`(id) ON UPDATE CASCADE; +ALTER TABLE `vn`.`invoiceCorrection` ADD CONSTRAINT `cplusRectificationType_FK` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `vn`.`cplusRectificationType`(id) ON UPDATE CASCADE; diff --git a/db/changes/235001/00-getTaxBases.sql b/db/changes/240001/00-getTaxBases.sql similarity index 100% rename from db/changes/235001/00-getTaxBases.sql rename to db/changes/240001/00-getTaxBases.sql diff --git a/db/changes/235001/01-newHasAnyPositiveBase.sql b/db/changes/240001/01-newHasAnyPositiveBase.sql similarity index 91% rename from db/changes/235001/01-newHasAnyPositiveBase.sql rename to db/changes/240001/01-newHasAnyPositiveBase.sql index c9e7e8e05..70fd51bcc 100644 --- a/db/changes/235001/01-newHasAnyPositiveBase.sql +++ b/db/changes/240001/01-newHasAnyPositiveBase.sql @@ -14,7 +14,7 @@ BEGIN CALL getTaxBases(); - SELECT positive > 0 INTO hasAnyPositiveBase + SELECT positive INTO hasAnyPositiveBase FROM tmp.taxBases; DROP TEMPORARY TABLE diff --git a/db/changes/235001/01-refactorHasAnyNegativeBase.sql b/db/changes/240001/01-refactorHasAnyNegativeBase.sql similarity index 91% rename from db/changes/235001/01-refactorHasAnyNegativeBase.sql rename to db/changes/240001/01-refactorHasAnyNegativeBase.sql index 65822fc95..f851ee6b9 100644 --- a/db/changes/235001/01-refactorHasAnyNegativeBase.sql +++ b/db/changes/240001/01-refactorHasAnyNegativeBase.sql @@ -14,7 +14,7 @@ BEGIN CALL getTaxBases(); - SELECT negative > 0 INTO hasAnyNegativeBase + SELECT negative INTO hasAnyNegativeBase FROM tmp.taxBases; DROP TEMPORARY TABLE diff --git a/modules/invoiceOut/back/models/invoice-correction.json b/modules/invoiceOut/back/models/invoice-correction.json index 5924c9232..58f6f63b7 100644 --- a/modules/invoiceOut/back/models/invoice-correction.json +++ b/modules/invoiceOut/back/models/invoice-correction.json @@ -26,6 +26,33 @@ "invoiceCorrectionTypeFk": { "type": "number", "required": true + }, + "relations": { + "correcting": { + "type": "belongsTo", + "model": "InvoiceOut", + "foreignKey": "correctingFk" + }, + "corrected": { + "type": "belongsTo", + "model": "InvoiceOut", + "foreignKey": "correctedFk" + }, + "cplusRectificationType": { + "type": "belongsTo", + "model": "cplusRectificationType", + "foreignKey": "cplusRectificationTypeFk" + }, + "siiTypeInvoiceOut": { + "type": "belongsTo", + "model": "siiTypeInvoiceOut", + "foreignKey": "siiTypeInvoiceOutFk" + }, + "invoiceCorrectionType": { + "type": "belongsTo", + "model": "invoiceCorrectionType", + "foreignKey": "invoiceCorrectionTypeFk" + } } } } diff --git a/modules/ticket/back/methods/ticket/canBeInvoiced.js b/modules/ticket/back/methods/ticket/canBeInvoiced.js index 75d13a508..855a864c2 100644 --- a/modules/ticket/back/methods/ticket/canBeInvoiced.js +++ b/modules/ticket/back/methods/ticket/canBeInvoiced.js @@ -17,11 +17,6 @@ module.exports = function(Self) { type: 'boolean' } ], - returns: { - arg: 'data', - type: 'boolean', - root: true - }, http: { path: `/canBeInvoiced`, verb: 'get' @@ -63,7 +58,5 @@ module.exports = function(Self) { if (ticketsIds.length == 1 && priceZero) throw new UserError(`A ticket with an amount of zero can't be invoiced`); }); - - return true; }; }; diff --git a/modules/ticket/back/methods/ticket/invoiceTickets.js b/modules/ticket/back/methods/ticket/invoiceTickets.js index f1793773b..57f623289 100644 --- a/modules/ticket/back/methods/ticket/invoiceTickets.js +++ b/modules/ticket/back/methods/ticket/invoiceTickets.js @@ -61,20 +61,19 @@ module.exports = function(Self) { if (!isSameClient) throw new UserError(`You can't invoice tickets from multiple clients`); - const client = await models.Client.findById(clientId, { - fields: ['id', 'hasToInvoiceByAddress'] + const {hasToInvoiceByAddress} = await models.Client.findById(clientId, { + fields: ['hasToInvoiceByAddress'] }, myOptions); - let ticketsByAddress = {[firstTicket.addressFk]: ticketsIds}; - if (client.hasToInvoiceByAddress) { - ticketsByAddress = tickets.reduce((group, ticket) => { - const {addressFk} = ticket; + let ticketsByAddress = hasToInvoiceByAddress + ? Object.values(tickets.reduce((group, {id, addressFk}) => { group[addressFk] = group[addressFk] ?? []; - group[addressFk].push(ticket.id); + group[addressFk].push(id); return group; - }, {}); - } - for (const ticketIds of Object.values(ticketsByAddress)) + }, {})) + : [[ticketsIds]]; + + for (const ticketIds of ticketsByAddress) invoicesIds.push(await createInvoice(ctx, companyId, ticketIds, invoiceCorrection, myOptions)); if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index 32aa03f9d..83222a4ee 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -106,8 +106,7 @@ module.exports = function(Self) { ); } - if (resultInvoice.id) - await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions); + await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions); if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js index e443ed6d3..1509b87df 100644 --- a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js +++ b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js @@ -27,10 +27,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); - - expect(canBeInvoiced).toEqual(false); - + await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); await tx.rollback(); } catch (e) { error = e; @@ -59,10 +56,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); - - expect(canBeInvoiced).toEqual(false); - + await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); await tx.rollback(); } catch (e) { error = e; @@ -95,10 +89,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); - - expect(canBeInvoiced).toEqual(false); - + await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); await tx.rollback(); } catch (e) { error = e; @@ -123,10 +114,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); - - expect(canBeInvoiced).toEqual(true); - + await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); await tx.rollback(); } catch (e) { await tx.rollback(); From c116bc56c3e23d52cff1ba6cda4eb396cd0aeaad Mon Sep 17 00:00:00 2001 From: pablone Date: Tue, 2 Jan 2024 19:37:51 +0100 Subject: [PATCH 82/87] refactor(clientSms): refs #6259 redirect to lilium --- modules/client/front/sms/index.html | 42 ++--------------------------- modules/client/front/sms/index.js | 28 ++++--------------- 2 files changed, 7 insertions(+), 63 deletions(-) diff --git a/modules/client/front/sms/index.html b/modules/client/front/sms/index.html index e2bc0785e..7fb3b870e 100644 --- a/modules/client/front/sms/index.html +++ b/modules/client/front/sms/index.html @@ -1,40 +1,2 @@ - - - - - - - - Sender - Destination - Message - Status - Created - - - - - - - {{::clientSms.sms.sender.name}} - - - {{::clientSms.sms.destination}} - {{::clientSms.sms.message}} - {{::clientSms.sms.status}} - {{::clientSms.sms.created | date:'dd/MM/yyyy HH:mm'}} - - - - - - - + + diff --git a/modules/client/front/sms/index.js b/modules/client/front/sms/index.js index 6ad64282e..8fa130248 100644 --- a/modules/client/front/sms/index.js +++ b/modules/client/front/sms/index.js @@ -1,32 +1,14 @@ import ngModule from '../module'; import Section from 'salix/components/section'; -export default class Controller extends Section { +class Controller extends Section { constructor($element, $) { super($element, $); + } - this.filter = { - fields: ['id', 'smsFk'], - include: { - relation: 'sms', - scope: { - fields: [ - 'senderFk', - 'sender', - 'destination', - 'message', - 'statusCode', - 'status', - 'created'], - include: { - relation: 'sender', - scope: { - fields: ['name'] - } - } - } - } - }; + async $onInit() { + this.$state.go('client.card.summary', {id: this.$params.id}); + window.location.href = await this.vnApp.getUrl(`Customer/${this.$params.id}/sms`); } } From 5dc49d226ad4450b130ff47231702593a69ddc00 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 3 Jan 2024 10:13:56 +0100 Subject: [PATCH 83/87] refs #6274 fix locale --- loopback/locale/en.json | 3 ++- loopback/locale/es.json | 7 +++--- .../back/methods/worker-time-control/login.js | 7 +++--- .../worker-time-control/specs/login.spec.js | 24 +++++++++++++++---- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index c5e8d4fcf..508c17344 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -200,5 +200,6 @@ "Try again": "Try again", "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}}" + "It was not able to remove the next expeditions:": "It was not able to remove the next expeditions: {{expeditions}}", + "Incorrect pin": "Incorrect pin." } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index fc209a9cd..e2b90983b 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -330,9 +330,8 @@ "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}}", - "This user does not have an assigned tablet": "Este usuario no tiene tablet asignada", - "Incorrect pin.": "Pin incorrecto.", + "This user does not have an assigned tablet": "Este usuario no tiene tablet asignada", + "Incorrect pin": "Pin incorrecto.", "You already have the mailAlias": "Ya tienes este alias de correo", "The alias cant be modified": "Este alias de correo no puede ser modificado" -} - +} \ No newline at end of file diff --git a/modules/worker/back/methods/worker-time-control/login.js b/modules/worker/back/methods/worker-time-control/login.js index b2a17b4e4..9aa4bd145 100644 --- a/modules/worker/back/methods/worker-time-control/login.js +++ b/modules/worker/back/methods/worker-time-control/login.js @@ -1,7 +1,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethod('login', { + Self.remoteMethodCtx('login', { description: 'Consult the user\'s information and the buttons that must be activated after logging in', accessType: 'READ', accepts: [ @@ -21,14 +21,15 @@ module.exports = Self => { } }); - Self.login = async(pin, options) => { + Self.login = async(ctx, pin, options) => { const myOptions = {}; + const $t = ctx.req.__; if (typeof options == 'object') Object.assign(myOptions, options); const query = `CALL vn.workerTimeControl_login(?)`; const [[user]] = await Self.rawSql(query, [pin], myOptions); - if (!user) throw new UserError('Incorrect pin.'); + if (!user) throw new UserError($t('Incorrect pin')); return user; }; }; diff --git a/modules/worker/back/methods/worker-time-control/specs/login.spec.js b/modules/worker/back/methods/worker-time-control/specs/login.spec.js index 8e992de96..d9f2dbb39 100644 --- a/modules/worker/back/methods/worker-time-control/specs/login.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/login.spec.js @@ -1,20 +1,34 @@ -const UserError = require('vn-loopback/util/user-error'); const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); +const UserError = require('vn-loopback/util/user-error'); describe('workerTimeControl login()', () => { + let ctx; + beforeAll(async() => { + ctx = { + accessToken: {userId: 9}, + req: { + headers: {origin: 'http://localhost'}, + __: key => key + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: ctx + }); + }); + it('should correctly login', async() => { - const response = await models.WorkerTimeControl.login(9); + const response = await models.WorkerTimeControl.login(ctx, 9); expect(response.name).toBe('developer'); }); it('should throw UserError if pin is not provided', async() => { try { - await models.WorkerTimeControl.login(); + await models.WorkerTimeControl.login(ctx); } catch (error) { expect(error).toBeInstanceOf(UserError); - expect(error.message).toBe('Incorrect pin.'); + expect(error.message).toBe('Incorrect pin'); } }); }); - From f73a447391b7541f41e3be2ccc05327c1254578e Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 3 Jan 2024 11:57:49 +0100 Subject: [PATCH 84/87] refs #6398 Hotfix 1/2 --- modules/ticket/back/models/ticket-tracking.json | 3 --- modules/ticket/front/tracking/index/index.html | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/ticket/back/models/ticket-tracking.json b/modules/ticket/back/models/ticket-tracking.json index 4b5a4d473..ac0eb9a69 100644 --- a/modules/ticket/back/models/ticket-tracking.json +++ b/modules/ticket/back/models/ticket-tracking.json @@ -20,9 +20,6 @@ }, "stateFk": { "type": "number" - }, - "userFk": { - "type": "number" } }, "relations": { diff --git a/modules/ticket/front/tracking/index/index.html b/modules/ticket/front/tracking/index/index.html index 12c4778c9..10ee6d848 100644 --- a/modules/ticket/front/tracking/index/index.html +++ b/modules/ticket/front/tracking/index/index.html @@ -23,9 +23,9 @@ {{::tracking.state.name}} - {{::tracking.worker.user.name || 'System' | translate}} + ng-class="{'link': tracking.user.id}" + ng-click="workerDescriptor.show($event, tracking.user.id)"> + {{::tracking.user.name || 'System' | translate}} {{::tracking.created | date:'dd/MM/yyyy HH:mm'}} From ba26237998a1bf2143c0b095963cd48aa1bffb28 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 3 Jan 2024 12:19:28 +0100 Subject: [PATCH 85/87] refs #5914 refactor: getTaxBases --- db/changes/240001/00-getTaxBases.sql | 10 ++++---- .../240001/01-newHasAnyPositiveBase.sql | 6 +++-- .../240001/01-refactorHasAnyNegativeBase.sql | 7 ++++-- .../front/descriptor-menu/locale/es.yml | 1 + .../back/methods/ticket/invoiceTickets.js | 2 +- .../ticket/specs/canBeInvoiced.spec.js | 25 +++++++++++++++++++ 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/db/changes/240001/00-getTaxBases.sql b/db/changes/240001/00-getTaxBases.sql index fa43c32f7..8bd1b745a 100644 --- a/db/changes/240001/00-getTaxBases.sql +++ b/db/changes/240001/00-getTaxBases.sql @@ -2,8 +2,8 @@ DELIMITER $$ $$ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`getTaxBases`() BEGIN - -/* Calcula y devuelve en número de bases imponibles postivas y negativas +/** +* Calcula y devuelve en número de bases imponibles postivas y negativas * Requiere la tabla temporal tmp.ticketToInvoice(id) * * returns tmp.taxBases @@ -21,10 +21,10 @@ BEGIN CREATE TEMPORARY TABLE tmp.taxBases ENGINE = MEMORY SELECT - SUM(CASE WHEN taxableBase > 0 THEN 1 ELSE 0 END) as positive, - SUM(CASE WHEN taxableBase < 0 THEN 1 ELSE 0 END) as negative + SUM(taxableBase > 0) as positive, + SUM(taxableBase < 0) as negative FROM( - SELECT SUM(taxableBase) as taxableBase + SELECT SUM(taxableBase) taxableBase FROM tmp.ticketTax GROUP BY pgcFk ) t; diff --git a/db/changes/240001/01-newHasAnyPositiveBase.sql b/db/changes/240001/01-newHasAnyPositiveBase.sql index 70fd51bcc..c4edfaed0 100644 --- a/db/changes/240001/01-newHasAnyPositiveBase.sql +++ b/db/changes/240001/01-newHasAnyPositiveBase.sql @@ -4,7 +4,8 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`hasAnyPositiveBase`( DETERMINISTIC BEGIN -/* Calcula si existe alguna base imponible positiva +/** +* Calcula si existe alguna base imponible positiva * Requiere la tabla temporal tmp.ticketToInvoice(id) para getTaxBases() * * returns BOOLEAN @@ -15,7 +16,8 @@ BEGIN CALL getTaxBases(); SELECT positive INTO hasAnyPositiveBase - FROM tmp.taxBases; + FROM tmp.taxBases + LIMIT 1; DROP TEMPORARY TABLE tmp.ticketTax, diff --git a/db/changes/240001/01-refactorHasAnyNegativeBase.sql b/db/changes/240001/01-refactorHasAnyNegativeBase.sql index f851ee6b9..a3eb2d9c7 100644 --- a/db/changes/240001/01-refactorHasAnyNegativeBase.sql +++ b/db/changes/240001/01-refactorHasAnyNegativeBase.sql @@ -4,7 +4,8 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`hasAnyNegativeBase`( DETERMINISTIC BEGIN -/* Calcula si existe alguna base imponible negativa +/** +* Calcula si existe alguna base imponible negativa * Requiere la tabla temporal tmp.ticketToInvoice(id) para getTaxBases() * * returns BOOLEAN @@ -15,7 +16,8 @@ BEGIN CALL getTaxBases(); SELECT negative INTO hasAnyNegativeBase - FROM tmp.taxBases; + FROM tmp.taxBases + LIMIT 1; DROP TEMPORARY TABLE tmp.ticketTax, @@ -27,3 +29,4 @@ BEGIN END$$ DELIMITER ; + diff --git a/modules/invoiceOut/front/descriptor-menu/locale/es.yml b/modules/invoiceOut/front/descriptor-menu/locale/es.yml index 9456646af..bf89b2ba0 100644 --- a/modules/invoiceOut/front/descriptor-menu/locale/es.yml +++ b/modules/invoiceOut/front/descriptor-menu/locale/es.yml @@ -23,3 +23,4 @@ The following refund tickets have been created: "Se han creado los siguientes ti Refund...: Abono... Transfer invoice to...: Transferir factura a... Rectificative type: Tipo rectificativa +Invoice trasfered!: ¡Factura transferida! diff --git a/modules/ticket/back/methods/ticket/invoiceTickets.js b/modules/ticket/back/methods/ticket/invoiceTickets.js index 57f623289..06429836e 100644 --- a/modules/ticket/back/methods/ticket/invoiceTickets.js +++ b/modules/ticket/back/methods/ticket/invoiceTickets.js @@ -71,7 +71,7 @@ module.exports = function(Self) { group[addressFk].push(id); return group; }, {})) - : [[ticketsIds]]; + : [ticketsIds]; for (const ticketIds of ticketsByAddress) invoicesIds.push(await createInvoice(ctx, companyId, ticketIds, invoiceCorrection, myOptions)); diff --git a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js index 1509b87df..78973e040 100644 --- a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js +++ b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js @@ -121,4 +121,29 @@ describe('ticket canBeInvoiced()', () => { throw e; } }); + + it('should return falsy for a ticket has positiveBase', async() => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = {transaction: tx}; + + await models.Ticket.rawSql(` + CREATE OR REPLACE TEMPORARY TABLE tmp.ticketToInvoice + (PRIMARY KEY (id)) + ENGINE = MEMORY + SELECT id + FROM vn.ticket + WHERE id IN (?) + `, [ticketId], options); + + await models.Ticket.canBeInvoiced(ctx, [ticketId], true, options); + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual(`hasAnyPositiveBase`); + }); }); From 227afbe39dfa3255f177a6d6736e1a4267bbe249 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 3 Jan 2024 14:54:01 +0100 Subject: [PATCH 86/87] refs #5914 fix(invoiceOut_descriptorMenu): transalation --- modules/invoiceOut/front/descriptor-menu/index.js | 2 +- modules/invoiceOut/front/descriptor-menu/locale/es.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js index aee323e39..2c28599e7 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.js +++ b/modules/invoiceOut/front/descriptor-menu/index.js @@ -137,7 +137,7 @@ class Controller extends Section { }; this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => { const invoiceId = res.data; - this.vnApp.showSuccess(this.$t('Invoice trasfered!')); + this.vnApp.showSuccess(this.$t('Transferred invoice')); this.$state.go('invoiceOut.card.summary', {id: invoiceId}); }); } diff --git a/modules/invoiceOut/front/descriptor-menu/locale/es.yml b/modules/invoiceOut/front/descriptor-menu/locale/es.yml index bf89b2ba0..aaeefd9cc 100644 --- a/modules/invoiceOut/front/descriptor-menu/locale/es.yml +++ b/modules/invoiceOut/front/descriptor-menu/locale/es.yml @@ -23,4 +23,4 @@ The following refund tickets have been created: "Se han creado los siguientes ti Refund...: Abono... Transfer invoice to...: Transferir factura a... Rectificative type: Tipo rectificativa -Invoice trasfered!: ¡Factura transferida! +Transferred invoice: Factura transferida From 2a65ad6b31d3055e6d13e345c5e86811ddf32ab9 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 4 Jan 2024 08:22:01 +0100 Subject: [PATCH 87/87] refs #6635 build: new version --- CHANGELOG.md | 7 +++++++ db/changes/240401/.gitkeep | 0 package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 db/changes/240401/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index 1907f46bd..69e93a309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +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). +## [2404.01] - 2024-01-25 + +### Added +### Changed +### Fixed + + ## [2402.01] - 2024-01-11 ### Added diff --git a/db/changes/240401/.gitkeep b/db/changes/240401/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/package-lock.json b/package-lock.json index 012fb50e7..36e11dc8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "salix-back", - "version": "24.02.01", + "version": "24.04.01", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "salix-back", - "version": "24.02.01", + "version": "24.04.01", "license": "GPL-3.0", "dependencies": { "axios": "^1.2.2", diff --git a/package.json b/package.json index ab3d99e19..f13c44162 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "24.02.01", + "version": "24.04.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0",