From 03e2f5730621e6ca2f481e455a6f693b450f7469 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 2 Nov 2023 10:57:50 +0100 Subject: [PATCH 1/9] refs #6067 fix: emailVerify url --- back/models/vn-user.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/back/models/vn-user.js b/back/models/vn-user.js index de5bf7b63..970497e4e 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -220,8 +220,11 @@ module.exports = function(Self) { class Mailer { async send(verifyOptions, cb) { + const url = new URL(verifyOptions.verifyHref); + if (process.env.NODE_ENV) url.port = ''; + const params = { - url: verifyOptions.verifyHref, + url: url.href, recipient: verifyOptions.to }; From 728838334cf427806ae42acaccbcd7e5944f1065 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Thu, 2 Nov 2023 14:42:22 +0100 Subject: [PATCH 2/9] hotFix_6312 fix originalQuantity --- modules/ticket/back/methods/sale/updateQuantity.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/sale/updateQuantity.js b/modules/ticket/back/methods/sale/updateQuantity.js index 1a497da24..610826283 100644 --- a/modules/ticket/back/methods/sale/updateQuantity.js +++ b/modules/ticket/back/methods/sale/updateQuantity.js @@ -64,7 +64,10 @@ module.exports = Self => { const sale = await models.Sale.findById(id, filter, myOptions); const oldQuantity = sale.quantity; - const result = await sale.updateAttributes({quantity: newQuantity}, myOptions); + const result = await sale.updateAttributes({ + quantity: newQuantity, + originalQuantity: newQuantity + }, myOptions); const salesPerson = sale.ticket().client().salesPersonUser(); if (salesPerson) { From 99c88e6f5ddea89ac38bc385ee47bae4cef0b445 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Sun, 5 Nov 2023 09:33:18 +0100 Subject: [PATCH 3/9] fix: refs #6390 Loggable set as base for ItemShelving --- modules/item/back/models/item-shelving.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/item/back/models/item-shelving.json b/modules/item/back/models/item-shelving.json index 61d05539e..bb1a141c4 100644 --- a/modules/item/back/models/item-shelving.json +++ b/modules/item/back/models/item-shelving.json @@ -1,6 +1,6 @@ { "name": "ItemShelving", - "base": "VnModel", + "base": "Loggable", "options": { "mysql": { "table": "itemShelving" From a1c8bba4a56e3d0d2907755e6060be55237f24fd Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 10 Nov 2023 11:29:18 +0100 Subject: [PATCH 4/9] hotfix addressId --- modules/ticket/back/methods/ticket/closure.js | 289 +++++++++--------- 1 file changed, 145 insertions(+), 144 deletions(-) diff --git a/modules/ticket/back/methods/ticket/closure.js b/modules/ticket/back/methods/ticket/closure.js index 9f9aec9bd..1d04679d3 100644 --- a/modules/ticket/back/methods/ticket/closure.js +++ b/modules/ticket/back/methods/ticket/closure.js @@ -5,177 +5,178 @@ const config = require('vn-print/core/config'); const storage = require('vn-print/core/storage'); module.exports = async function(ctx, Self, tickets, reqArgs = {}) { - const userId = ctx.req.accessToken.userId; - if (tickets.length == 0) return; + const userId = ctx.req.accessToken.userId; + if (tickets.length == 0) return; - const failedtickets = []; - for (const ticket of tickets) { - try { - await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId}); + const failedtickets = []; + for (const ticket of tickets) { + try { + await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId}); - const [invoiceOut] = await Self.rawSql(` - SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued - FROM ticket t - JOIN invoiceOut io ON io.ref = t.refFk - JOIN company cny ON cny.id = io.companyFk - WHERE t.id = ? - `, [ticket.id]); + const [invoiceOut] = await Self.rawSql(` + SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued + FROM ticket t + JOIN invoiceOut io ON io.ref = t.refFk + JOIN company cny ON cny.id = io.companyFk + WHERE t.id = ? + `, [ticket.id]); - const mailOptions = { - overrideAttachments: true, - attachments: [] - }; + const mailOptions = { + overrideAttachments: true, + attachments: [] + }; - const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed; + const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed; - if (invoiceOut) { - const args = { - reference: invoiceOut.ref, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }; + if (invoiceOut) { + const args = { + reference: invoiceOut.ref, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; - const invoiceReport = new Report('invoice', args); - const stream = await invoiceReport.toPdfStream(); + const invoiceReport = new Report('invoice', args); + const stream = await invoiceReport.toPdfStream(); - const issued = invoiceOut.issued; - const year = issued.getFullYear().toString(); - const month = (issued.getMonth() + 1).toString(); - const day = issued.getDate().toString(); + const issued = invoiceOut.issued; + const year = issued.getFullYear().toString(); + const month = (issued.getMonth() + 1).toString(); + const day = issued.getDate().toString(); - const fileName = `${year}${invoiceOut.ref}.pdf`; + const fileName = `${year}${invoiceOut.ref}.pdf`; - // Store invoice - await storage.write(stream, { - type: 'invoice', - path: `${year}/${month}/${day}`, - fileName: fileName - }); + // Store invoice + await storage.write(stream, { + type: 'invoice', + path: `${year}/${month}/${day}`, + fileName: fileName + }); - await Self.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id], {userId}); + await Self.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id], {userId}); - if (isToBeMailed) { - const invoiceAttachment = { - filename: fileName, - content: stream - }; + if (isToBeMailed) { + const invoiceAttachment = { + filename: fileName, + content: stream + }; - if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') { - const exportation = new Report('exportation', args); - const stream = await exportation.toPdfStream(); - const fileName = `CITES-${invoiceOut.ref}.pdf`; + if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') { + const exportation = new Report('exportation', args); + const stream = await exportation.toPdfStream(); + const fileName = `CITES-${invoiceOut.ref}.pdf`; - mailOptions.attachments.push({ - filename: fileName, - content: stream - }); - } + mailOptions.attachments.push({ + filename: fileName, + content: stream + }); + } - mailOptions.attachments.push(invoiceAttachment); + mailOptions.attachments.push(invoiceAttachment); - const email = new Email('invoice', args); - await email.send(mailOptions); - } - } else if (isToBeMailed) { - const args = { - id: ticket.id, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }; + const email = new Email('invoice', args); + await email.send(mailOptions); + } + } else if (isToBeMailed) { + const args = { + id: ticket.id, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; - const email = new Email('delivery-note-link', args); - await email.send(); - } + const email = new Email('delivery-note-link', args); + await email.send(); + } - // Incoterms authorization - const [{firstOrder}] = await Self.rawSql(` - SELECT COUNT(*) as firstOrder - FROM ticket t - JOIN client c ON c.id = t.clientFk - WHERE t.clientFk = ? - AND NOT t.isDeleted - AND c.isVies - `, [ticket.clientFk]); + // Incoterms authorization + const [{firstOrder}] = await Self.rawSql(` + SELECT COUNT(*) as firstOrder + FROM ticket t + JOIN client c ON c.id = t.clientFk + WHERE t.clientFk = ? + AND NOT t.isDeleted + AND c.isVies + `, [ticket.clientFk]); - if (firstOrder == 1) { - const args = { - id: ticket.clientFk, - companyId: ticket.companyFk, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }; + if (firstOrder == 1) { + const args = { + id: ticket.clientFk, + companyId: ticket.companyFk, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail, + addressId: ticket.addressFk + }; - const email = new Email('incoterms-authorization', args); - await email.send(); + const email = new Email('incoterms-authorization', args); + await email.send(); - const [sample] = await Self.rawSql( - `SELECT id - FROM sample - WHERE code = 'incoterms-authorization' - `); + const [sample] = await Self.rawSql( + `SELECT id + FROM sample + WHERE code = 'incoterms-authorization' + `); - await Self.rawSql(` - INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) - `, [ticket.clientFk, sample.id, ticket.companyFk], {userId}); - }; - } catch (error) { - // Domain not found - if (error.responseCode == 450) - return invalidEmail(ticket); + await Self.rawSql(` + INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) + `, [ticket.clientFk, sample.id, ticket.companyFk], {userId}); + } + } catch (error) { + // Domain not found + if (error.responseCode == 450) + return invalidEmail(ticket); - // Save tickets on a list of failed ids - failedtickets.push({ - id: ticket.id, - stacktrace: error - }); - } - } + // Save tickets on a list of failed ids + failedtickets.push({ + id: ticket.id, + stacktrace: error + }); + } + } - // Send email with failed tickets - if (failedtickets.length > 0) { - let body = 'This following tickets have failed:

'; + // Send email with failed tickets + if (failedtickets.length > 0) { + let body = 'This following tickets have failed:

'; - for (const ticket of failedtickets) { - body += `Ticket: ${ticket.id} -
${ticket.stacktrace}

`; - } + for (const ticket of failedtickets) { + body += `Ticket: ${ticket.id} +
${ticket.stacktrace}

`; + } - smtp.send({ - to: config.app.reportEmail, - subject: '[API] Nightly ticket closure report', - html: body - }); - } + smtp.send({ + to: config.app.reportEmail, + subject: '[API] Nightly ticket closure report', + html: body + }); + } - async function invalidEmail(ticket) { - await Self.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [ - ticket.clientFk - ], {userId}); + async function invalidEmail(ticket) { + await Self.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [ + ticket.clientFk + ], {userId}); - const oldInstance = `{"email": "${ticket.recipient}"}`; - const newInstance = `{"email": ""}`; - await Self.rawSql(` - INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) - VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [ - ticket.clientFk, - oldInstance, - newInstance - ], {userId}); + const oldInstance = `{"email": "${ticket.recipient}"}`; + const newInstance = `{"email": ""}`; + await Self.rawSql(` + INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) + VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [ + ticket.clientFk, + oldInstance, + newInstance + ], {userId}); - const body = `No se ha podido enviar el albarán ${ticket.id} - al cliente ${ticket.clientFk} - ${ticket.clientName} - porque la dirección de email "${ticket.recipient}" no es correcta - o no está disponible.

- Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. - Actualiza la dirección de email con una correcta.`; + const body = `No se ha podido enviar el albarán ${ticket.id} + al cliente ${ticket.clientFk} - ${ticket.clientName} + porque la dirección de email "${ticket.recipient}" no es correcta + o no está disponible.

+ Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. + Actualiza la dirección de email con una correcta.`; - smtp.send({ - to: ticket.salesPersonEmail, - subject: 'No se ha podido enviar el albarán', - html: body - }); - } + smtp.send({ + to: ticket.salesPersonEmail, + subject: 'No se ha podido enviar el albarán', + html: body + }); + } }; From 1a66987cd0ff298ff392ad27d43a81bed410eb14 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 13 Nov 2023 12:26:31 +0100 Subject: [PATCH 5/9] refs #5979 fix(vn-user): resetPassword url --- back/models/vn-user.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 970497e4e..712ed7d16 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -92,7 +92,11 @@ module.exports = function(Self) { }; Self.on('resetPasswordRequest', async function(info) { - const url = await Self.app.models.Url.getUrl(); + const loopBackContext = LoopBackContext.getCurrentContext(); + const httpCtx = {req: loopBackContext.active}; + const httpRequest = httpCtx.req.http.req; + const headers = httpRequest.headers; + const origin = headers.origin; const defaultHash = '/reset-password?access_token=$token$'; const recoverHashes = { @@ -108,7 +112,7 @@ module.exports = function(Self) { const params = { recipient: info.email, lang: user.lang, - url: url.slice(0, -1) + recoverHash + url: origin + '/#!' + recoverHash }; const options = Object.assign({}, info.options); From f3faf37e1a0e77227402a2c41fa54b5fdd2f5f7c Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 14 Nov 2023 12:34:00 +0100 Subject: [PATCH 6/9] hotfix addressFk --- .../ticket/back/methods/ticket/closeAll.js | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/modules/ticket/back/methods/ticket/closeAll.js b/modules/ticket/back/methods/ticket/closeAll.js index 660c16893..46c45aa92 100644 --- a/modules/ticket/back/methods/ticket/closeAll.js +++ b/modules/ticket/back/methods/ticket/closeAll.js @@ -32,31 +32,30 @@ module.exports = Self => { throw new UserError('You cannot close tickets for today'); const tickets = await Self.rawSql(` - SELECT - t.id, - t.clientFk, - t.companyFk, - c.name clientName, - c.email recipient, - c.salesPersonFk, - c.isToBeMailed, - c.hasToInvoice, - co.hasDailyInvoice, - eu.email salesPersonEmail - FROM ticket t - JOIN agencyMode am ON am.id = t.agencyModeFk - JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission - JOIN ticketState ts ON ts.ticketFk = t.id - JOIN alertLevel al ON al.id = ts.alertLevel - JOIN client c ON c.id = t.clientFk - JOIN province p ON p.id = c.provinceFk - JOIN country co ON co.id = p.countryFk - LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk - WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code != 'delivered')) - AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) - AND util.dayEnd(?) - AND t.refFk IS NULL - GROUP BY t.id + SELECT t.id, + t.clientFk, + t.companyFk, + c.name clientName, + c.email recipient, + c.salesPersonFk, + c.isToBeMailed, + c.hasToInvoice, + co.hasDailyInvoice, + eu.email salesPersonEmail, + t.addressFk + FROM ticket t + JOIN agencyMode am ON am.id = t.agencyModeFk + JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN alertLevel al ON al.id = ts.alertLevel + JOIN client c ON c.id = t.clientFk + JOIN province p ON p.id = c.provinceFk + JOIN country co ON co.id = p.countryFk + LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk + WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code != 'delivered')) + AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) AND util.dayEnd(?) + AND t.refFk IS NULL + GROUP BY t.id `, [toDate, toDate]); await closure(ctx, Self, tickets); From a5682e9a0d663637c6f5b726569cd364e8b8a933 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Tue, 14 Nov 2023 15:39:50 +0100 Subject: [PATCH 7/9] doc: refs #6062 README abbreviation --- README.md | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 59f5dbcf7..b420bc44f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Salix is also the scientific name of a beautifull tree! :) Required applications. -* Node.js >= 16.x LTS +* Node.js * Docker * Git @@ -17,20 +17,7 @@ You will need to install globally the following items. $ sudo npm install -g jest gulp-cli ``` -For the usage of jest --watch on macOs. -``` -$ brew install watchman -``` -* [watchman](https://facebook.github.io/watchman/) - -## Linux Only Prerequisites - -Your user must be on the docker group to use it so you will need to run this command: -``` -$ sudo usermod -a -G docker yourusername -``` - -## Getting Started // Installing +## Installing dependencies and launching Pull from repository. @@ -76,29 +63,6 @@ In Visual Studio Code we use the ESLint extension. ext install dbaeumer.vscode-eslint ``` -Gitlens for visualization of code authorship -``` -ext install eamodio.gitlens -``` - -Spanish language pack -``` -ext install ms-ceintl.vscode-language-pack-es -``` - -### Recommended extensions - -Material icon Theme -``` -ext install pkief.material-icon-theme -``` - -Material UI Themes -``` -ext install equinusocio.vsc-material-theme -``` - - ## Built With * [angularjs](https://angularjs.org/) From 89967b85383fd53c5232b1a0cfc92b670ab6bf56 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 15 Nov 2023 13:16:31 +0100 Subject: [PATCH 8/9] fix(workerDescriptor): show account button --- modules/worker/front/descriptor/index.html | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/worker/front/descriptor/index.html b/modules/worker/front/descriptor/index.html index aa6b80300..8290e2a15 100644 --- a/modules/worker/front/descriptor/index.html +++ b/modules/worker/front/descriptor/index.html @@ -38,7 +38,7 @@ + > @@ -61,8 +61,6 @@
@@ -75,13 +73,13 @@ - - Date: Thu, 16 Nov 2023 07:27:42 +0100 Subject: [PATCH 9/9] fix: translation --- loopback/locale/es.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 4b297144f..74dc2f15a 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -321,6 +321,6 @@ "Ticket without Route": "Ticket sin ruta", "Booking completed": "Reserva completada", "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 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" }