From 3e522b08b6c7fc93eb36b1721814f6efbfe428f0 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 11 Oct 2023 11:43:21 +0200 Subject: [PATCH 01/35] refs #6184 Added saveCmr --- modules/ticket/back/methods/ticket/saveCmr.js | 82 +++++++++++++++++++ .../ticket/back/methods/ticket/saveSign.js | 3 +- modules/ticket/back/models/ticket-methods.js | 1 + 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 modules/ticket/back/methods/ticket/saveCmr.js diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js new file mode 100644 index 000000000..ce39ba20a --- /dev/null +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -0,0 +1,82 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('saveCmr', { + description: 'Save sign', + accessType: 'WRITE', + accepts: + [ + { + arg: 'tickets', + type: ['number'], + required: true, + description: 'The tickets' + } + ], + http: { + path: `/saveCmr`, + verb: 'POST' + } + }); + + Self.saveCmr = async(ctx, tickets, options) => { + const models = Self.app.models; + const myOptions = {userId: ctx.req.accessToken.userId}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + for (const ticketId of tickets) { + const cmrFk = await models.Ticket.findOne( + {where: {id: ticketId}, + fields: ['cmrFk'] + }, myOptions); + + if (cmrFk) { + const dmsTypeCmr = await models.DmsType.findOne({ + where: {code: 'ticket'}, + fields: ['id'] + }, myOptions); + + const hasDmsCmr = await models.TicketDms.findOne({ + where: { ticketFk: ticketId }, + fields: ['dmsFk'], + include: { + relation: 'dms', + scope: { + where: { dmsTypeFk: dmsTypeCmr } + } + } + }, myOptions); + + if (!hasDmsCmr) { + const zip = await models.Route.downloadCmrsZip(ctx, cmr, myOptions); + const ticket = await models.Ticket.findById(ticketId, null, myOptions); + const ctxUploadFile = Object.assign({}, zip); + ctxUploadFile.args = { + warehouseId: ticket.warehouseFk, + companyId: ticket.companyFk, + dmsTypeId: dmsTypeCmr.id, + reference: '', + description: `Documento comprimido - CMR ${cmrFk}`, + hasFile: false + }; + await models.Dms.uploadFile(ctxUploadFile, myOptions); + } + } + } + if (tx) await tx.commit(); + return; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 9888328e7..015a95afb 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -91,7 +91,7 @@ module.exports = Self => { } ] }, myOptions); - const dmsType = await models.DmsType.findOne({where: {code: 'Ticket'}, fields: ['id']}, myOptions); + const dmsType = await models.DmsType.findOne({where: {code: 'ticket'}, fields: ['id']}, myOptions); const ctxUploadFile = Object.assign({}, ctx); if (ticket.route() === null) throw new UserError('Ticket without route'); @@ -131,6 +131,7 @@ module.exports = Self => { const ticket = await models.Ticket.findById(ticketId, null, myOptions); await ticket.updateAttribute('isSigned', true, myOptions); await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [ticketId, 'DELIVERED'], myOptions); + await models.Ticket.saveCmr(ticketId, myOptions); } if (tx) await tx.commit(); diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js index 14cb104be..c932548e1 100644 --- a/modules/ticket/back/models/ticket-methods.js +++ b/modules/ticket/back/models/ticket-methods.js @@ -41,6 +41,7 @@ module.exports = function(Self) { require('../methods/ticket/collectionLabel')(Self); require('../methods/ticket/expeditionPalletLabel')(Self); require('../methods/ticket/saveSign')(Self); + require('../methods/ticket/saveCmr')(Self); require('../methods/ticket/invoiceTickets')(Self); require('../methods/ticket/docuwareDownload')(Self); }; From d9339af87e0fc92fd05dc5cc20499bd66963adb8 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 11 Oct 2023 11:46:56 +0200 Subject: [PATCH 02/35] refs #6184 Insert in ticketCmr --- modules/ticket/back/methods/ticket/saveCmr.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index ce39ba20a..5df4d8ae7 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -22,7 +22,7 @@ module.exports = Self => { Self.saveCmr = async(ctx, tickets, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; - let tx; + let tx, dms; if (typeof options == 'object') Object.assign(myOptions, options); @@ -68,7 +68,8 @@ module.exports = Self => { description: `Documento comprimido - CMR ${cmrFk}`, hasFile: false }; - await models.Dms.uploadFile(ctxUploadFile, myOptions); + dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); + await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); } } } From c0089b1fa0b38a0927a046d33c5905cb5f2a4fa2 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 11 Oct 2023 12:20:30 +0200 Subject: [PATCH 03/35] refs #6184 Added cmrFk in ticket model --- modules/ticket/back/methods/ticket/saveCmr.js | 12 +++++------- modules/ticket/back/models/ticket.json | 3 +++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 5df4d8ae7..06dc5b7fb 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -1,8 +1,6 @@ -const UserError = require('vn-loopback/util/user-error'); - module.exports = Self => { Self.remoteMethodCtx('saveCmr', { - description: 'Save sign', + description: 'Save cmr', accessType: 'WRITE', accepts: [ @@ -34,10 +32,10 @@ module.exports = Self => { try { for (const ticketId of tickets) { - const cmrFk = await models.Ticket.findOne( - {where: {id: ticketId}, - fields: ['cmrFk'] - }, myOptions); + const cmrFk = await models.Ticket.findOne({ + where: {id: ticketId}, + fields: ['cmrFk'] + }, myOptions); if (cmrFk) { const dmsTypeCmr = await models.DmsType.findOne({ diff --git a/modules/ticket/back/models/ticket.json b/modules/ticket/back/models/ticket.json index ec4193bed..b5f2b5ed9 100644 --- a/modules/ticket/back/models/ticket.json +++ b/modules/ticket/back/models/ticket.json @@ -63,6 +63,9 @@ }, "weight": { "type": "number" + }, + "cmrFk": { + "type": "number" } }, "relations": { From 3e70cb07e0c0cfdff874323b533ffdd41b738973 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 11 Oct 2023 14:20:35 +0200 Subject: [PATCH 04/35] refs #6184 Changes --- .../back/methods/route/downloadCmrsZip.js | 6 +- modules/route/back/models/cmr.json | 58 +++++++++++++++++++ modules/ticket/back/methods/ticket/saveCmr.js | 37 ++++++------ modules/ticket/back/models/ticket.json | 5 ++ 4 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 modules/route/back/models/cmr.json diff --git a/modules/route/back/methods/route/downloadCmrsZip.js b/modules/route/back/methods/route/downloadCmrsZip.js index 532e019b6..c3379ab82 100644 --- a/modules/route/back/methods/route/downloadCmrsZip.js +++ b/modules/route/back/methods/route/downloadCmrsZip.js @@ -49,8 +49,12 @@ module.exports = Self => { try { for (let id of ids) { if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); + + const baseUrl = (ctx.req.headers.origin) + ? `${ctx.req.headers.origin}/api` + : `${ctx.req.headers.referer}api` const response = await axios.get( - `${ctx.req.headers.referer}api/Routes/${id}/cmr?access_token=${token.id}`, { + `${baseUrl}/Routes/${id}/cmr?access_token=${token.id}`, { ...myOptions, responseType: 'arraybuffer', }); diff --git a/modules/route/back/models/cmr.json b/modules/route/back/models/cmr.json new file mode 100644 index 000000000..0e2168bed --- /dev/null +++ b/modules/route/back/models/cmr.json @@ -0,0 +1,58 @@ +{ + "name": "Cmr", + "base": "VnModel", + "options": { + "mysql": { + "table": "cmr" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "truckPlate": { + "type": "number" + }, + "observations": { + "type": "string" + }, + "senderInstrucctions": { + "type": "string" + }, + "paymentInstruccions": { + "type": "string" + }, + "specialAgreements": { + "type": "string" + }, + "created": { + "type": "date" + }, + "companyFk": { + "type": "number" + }, + "addressToFk": { + "type": "number" + }, + "addressFromFk": { + "type": "number" + }, + "supplierFk": { + "type": "number" + }, + "packagesList": { + "type": "string" + }, + "merchandiseDetail": { + "type": "string" + }, + "landed": { + "type": "date" + }, + "ead": { + "type": "date" + } + } +} diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 06dc5b7fb..2bd52aaa8 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -20,7 +20,7 @@ module.exports = Self => { Self.saveCmr = async(ctx, tickets, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; - let tx, dms; + let tx; if (typeof options == 'object') Object.assign(myOptions, options); @@ -32,42 +32,43 @@ module.exports = Self => { try { for (const ticketId of tickets) { - const cmrFk = await models.Ticket.findOne({ - where: {id: ticketId}, - fields: ['cmrFk'] - }, myOptions); + const ticket = await models.Ticket.findById(ticketId, myOptions); - if (cmrFk) { - const dmsTypeCmr = await models.DmsType.findOne({ - where: {code: 'ticket'}, + if (ticket.cmrFk) { + const dmsType = await models.DmsType.findOne({ + where: {code: 'cmr'}, fields: ['id'] }, myOptions); const hasDmsCmr = await models.TicketDms.findOne({ where: { ticketFk: ticketId }, - fields: ['dmsFk'], include: { relation: 'dms', + fields: ['dmsFk'], scope: { - where: { dmsTypeFk: dmsTypeCmr } + where: { dmsTypeFk: dmsType.id } } } }, myOptions); - if (!hasDmsCmr) { - const zip = await models.Route.downloadCmrsZip(ctx, cmr, myOptions); - const ticket = await models.Ticket.findById(ticketId, null, myOptions); - const ctxUploadFile = Object.assign({}, zip); + if (!hasDmsCmr.dms()) { + const zip = await models.Route.downloadCmrsZip(ctx, ticket.cmrFk.toString(), myOptions); + let ctxUploadFile; + ctx.req.file = Object.assign({}, zip); + ctxUploadFile = Object.assign({}, ctx); ctxUploadFile.args = { warehouseId: ticket.warehouseFk, companyId: ticket.companyFk, - dmsTypeId: dmsTypeCmr.id, + dmsTypeId: dmsType.id, reference: '', - description: `Documento comprimido - CMR ${cmrFk}`, + description: `Documento comprimido - CMR ${ticket.cmrFk}`, hasFile: false }; - dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); - await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); + const dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); + await models.TicketDms.create({ + ticketFk: ticketId, + dmsFk: dms[0].id + }, myOptions); } } } diff --git a/modules/ticket/back/models/ticket.json b/modules/ticket/back/models/ticket.json index b5f2b5ed9..4a5205d3d 100644 --- a/modules/ticket/back/models/ticket.json +++ b/modules/ticket/back/models/ticket.json @@ -139,6 +139,11 @@ "type": "belongsTo", "model": "Zone", "foreignKey": "zoneFk" + }, + "cmrFk": { + "type": "belongsTo", + "model": "Cmr", + "foreignKey": "cmrFk" } } } From 0771548ef1c5ce9cbff10f2fd427f836aa696458 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 9 Nov 2023 14:14:09 +0100 Subject: [PATCH 05/35] refs #6184 Requested changes --- modules/ticket/back/methods/ticket/saveCmr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 2bd52aaa8..c322dd27c 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -61,7 +61,7 @@ module.exports = Self => { companyId: ticket.companyFk, dmsTypeId: dmsType.id, reference: '', - description: `Documento comprimido - CMR ${ticket.cmrFk}`, + description: `${ticket.cmrFk} - ${ticket.id}`, hasFile: false }; const dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); From 2792efa9cd4030d9d6fbf27f48e5c4cf2e6654bf Mon Sep 17 00:00:00 2001 From: guillermo Date: Mon, 13 Nov 2023 08:36:05 +0100 Subject: [PATCH 06/35] perf: refs #6184 Requested changes --- modules/ticket/back/methods/ticket/saveCmr.js | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index c322dd27c..680e7a1f0 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -31,38 +31,39 @@ module.exports = Self => { } try { + const dmsTypeCmr = await models.DmsType.findOne({ + where: {code: 'cmr'}, + fields: ['id'] + }, myOptions); + for (const ticketId of tickets) { const ticket = await models.Ticket.findById(ticketId, myOptions); if (ticket.cmrFk) { - const dmsType = await models.DmsType.findOne({ - where: {code: 'cmr'}, - fields: ['id'] - }, myOptions); - const hasDmsCmr = await models.TicketDms.findOne({ where: { ticketFk: ticketId }, include: { relation: 'dms', fields: ['dmsFk'], scope: { - where: { dmsTypeFk: dmsType.id } + where: { dmsTypeFk: dmsTypeCmr.id } } } }, myOptions); if (!hasDmsCmr.dms()) { const zip = await models.Route.downloadCmrsZip(ctx, ticket.cmrFk.toString(), myOptions); - let ctxUploadFile; ctx.req.file = Object.assign({}, zip); - ctxUploadFile = Object.assign({}, ctx); - ctxUploadFile.args = { - warehouseId: ticket.warehouseFk, - companyId: ticket.companyFk, - dmsTypeId: dmsType.id, - reference: '', - description: `${ticket.cmrFk} - ${ticket.id}`, - hasFile: false + const ctxUploadFile = { + ...ctx, + args: { + warehouseId: ticket.warehouseFk, + companyId: ticket.companyFk, + dmsTypeId: dmsTypeCmr.id, + reference: ticket.id, + description: `${ticket.cmrFk} - ${ticket.id}`, + hasFile: false + } }; const dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); await models.TicketDms.create({ From 64ca72b1f44568151e86e065f6986162ca9b47de Mon Sep 17 00:00:00 2001 From: guillermo Date: Mon, 13 Nov 2023 09:57:25 +0100 Subject: [PATCH 07/35] refactor refs #6184 Changed downloadCmrsZip --- .../route/back/methods/route/downloadCmrsZip.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/route/back/methods/route/downloadCmrsZip.js b/modules/route/back/methods/route/downloadCmrsZip.js index c3379ab82..23fae5ddc 100644 --- a/modules/route/back/methods/route/downloadCmrsZip.js +++ b/modules/route/back/methods/route/downloadCmrsZip.js @@ -37,7 +37,6 @@ module.exports = Self => { Self.downloadCmrsZip = async function(ctx, ids, options) { const models = Self.app.models; const myOptions = {}; - const token = ctx.req.accessToken; const zip = new JSZip(); if (typeof options == 'object') @@ -47,18 +46,20 @@ module.exports = Self => { let totalSize = 0; ids = ids.split(','); try { - for (let id of ids) { + const baseUrl = (await Self.app.models.Url.getUrl()).replace('#!', 'api'); + + for (const id of ids) { if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); - const baseUrl = (ctx.req.headers.origin) - ? `${ctx.req.headers.origin}/api` - : `${ctx.req.headers.referer}api` const response = await axios.get( - `${baseUrl}/Routes/${id}/cmr?access_token=${token.id}`, { + `${baseUrl}Routes/${id}/cmr`, { ...myOptions, + headers: { + Authorization: ctx.req.accessToken.id + }, responseType: 'arraybuffer', }); - + if (response.headers['content-type'] !== 'application/pdf') throw new UserError(`The response is not a PDF`); From 45fd96cee6d59d14852529aaf0bdf9e1af7d1795 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 17 Jan 2024 13:07:26 +0100 Subject: [PATCH 08/35] feat: #6184 Modified uploadFile --- back/methods/dms/uploadFile.js | 46 +++++-------------- back/models/dms.js | 30 ++++++++++++ .../back/methods/route/downloadCmrsZip.js | 33 ++++++------- modules/ticket/back/methods/ticket/saveCmr.js | 28 +++++------ 4 files changed, 71 insertions(+), 66 deletions(-) diff --git a/back/methods/dms/uploadFile.js b/back/methods/dms/uploadFile.js index a4212b804..728ae229f 100644 --- a/back/methods/dms/uploadFile.js +++ b/back/methods/dms/uploadFile.js @@ -49,7 +49,6 @@ module.exports = Self => { Self.uploadFile = async(ctx, options) => { const models = Self.app.models; const TempContainer = models.TempContainer; - const DmsContainer = models.DmsContainer; const fileOptions = {}; const args = ctx.args; @@ -79,19 +78,21 @@ module.exports = Self => { const addedDms = []; for (const uploadedFile of files) { - const newDms = await createDms(ctx, uploadedFile, myOptions); - const pathHash = DmsContainer.getHash(newDms.id); - const file = await TempContainer.getFile(tempContainer.name, uploadedFile.name); srcFile = path.join(file.client.root, file.container, file.name); - const dmsContainer = await DmsContainer.container(pathHash); - const dstFile = path.join(dmsContainer.client.root, pathHash, newDms.file); - - await fs.move(srcFile, dstFile, { - overwrite: true - }); - + const data = { + workerFk: ctx.req.accessToken.userId, + dmsTypeFk: args.dmsTypeId, + companyFk: args.companyId, + warehouseFk: args.warehouseId, + reference: args.reference, + description: args.description, + contentType: file.type, + hasFile: args.hasFile + }; + const extension = await models.DmsContainer.getFileExtension(uploadedFile.name); + const newDms = await Self.createFromFile(data, extension, srcFile, myOptions); addedDms.push(newDms); } @@ -107,27 +108,4 @@ module.exports = Self => { throw e; } }; - - async function createDms(ctx, file, myOptions) { - const models = Self.app.models; - const myUserId = ctx.req.accessToken.userId; - const args = ctx.args; - - const newDms = await Self.create({ - workerFk: myUserId, - dmsTypeFk: args.dmsTypeId, - companyFk: args.companyId, - warehouseFk: args.warehouseId, - reference: args.reference, - description: args.description, - contentType: file.type, - hasFile: args.hasFile - }, myOptions); - - let fileName = file.name; - const extension = models.DmsContainer.getFileExtension(fileName); - fileName = `${newDms.id}.${extension}`; - - return newDms.updateAttribute('file', fileName, myOptions); - } }; diff --git a/back/models/dms.js b/back/models/dms.js index 24c072f56..e5b925e82 100644 --- a/back/models/dms.js +++ b/back/models/dms.js @@ -1,4 +1,6 @@ const UserError = require('vn-loopback/util/user-error'); +const fs = require('fs-extra'); +const path = require('path'); module.exports = Self => { require('../methods/dms/downloadFile')(Self); @@ -35,4 +37,32 @@ module.exports = Self => { return [stream, dms.contentType, `filename="${dms.file}"`]; }; + + Self.getPath = async function(dms) { + const models = Self.app.models; + const pathHash = await models.DmsContainer.getHash(dms.id); + const dmsContainer = await models.DmsContainer.container(pathHash); + const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file); + return dstFile; + }; + + Self.createWithExtension = async function(data, extension, options) { + const newDms = await Self.create(data, options); + return newDms.updateAttribute('file', `${newDms.id}.${extension}`, options); + }; + + Self.createFromFile = async function(data, extension, srcFile, options) { + const dms = await Self.createWithExtension(data, extension, options); + const dstFile = await Self.getPath(dms); + await fs.move(srcFile, dstFile, {overwrite: true}); + return dms; + }; + + Self.createFromStream = async function(data, extension, stream, options) { + const dms = await Self.createWithExtension(data, extension, options); + const dstFile = await Self.getPath(dms); + const writeStream = await fs.createWriteStream(dstFile); + await readStream.pipe(writeStream); + return dms; + }; }; diff --git a/modules/route/back/methods/route/downloadCmrsZip.js b/modules/route/back/methods/route/downloadCmrsZip.js index 23fae5ddc..fbf439d24 100644 --- a/modules/route/back/methods/route/downloadCmrsZip.js +++ b/modules/route/back/methods/route/downloadCmrsZip.js @@ -45,32 +45,29 @@ module.exports = Self => { const zipConfig = await models.ZipConfig.findOne(null, myOptions); let totalSize = 0; ids = ids.split(','); - try { - const baseUrl = (await Self.app.models.Url.getUrl()).replace('#!', 'api'); - for (const id of ids) { - if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); + const baseUrl = (await Self.app.models.Url.getUrl()).replace('#!', 'api'); - const response = await axios.get( - `${baseUrl}Routes/${id}/cmr`, { + for (const id of ids) { + if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); + + const response = await axios.get( + `${baseUrl}Routes/${id}/cmr`, { ...myOptions, headers: { Authorization: ctx.req.accessToken.id }, responseType: 'arraybuffer', }); - - if (response.headers['content-type'] !== 'application/pdf') - throw new UserError(`The response is not a PDF`); - - zip.file(`${id}.pdf`, response.data, { binary: true }); - } - - const zipStream = zip.generateNodeStream({ streamFiles: true }); - - return [zipStream, 'application/zip', `filename="cmrs.zip"`]; - } catch (e) { - throw e; + + if (response.headers['content-type'] !== 'application/pdf') + throw new UserError(`The response is not a PDF`); + + zip.file(`${id}.pdf`, response.data, {binary: true}); } + + const zipStream = zip.generateNodeStream({streamFiles: true}); + + return [zipStream, 'application/zip', `filename="cmrs.zip"`]; }; }; diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 680e7a1f0..01c45e104 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -41,31 +41,31 @@ module.exports = Self => { if (ticket.cmrFk) { const hasDmsCmr = await models.TicketDms.findOne({ - where: { ticketFk: ticketId }, + where: {ticketFk: ticketId}, include: { relation: 'dms', fields: ['dmsFk'], scope: { - where: { dmsTypeFk: dmsTypeCmr.id } + where: {dmsTypeFk: dmsTypeCmr.id} } } }, myOptions); if (!hasDmsCmr.dms()) { const zip = await models.Route.downloadCmrsZip(ctx, ticket.cmrFk.toString(), myOptions); - ctx.req.file = Object.assign({}, zip); - const ctxUploadFile = { - ...ctx, - args: { - warehouseId: ticket.warehouseFk, - companyId: ticket.companyFk, - dmsTypeId: dmsTypeCmr.id, - reference: ticket.id, - description: `${ticket.cmrFk} - ${ticket.id}`, - hasFile: false - } + const stream = Object.assign({}, zip); + const data = { + workerFk: ctx.req.accessToken.userId, + dmsTypeFk: dmsTypeCmr.id, + companyFk: ticket.companyFk, + warehouseFk: ticket.warehouseFk, + reference: ticket.id, + description: `${ticket.cmrFk} - ${ticket.id}`, + contentType: '?', + hasFile: false }; - const dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); + + const dms = await models.Dms.createFromStream(data, 'zip', stream, myOptions); await models.TicketDms.create({ ticketFk: ticketId, dmsFk: dms[0].id From 1a52e58eaaf2fc13e8e619eceeda11fe55d01e8e Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 17 Jan 2024 14:18:31 +0100 Subject: [PATCH 09/35] feat: #6184 Created generateCmrPdf --- back/models/dms.js | 2 +- .../back/methods/route/downloadCmrsZip.js | 23 +------ .../back/methods/route/generateCmrPdf.js | 64 +++++++++++++++++++ modules/route/back/models/route.js | 1 + modules/ticket/back/methods/ticket/saveCmr.js | 16 +++-- 5 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 modules/route/back/methods/route/generateCmrPdf.js diff --git a/back/models/dms.js b/back/models/dms.js index e5b925e82..d6eab4fe4 100644 --- a/back/models/dms.js +++ b/back/models/dms.js @@ -62,7 +62,7 @@ module.exports = Self => { const dms = await Self.createWithExtension(data, extension, options); const dstFile = await Self.getPath(dms); const writeStream = await fs.createWriteStream(dstFile); - await readStream.pipe(writeStream); + await stream.pipe(writeStream); return dms; }; }; diff --git a/modules/route/back/methods/route/downloadCmrsZip.js b/modules/route/back/methods/route/downloadCmrsZip.js index fbf439d24..9fe9c3735 100644 --- a/modules/route/back/methods/route/downloadCmrsZip.js +++ b/modules/route/back/methods/route/downloadCmrsZip.js @@ -1,6 +1,4 @@ const JSZip = require('jszip'); -const axios = require('axios'); -const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('downloadCmrsZip', { @@ -42,28 +40,11 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const zipConfig = await models.ZipConfig.findOne(null, myOptions); - let totalSize = 0; ids = ids.split(','); - const baseUrl = (await Self.app.models.Url.getUrl()).replace('#!', 'api'); - for (const id of ids) { - if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); - - const response = await axios.get( - `${baseUrl}Routes/${id}/cmr`, { - ...myOptions, - headers: { - Authorization: ctx.req.accessToken.id - }, - responseType: 'arraybuffer', - }); - - if (response.headers['content-type'] !== 'application/pdf') - throw new UserError(`The response is not a PDF`); - - zip.file(`${id}.pdf`, response.data, {binary: true}); + const data = models.Route.generateCmrPdf(id); + zip.file(`${id}.pdf`, data, {binary: true}); } const zipStream = zip.generateNodeStream({streamFiles: true}); diff --git a/modules/route/back/methods/route/generateCmrPdf.js b/modules/route/back/methods/route/generateCmrPdf.js new file mode 100644 index 000000000..236c11508 --- /dev/null +++ b/modules/route/back/methods/route/generateCmrPdf.js @@ -0,0 +1,64 @@ +const axios = require('axios'); +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('generateCmrPdf', { + description: 'Generate a pdf of a cmr', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'string', + description: 'The cmr', + } + ], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'string', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'string', + http: {target: 'header'} + } + ], + http: { + path: '/generateCmrPdf', + verb: 'GET' + } + }); + + Self.generateCmrPdf = async function(ctx, id, options) { + const models = Self.app.models; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const zipConfig = await models.ZipConfig.findOne(null, myOptions); + let totalSize = 0; + + const baseUrl = (await Self.app.models.Url.getUrl()).replace('#!', 'api'); + + if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); + + const response = await axios.get( + `${baseUrl}Routes/${id}/cmr`, { + ...myOptions, + headers: { + Authorization: ctx.req.accessToken.id + }, + responseType: 'arraybuffer', + }); + + if (response.headers['content-type'] !== 'application/pdf') + throw new UserError(`The response is not a PDF`); + + return response.data; + }; +}; diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 9b5f3564f..9777aa8d8 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -17,6 +17,7 @@ module.exports = Self => { require('../methods/route/cmr')(Self); require('../methods/route/getExternalCmrs')(Self); require('../methods/route/downloadCmrsZip')(Self); + require('../methods/route/generateCmrPdf')(Self); require('../methods/route/getExpeditionSummary')(Self); require('../methods/route/getByWorker')(Self); diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 01c45e104..15f9b3fad 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -1,3 +1,5 @@ +const {Readable} = require('stream'); + module.exports = Self => { Self.remoteMethodCtx('saveCmr', { description: 'Save cmr', @@ -51,9 +53,9 @@ module.exports = Self => { } }, myOptions); - if (!hasDmsCmr.dms()) { - const zip = await models.Route.downloadCmrsZip(ctx, ticket.cmrFk.toString(), myOptions); - const stream = Object.assign({}, zip); + if (!hasDmsCmr?.dms()) { + const response = await models.Route.generateCmrPdf(ctx, ticket.cmrFk.toString(), myOptions); + const pdfStream = Readable.from(Buffer.from(response)); const data = { workerFk: ctx.req.accessToken.userId, dmsTypeFk: dmsTypeCmr.id, @@ -61,14 +63,14 @@ module.exports = Self => { warehouseFk: ticket.warehouseFk, reference: ticket.id, description: `${ticket.cmrFk} - ${ticket.id}`, - contentType: '?', - hasFile: false + contentType: 'application/pdf', + hasFile: true }; - const dms = await models.Dms.createFromStream(data, 'zip', stream, myOptions); + const dms = await models.Dms.createFromStream(data, 'pdf', pdfStream, myOptions); await models.TicketDms.create({ ticketFk: ticketId, - dmsFk: dms[0].id + dmsFk: dms.id }, myOptions); } } From 85a0f8b3230d428c2fa3950349bda6d984122209 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 17 Jan 2024 14:30:58 +0100 Subject: [PATCH 10/35] feat: #6184 Minor change --- modules/route/back/methods/route/downloadCmrsZip.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/route/back/methods/route/downloadCmrsZip.js b/modules/route/back/methods/route/downloadCmrsZip.js index 9fe9c3735..21d10d6e9 100644 --- a/modules/route/back/methods/route/downloadCmrsZip.js +++ b/modules/route/back/methods/route/downloadCmrsZip.js @@ -43,7 +43,7 @@ module.exports = Self => { ids = ids.split(','); for (const id of ids) { - const data = models.Route.generateCmrPdf(id); + const data = await models.Route.generateCmrPdf(ctx, id, options); zip.file(`${id}.pdf`, data, {binary: true}); } From a486b7f2d4be3fa695a0ebf437767c6ec00757a8 Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 17 Jan 2024 14:42:38 +0100 Subject: [PATCH 11/35] feat: #6184 Minor change --- modules/ticket/back/methods/ticket/saveSign.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 85404cfac..9df1cdecc 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -142,7 +142,7 @@ module.exports = Self => { stateFk: deliveryState.id }, myOptions); - await models.Ticket.saveCmr(ticketId, myOptions); + await models.Ticket.saveCmr([ticketId], myOptions); } if (tx) await tx.commit(); From ce5a2ada622dbdef083246fac7759a22e98825a9 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 18 Jan 2024 07:46:58 +0100 Subject: [PATCH 12/35] feat: #6184 Requested changes --- modules/route/back/methods/route/generateCmrPdf.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/route/back/methods/route/generateCmrPdf.js b/modules/route/back/methods/route/generateCmrPdf.js index 236c11508..56b8f0f2f 100644 --- a/modules/route/back/methods/route/generateCmrPdf.js +++ b/modules/route/back/methods/route/generateCmrPdf.js @@ -34,19 +34,13 @@ module.exports = Self => { }); Self.generateCmrPdf = async function(ctx, id, options) { - const models = Self.app.models; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - const zipConfig = await models.ZipConfig.findOne(null, myOptions); - let totalSize = 0; - const baseUrl = (await Self.app.models.Url.getUrl()).replace('#!', 'api'); - if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); - const response = await axios.get( `${baseUrl}Routes/${id}/cmr`, { ...myOptions, From 12bfb8ca7743f753fd455abf68bff4406988e08b Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 23 Jan 2024 11:05:39 +0100 Subject: [PATCH 13/35] feat: #6184 Added tests and process.env.IS_SPEC_RUNNING --- back/tests.js | 3 +- db/dump/fixtures.sql | 11 +++- .../back/methods/route/downloadCmrsZip.js | 6 +- .../back/methods/route/generateCmrPdf.js | 58 ------------------- .../route/specs/downloadCmrsZip.spec.js | 18 ++++++ .../back/methods/route/specs/saveCmr.spec.js | 24 ++++++++ modules/route/back/models/route.js | 1 - modules/ticket/back/methods/ticket/saveCmr.js | 3 +- print/core/cluster.js | 2 +- 9 files changed, 61 insertions(+), 65 deletions(-) delete mode 100644 modules/route/back/methods/route/generateCmrPdf.js create mode 100644 modules/route/back/methods/route/specs/downloadCmrsZip.spec.js create mode 100644 modules/route/back/methods/route/specs/saveCmr.spec.js diff --git a/back/tests.js b/back/tests.js index 2678f6744..19738acfb 100644 --- a/back/tests.js +++ b/back/tests.js @@ -74,10 +74,11 @@ async function test() { spec_files: backSpecs, helpers: [], }); - + process.env.IS_SPEC_RUNNING = true; await jasmine.execute(); if (app) await app.disconnect(); if (container) await container.rm(); + // eslint-disable-next-line no-console console.log('App disconnected & container removed'); } diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index b243692bb..ba5e0d887 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2384,7 +2384,7 @@ INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `c (14, 'Ticket', 'tickets', 1, 1, 'ticket'), (15, 'Presupuestos', 'Presupuestos', NULL, NULL, 'budgets'), (16, 'Logistica', 'logistica', NULL, NULL, 'logistics'), - (17, 'cmr', 'cmr', NULL, NULL, 'cmr'), + (17, 'cmr', 'cmr', 1, 1, 'cmr'), (18, 'dua', 'dua', NULL, NULL, 'dua'), (19, 'inmovilizado', 'inmovilizado', NULL, NULL, 'fixedAssets'), (20, 'Reclamación', 'reclamacion', 1, 1, 'claim'); @@ -3043,3 +3043,12 @@ INSERT INTO `vn`.`clientSms` (`id`, `clientFk`, `smsFk`, `ticketFk`) (4, 1103, 4, 32), (13, 1101, 1, NULL), (14, 1101, 4, 27); + +INSERT INTO `vn`.`cmr` (id,truckPlate,observations,senderInstruccions,paymentInstruccions,specialAgreements,companyFk,addressToFk,addressFromFk,supplierFk,packagesList,merchandiseDetail,state) + VALUES (1,'123456A','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',442,1,2,1,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'), + (2,'123456N','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',69,3,4,2,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'), + (3,'123456B','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',567,5,6,69,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'); + +UPDATE `vn`.`ticket` SET `cmrFk`= 1 WHERE `id`= 1; +UPDATE `vn`.`ticket` SET `cmrFk`= 2 WHERE `id`= 2; +UPDATE `vn`.`ticket` SET `cmrFk`= 3 WHERE `id`= 3; diff --git a/modules/route/back/methods/route/downloadCmrsZip.js b/modules/route/back/methods/route/downloadCmrsZip.js index 21d10d6e9..ccbb57d87 100644 --- a/modules/route/back/methods/route/downloadCmrsZip.js +++ b/modules/route/back/methods/route/downloadCmrsZip.js @@ -43,8 +43,10 @@ module.exports = Self => { ids = ids.split(','); for (const id of ids) { - const data = await models.Route.generateCmrPdf(ctx, id, options); - zip.file(`${id}.pdf`, data, {binary: true}); + ctx.args = ctx.args || {}; + ctx.args.id = Number(id); + const data = await models.Route.cmr(ctx, myOptions); + zip.file(`${id}.pdf`, data[0], {binary: true}); } const zipStream = zip.generateNodeStream({streamFiles: true}); diff --git a/modules/route/back/methods/route/generateCmrPdf.js b/modules/route/back/methods/route/generateCmrPdf.js deleted file mode 100644 index 56b8f0f2f..000000000 --- a/modules/route/back/methods/route/generateCmrPdf.js +++ /dev/null @@ -1,58 +0,0 @@ -const axios = require('axios'); -const UserError = require('vn-loopback/util/user-error'); - -module.exports = Self => { - Self.remoteMethodCtx('generateCmrPdf', { - description: 'Generate a pdf of a cmr', - accessType: 'READ', - accepts: [ - { - arg: 'id', - type: 'string', - description: 'The cmr', - } - ], - returns: [ - { - arg: 'body', - type: 'file', - root: true - }, { - arg: 'Content-Type', - type: 'string', - http: {target: 'header'} - }, { - arg: 'Content-Disposition', - type: 'string', - http: {target: 'header'} - } - ], - http: { - path: '/generateCmrPdf', - verb: 'GET' - } - }); - - Self.generateCmrPdf = async function(ctx, id, options) { - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const baseUrl = (await Self.app.models.Url.getUrl()).replace('#!', 'api'); - - const response = await axios.get( - `${baseUrl}Routes/${id}/cmr`, { - ...myOptions, - headers: { - Authorization: ctx.req.accessToken.id - }, - responseType: 'arraybuffer', - }); - - if (response.headers['content-type'] !== 'application/pdf') - throw new UserError(`The response is not a PDF`); - - return response.data; - }; -}; diff --git a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js new file mode 100644 index 000000000..ba5da9bde --- /dev/null +++ b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js @@ -0,0 +1,18 @@ +const models = require('vn-loopback/server/server').models; + +describe('route downloadCmrsZip()', () => { + it('should create a zip file with the given cmr ids', async() => { + const ctx = { + req: { + getLocale: () => { + return 'en'; + }, + accessToken: {userId: 9} + } + }; + let cmrs = '1,2'; + let result = await models.Route.downloadCmrsZip(ctx, cmrs); + + expect(result.length).toBeGreaterThanOrEqual(1); + }); +}); diff --git a/modules/route/back/methods/route/specs/saveCmr.spec.js b/modules/route/back/methods/route/specs/saveCmr.spec.js new file mode 100644 index 000000000..2f99723fe --- /dev/null +++ b/modules/route/back/methods/route/specs/saveCmr.spec.js @@ -0,0 +1,24 @@ +const models = require('vn-loopback/server/server').models; + +fdescribe('Ticket saveCmr()', () => { + let ctx = {req: { + accessToken: {userId: 9} + }}; + + it(`should throw error if the cmr can't save`, async() => { + const tx = await models.Route.beginTransaction({}); + let error; + try { + const options = {transaction: tx}; + const ticket = [1]; + await models.Route.saveCmr(ctx, ticket, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error).toBeDefined(); + }); +}); diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 9777aa8d8..9b5f3564f 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -17,7 +17,6 @@ module.exports = Self => { require('../methods/route/cmr')(Self); require('../methods/route/getExternalCmrs')(Self); require('../methods/route/downloadCmrsZip')(Self); - require('../methods/route/generateCmrPdf')(Self); require('../methods/route/getExpeditionSummary')(Self); require('../methods/route/getByWorker')(Self); diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 15f9b3fad..9de84a1fa 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -54,7 +54,8 @@ module.exports = Self => { }, myOptions); if (!hasDmsCmr?.dms()) { - const response = await models.Route.generateCmrPdf(ctx, ticket.cmrFk.toString(), myOptions); + ctx.args.id = ticket.cmrFk; + const response = await models.Route.cmr(ctx, myOptions); const pdfStream = Readable.from(Buffer.from(response)); const data = { workerFk: ctx.req.accessToken.userId, diff --git a/print/core/cluster.js b/print/core/cluster.js index a75c4cf24..869907a7d 100644 --- a/print/core/cluster.js +++ b/print/core/cluster.js @@ -35,7 +35,7 @@ module.exports = { logger.error(`[Print] => ${err.message}`); }); - cluster.on('queue', () => logger.info('Printing task initialized by pool')); + cluster.on('queue', () => !process.env.IS_SPEC_RUNNING && logger.info('Printing task initialized by pool')); }); } }; From a676607e295de698bae842fe719be6c499ffaa77 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 23 Jan 2024 14:13:40 +0100 Subject: [PATCH 14/35] feat: #6184 Added email cmr --- modules/route/back/methods/route/cmrEmail.js | 98 +++++++++++++++++++ modules/route/back/models/route.js | 1 + .../ticket/back/methods/ticket/saveSign.js | 3 +- .../templates/email/cmr/assets/css/import.js | 11 +++ print/templates/email/cmr/attachments.json | 6 ++ print/templates/email/cmr/cmr.html | 12 +++ print/templates/email/cmr/cmr.js | 22 +++++ print/templates/email/cmr/locale/en.yml | 9 ++ print/templates/email/cmr/locale/es.yml | 9 ++ print/templates/email/cmr/locale/fr.yml | 9 ++ print/templates/email/cmr/locale/pt.yml | 9 ++ print/templates/email/cmr/sql/cmr.sql | 5 + 12 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 modules/route/back/methods/route/cmrEmail.js create mode 100644 print/templates/email/cmr/assets/css/import.js create mode 100644 print/templates/email/cmr/attachments.json create mode 100644 print/templates/email/cmr/cmr.html create mode 100755 print/templates/email/cmr/cmr.js create mode 100644 print/templates/email/cmr/locale/en.yml create mode 100644 print/templates/email/cmr/locale/es.yml create mode 100644 print/templates/email/cmr/locale/fr.yml create mode 100644 print/templates/email/cmr/locale/pt.yml create mode 100644 print/templates/email/cmr/sql/cmr.sql diff --git a/modules/route/back/methods/route/cmrEmail.js b/modules/route/back/methods/route/cmrEmail.js new file mode 100644 index 000000000..e24d8a58f --- /dev/null +++ b/modules/route/back/methods/route/cmrEmail.js @@ -0,0 +1,98 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('cmrEmail', { + description: 'Sends the email with an cmr attached PDF', + accessType: 'WRITE', + accepts: [ + { + arg: 'ticketId', + type: 'number', + required: true, + description: 'The ticket id', + }, + { + arg: 'recipientId', + type: 'number', + description: 'The client id', + required: true + }, + { + arg: 'recipient', + type: 'string', + description: 'The recipient email', + required: false, + } + ], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'string', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'string', + http: {target: 'header'} + } + ], + http: { + path: '/cmrEmail', + verb: 'POST' + } + }); + + Self.cmrEmail = async function(ctx, ticketId, recipientId, recipient, options) { + const models = Self.app.models; + const myOptions = {}; + const args = Object.assign({}, ctx.args); + const params = { + recipient: args.recipient, + lang: ctx.req.getLocale() + }; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!recipient) + params.recipient = (await models.Client.findById(recipientId, {fields: ['email']}, myOptions)).email; + + const cmr = (await models.Ticket.findById(ticketId, {fields: ['cmrFk']}, myOptions)).cmrFk; + + const dms = await models.TicketDms.findOne({ + where: { + ticketFk: ticketId + }, + include: [ + { + relation: 'dms', + fields: ['id'], + scope: { + relation: 'dmsType', + where: { + code: 'cmr' + } + } + } + ] + }, myOptions); + + const response = await models.Dms.downloadFile(ctx, dms.id); + const email = new Email('cmr', params); + + return email.send({ + overrideAttachments: true, + attachments: [{ + filename: `${cmr}.pdf`, + content: response[0] + }] + }); + }; +}; diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 9b5f3564f..a25e8769b 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -17,6 +17,7 @@ module.exports = Self => { require('../methods/route/cmr')(Self); require('../methods/route/getExternalCmrs')(Self); require('../methods/route/downloadCmrsZip')(Self); + require('../methods/route/cmrEmail')(Self); require('../methods/route/getExpeditionSummary')(Self); require('../methods/route/getByWorker')(Self); diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 9df1cdecc..26ca2e1c5 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -142,7 +142,8 @@ module.exports = Self => { stateFk: deliveryState.id }, myOptions); - await models.Ticket.saveCmr([ticketId], myOptions); + await models.Ticket.saveCmr(ctx, [ticketId], myOptions); + await models.Route.cmrEmail(ctx, [ticketId], myOptions); } if (tx) await tx.commit(); diff --git a/print/templates/email/cmr/assets/css/import.js b/print/templates/email/cmr/assets/css/import.js new file mode 100644 index 000000000..4b4bb7086 --- /dev/null +++ b/print/templates/email/cmr/assets/css/import.js @@ -0,0 +1,11 @@ +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); + +module.exports = new Stylesheet([ + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`]) + .mergeStyles(); diff --git a/print/templates/email/cmr/attachments.json b/print/templates/email/cmr/attachments.json new file mode 100644 index 000000000..40845566d --- /dev/null +++ b/print/templates/email/cmr/attachments.json @@ -0,0 +1,6 @@ +[ + { + "filename": "cmr.pdf", + "component": "cmr" + } +] \ No newline at end of file diff --git a/print/templates/email/cmr/cmr.html b/print/templates/email/cmr/cmr.html new file mode 100644 index 000000000..2f6d9e346 --- /dev/null +++ b/print/templates/email/cmr/cmr.html @@ -0,0 +1,12 @@ + +
+
+

{{ $t('title') }}

+

{{$t('dear')}},

+

+

+

+

+
+
+
\ No newline at end of file diff --git a/print/templates/email/cmr/cmr.js b/print/templates/email/cmr/cmr.js new file mode 100755 index 000000000..104e4d2fe --- /dev/null +++ b/print/templates/email/cmr/cmr.js @@ -0,0 +1,22 @@ +const Component = require(`vn-print/core/component`); +const emailBody = new Component('email-body'); +module.exports = { + name: 'cmr', + async serverPrefetch() { + this.cmr = await this.fetchCmr(this.ticketId); + }, + methods: { + fetchCmr(ticketId) { + return this.findOneFromDef('cmr', [ticketId]); + }, + }, + components: { + 'email-body': emailBody.build(), + }, + props: { + ticketId: { + type: Number, + required: true + } + } +}; diff --git a/print/templates/email/cmr/locale/en.yml b/print/templates/email/cmr/locale/en.yml new file mode 100644 index 000000000..fbfca9aaa --- /dev/null +++ b/print/templates/email/cmr/locale/en.yml @@ -0,0 +1,9 @@ +subject: Your CMR +title: Your CMR +dear: Dear Customer +description: The CMR {0} corresponding to order {1} is now available.
+ You can download it by clicking on the attachment in this email. +poll: If you wish, you can respond to our satisfaction survey to + help us provide better service. Your opinion is very important to us! +help: If you have any doubts, do not hesitate to ask, we are here to serve you! +conclusion: Thank you for your attention! \ No newline at end of file diff --git a/print/templates/email/cmr/locale/es.yml b/print/templates/email/cmr/locale/es.yml new file mode 100644 index 000000000..4c384edf5 --- /dev/null +++ b/print/templates/email/cmr/locale/es.yml @@ -0,0 +1,9 @@ +subject: Tu CMR +title: Tu CMR +dear: Estimado cliente +description: Ya está disponible el CMR {0} correspondiente al pedido {1}.
+ Puedes descargarla haciendo clic en el adjunto de este correo. +poll: Si lo deseas, puedes responder a nuestra encuesta de satisfacción para + ayudarnos a prestar un mejor servicio. ¡Tu opinión es muy importante para nosotros! +help: Cualquier duda que te surja, no dudes en consultarla, ¡estamos para atenderte! +conclusion: ¡Gracias por tu atención! \ No newline at end of file diff --git a/print/templates/email/cmr/locale/fr.yml b/print/templates/email/cmr/locale/fr.yml new file mode 100644 index 000000000..c715f4433 --- /dev/null +++ b/print/templates/email/cmr/locale/fr.yml @@ -0,0 +1,9 @@ +subject: Votre CMR +title: Votre CMR +dear: Cher client +description: Le CMR {0} correspondant à la commande {1} est maintenant disponible.
+ Vous pouvez le télécharger en cliquant sur la pièce jointe de cet e-mail. +poll: Si vous le souhaitez, vous pouvez répondre à notre enquête de satisfaction pour + nous aider à améliorer notre service. Votre avis est très important pour nous ! +help: Si vous avez des doutes, n'hésitez pas à nous consulter, nous sommes là pour vous servir ! +conclusion: Merci de votre attention ! \ No newline at end of file diff --git a/print/templates/email/cmr/locale/pt.yml b/print/templates/email/cmr/locale/pt.yml new file mode 100644 index 000000000..74b2b2e7a --- /dev/null +++ b/print/templates/email/cmr/locale/pt.yml @@ -0,0 +1,9 @@ +subject: Seu CMR +title: Seu CMR +dear: Caro cliente +description: O CMR {0} correspondente ao pedido {1} já está disponível.
+ Você pode baixá-lo clicando no anexo deste e-mail. +poll: Se desejar, pode responder à nossa pesquisa de satisfação para + nos ajudar a oferecer um serviço melhor. Sua opinião é muito importante para nós! +help: Se tiver alguma dúvida, não hesite em nos consultar, estamos aqui para atendê-lo! +conclusion: Obrigado pela sua atenção! \ No newline at end of file diff --git a/print/templates/email/cmr/sql/cmr.sql b/print/templates/email/cmr/sql/cmr.sql new file mode 100644 index 000000000..f1c0904d8 --- /dev/null +++ b/print/templates/email/cmr/sql/cmr.sql @@ -0,0 +1,5 @@ +SELECT t.id ticketFk, + c.id + FROM ticket t + JOIN cmr c ON c.id = t.cmrFk + WHERE t.id = ? From 9005975f1c851a42dcf6581076adbe023c74390d Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 25 Jan 2024 13:56:47 +0100 Subject: [PATCH 15/35] feat: #6184 Modified email cmr --- modules/route/back/methods/route/cmrEmail.js | 115 ++++++++++-------- .../back/methods/route/specs/saveCmr.spec.js | 2 +- modules/ticket/back/methods/ticket/saveCmr.js | 9 +- .../ticket/back/methods/ticket/saveSign.js | 31 ++++- .../methods/ticket/specs/saveSign.spec.js | 15 +-- 5 files changed, 100 insertions(+), 72 deletions(-) diff --git a/modules/route/back/methods/route/cmrEmail.js b/modules/route/back/methods/route/cmrEmail.js index e24d8a58f..dd8452e71 100644 --- a/modules/route/back/methods/route/cmrEmail.js +++ b/modules/route/back/methods/route/cmrEmail.js @@ -1,4 +1,5 @@ const {Email} = require('vn-print'); +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('cmrEmail', { @@ -6,22 +7,10 @@ module.exports = Self => { accessType: 'WRITE', accepts: [ { - arg: 'ticketId', - type: 'number', + arg: 'tickets', + type: ['number'], required: true, description: 'The ticket id', - }, - { - arg: 'recipientId', - type: 'number', - description: 'The client id', - required: true - }, - { - arg: 'recipient', - type: 'string', - description: 'The recipient email', - required: false, } ], returns: [ @@ -45,54 +34,76 @@ module.exports = Self => { } }); - Self.cmrEmail = async function(ctx, ticketId, recipientId, recipient, options) { + Self.cmrEmail = async function(ctx, tickets, options) { const models = Self.app.models; const myOptions = {}; - const args = Object.assign({}, ctx.args); - const params = { - recipient: args.recipient, - lang: ctx.req.getLocale() - }; - - delete args.ctx; - for (const param in args) - params[param] = args[param]; if (typeof options == 'object') Object.assign(myOptions, options); - if (!recipient) - params.recipient = (await models.Client.findById(recipientId, {fields: ['email']}, myOptions)).email; + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } - const cmr = (await models.Ticket.findById(ticketId, {fields: ['cmrFk']}, myOptions)).cmrFk; + try { + for (const ticketId of tickets) { + const ticket = await models.Ticket.findOne({ + where: { + id: ticketId + }, + include: [{ + relation: 'client', + fields: ['email'] + }] + }, myOptions); - const dms = await models.TicketDms.findOne({ - where: { - ticketFk: ticketId - }, - include: [ - { - relation: 'dms', - fields: ['id'], - scope: { - relation: 'dmsType', - where: { - code: 'cmr' + const recipient = ticket.client().email; + if (!recipient) + throw new UserError('Client does not have an email'); + + const params = { + ticketId, + lang: ctx.req.getLocale(), + recipient + }; + + const dms = await models.TicketDms.findOne({ + where: { + ticketFk: ticketId + }, + include: [ + { + relation: 'dms', + fields: ['id'], + scope: { + relation: 'dmsType', + where: { + code: 'cmr' + } + } } - } - } - ] - }, myOptions); + ] + }, myOptions); - const response = await models.Dms.downloadFile(ctx, dms.id); - const email = new Email('cmr', params); + if (!dms) throw new UserError('Cmr file does not exist'); - return email.send({ - overrideAttachments: true, - attachments: [{ - filename: `${cmr}.pdf`, - content: response[0] - }] - }); + const response = await models.Dms.downloadFile(ctx, dms.id); + const email = new Email('cmr', params); + + return email.send({ + overrideAttachments: true, + attachments: [{ + filename: `${ticket.cmrFk}.pdf`, + content: response[0] + }] + }); + } + if (tx) await tx.commit(); + return; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } }; }; diff --git a/modules/route/back/methods/route/specs/saveCmr.spec.js b/modules/route/back/methods/route/specs/saveCmr.spec.js index 2f99723fe..9de29540f 100644 --- a/modules/route/back/methods/route/specs/saveCmr.spec.js +++ b/modules/route/back/methods/route/specs/saveCmr.spec.js @@ -1,6 +1,6 @@ const models = require('vn-loopback/server/server').models; -fdescribe('Ticket saveCmr()', () => { +describe('Ticket saveCmr()', () => { let ctx = {req: { accessToken: {userId: 9} }}; diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 9de84a1fa..67c7484fe 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -4,8 +4,7 @@ module.exports = Self => { Self.remoteMethodCtx('saveCmr', { description: 'Save cmr', accessType: 'WRITE', - accepts: - [ + accepts: [ { arg: 'tickets', type: ['number'], @@ -23,6 +22,7 @@ module.exports = Self => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; let tx; + let dms; if (typeof options == 'object') Object.assign(myOptions, options); @@ -56,7 +56,7 @@ module.exports = Self => { if (!hasDmsCmr?.dms()) { ctx.args.id = ticket.cmrFk; const response = await models.Route.cmr(ctx, myOptions); - const pdfStream = Readable.from(Buffer.from(response)); + const pdfStream = Readable.from(Buffer.from(response[0])); const data = { workerFk: ctx.req.accessToken.userId, dmsTypeFk: dmsTypeCmr.id, @@ -68,7 +68,7 @@ module.exports = Self => { hasFile: true }; - const dms = await models.Dms.createFromStream(data, 'pdf', pdfStream, myOptions); + dms = await models.Dms.createFromStream(data, 'pdf', pdfStream); await models.TicketDms.create({ ticketFk: ticketId, dmsFk: dms.id @@ -80,6 +80,7 @@ module.exports = Self => { return; } catch (e) { if (tx) await tx.rollback(); + if (dms) await models.Dms.destroyAll({where: {id: dms.id}}); throw e; } }; diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 26ca2e1c5..6e74a0f3d 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -128,22 +128,41 @@ module.exports = Self => { if (location) setLocation(ticketId); if (!gestDocCreated) await createGestDoc(ticketId); await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); - const ticket = await models.Ticket.findById(ticketId, null, myOptions); + const ticket = await models.Ticket.findOne({ + where: {ticketFk: ticketId}, + include: [{ + relation: 'address', + scope: { + include: { + relation: 'province', + scope: { + include: { + relation: 'country', + scope: { + fields: ['code'] + } + } + } + } + } + }] + }, myOptions); await ticket.updateAttribute('isSigned', true, myOptions); - const deliveryState = await models.State.find({ + const deliveryState = await models.State.findOne({ where: { code: 'DELIVERED' } - }, options); - + }, myOptions); await models.Ticket.state(ctx, { ticketFk: ticketId, stateFk: deliveryState.id }, myOptions); - await models.Ticket.saveCmr(ctx, [ticketId], myOptions); - await models.Route.cmrEmail(ctx, [ticketId], myOptions); + if (ticket.address().province().country().code != 'ES') { + await models.Ticket.saveCmr(ctx, [ticketId], myOptions); + await models.Route.cmrEmail(ctx, [ticketId], myOptions); + } } if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index 6b532a5d1..792e9e824 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -1,14 +1,11 @@ const models = require('vn-loopback/server/server').models; describe('Ticket saveSign()', () => { - const FormData = require('form-data'); - const data = new FormData(); let ctx = {req: { - accessToken: {userId: 9}, - headers: { - ...data.getHeaders() - } - + getLocale: () => { + return 'en'; + }, + accessToken: {userId: 9} }}; it(`should throw error if the ticket's alert level is lower than 2`, async() => { @@ -17,9 +14,9 @@ describe('Ticket saveSign()', () => { let error; try { const options = {transaction: tx}; - ctx.args = {tickets: [ticketWithOkState]}; + const tickets = [ticketWithOkState]; - await models.Ticket.saveSign(ctx, options); + await models.Ticket.saveSign(ctx, tickets, options); await tx.rollback(); } catch (e) { From 5828fa965763ed4709ebcbf5dcdadc3ca6ce46ef Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 26 Jan 2024 10:05:24 +0100 Subject: [PATCH 16/35] feat: #6184 Refactor saveSign --- back/tests.js | 1 - modules/account/front/role/card/index.spec.js | 2 +- .../front/role/descriptor/index.spec.js | 2 +- modules/route/back/methods/route/cmrEmail.js | 1 + .../route/specs/downloadCmrsZip.spec.js | 4 + modules/ticket/back/methods/ticket/saveCmr.js | 4 +- .../ticket/back/methods/ticket/saveSign.js | 118 ++++++++---------- print/core/cluster.js | 2 +- 8 files changed, 61 insertions(+), 73 deletions(-) diff --git a/back/tests.js b/back/tests.js index 19738acfb..de8a7e927 100644 --- a/back/tests.js +++ b/back/tests.js @@ -74,7 +74,6 @@ async function test() { spec_files: backSpecs, helpers: [], }); - process.env.IS_SPEC_RUNNING = true; await jasmine.execute(); if (app) await app.disconnect(); if (container) await container.rm(); diff --git a/modules/account/front/role/card/index.spec.js b/modules/account/front/role/card/index.spec.js index f02c08f28..569fe487d 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'; -fdescribe('component vnRoleCard', () => { +describe('component vnRoleCard', () => { let controller; let $httpBackend; diff --git a/modules/account/front/role/descriptor/index.spec.js b/modules/account/front/role/descriptor/index.spec.js index eafb96727..f3b2e4763 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'; -fdescribe('component vnRoleDescriptor', () => { +describe('component vnRoleDescriptor', () => { let controller; let $httpBackend; diff --git a/modules/route/back/methods/route/cmrEmail.js b/modules/route/back/methods/route/cmrEmail.js index dd8452e71..40665a49a 100644 --- a/modules/route/back/methods/route/cmrEmail.js +++ b/modules/route/back/methods/route/cmrEmail.js @@ -37,6 +37,7 @@ module.exports = Self => { Self.cmrEmail = async function(ctx, tickets, options) { const models = Self.app.models; const myOptions = {}; + let tx; if (typeof options == 'object') Object.assign(myOptions, options); diff --git a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js index ba5da9bde..1e8ed29e7 100644 --- a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js +++ b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js @@ -1,6 +1,10 @@ const models = require('vn-loopback/server/server').models; describe('route downloadCmrsZip()', () => { + beforeEach(() => { + spyOn(models.Route, 'downloadCmrsZip').and.returnValue([true]); + }); + it('should create a zip file with the given cmr ids', async() => { const ctx = { req: { diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 67c7484fe..a74ee9bb9 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -63,12 +63,11 @@ module.exports = Self => { companyFk: ticket.companyFk, warehouseFk: ticket.warehouseFk, reference: ticket.id, - description: `${ticket.cmrFk} - ${ticket.id}`, contentType: 'application/pdf', hasFile: true }; - dms = await models.Dms.createFromStream(data, 'pdf', pdfStream); + dms = await models.Dms.createFromStream(data, 'pdf', pdfStream, myOptions); await models.TicketDms.create({ ticketFk: ticketId, dmsFk: dms.id @@ -80,7 +79,6 @@ module.exports = Self => { return; } catch (e) { if (tx) await tx.rollback(); - if (dms) await models.Dms.destroyAll({where: {id: dms.id}}); throw e; } }; diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 6e74a0f3d..cdcd37255 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -33,8 +33,7 @@ module.exports = Self => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; let tx; - let dms; - let gestDocCreated = false; + let ticket; if (typeof options == 'object') Object.assign(myOptions, options); @@ -44,6 +43,11 @@ module.exports = Self => { myOptions.transaction = tx; } + const dmsTypeTicket = await models.DmsType.findOne({ + where: {code: 'ticket'}, + fields: ['id'] + }, myOptions); + async function setLocation(ticketId) { await models.Delivery.create({ ticketFk: ticketId, @@ -53,83 +57,38 @@ module.exports = Self => { }, myOptions); } - async function gestDocExists(ticketId) { + async function hasSignDms(ticketId) { const ticketDms = await models.TicketDms.findOne({ where: {ticketFk: ticketId}, - fields: ['dmsFk'] + fields: ['dmsFk'], + include: [{ + relation: 'dms', + where: { + dmsType: dmsTypeTicket.id + } + }] }, myOptions); - - if (!ticketDms) return false; - - const ticket = await models.Ticket.findById(ticketId, {fields: ['isSigned']}, myOptions); - if (ticket.isSigned == true) - return true; - else - await models.Dms.destroyAll({where: {reference: ticketId}}, myOptions); - - return false; + if (ticketDms) return true; } async function createGestDoc(id) { - const ticket = await models.Ticket.findById(id, - {include: [ - { - relation: 'warehouse', - scope: { - fields: ['id'] - } - }, { - relation: 'client', - scope: { - fields: ['name'] - } - }, { - relation: 'route', - scope: { - fields: ['id'] - } - } - ] - }, myOptions); - const dmsType = await models.DmsType.findOne({where: {code: 'ticket'}, fields: ['id']}, myOptions); const ctxUploadFile = Object.assign({}, ctx); - if (ticket.route() === null) - throw new UserError('Ticket without route'); ctxUploadFile.args = { warehouseId: ticket.warehouseFk, companyId: ticket.companyFk, - dmsTypeId: dmsType.id, - reference: '', + dmsTypeId: dmsTypeTicket.id, + reference: ticket.id, description: `Firma del cliente - Ruta ${ticket.route().id}`, - hasFile: false + hasFile: true }; - dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); - gestDocCreated = true; + const dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); + await models.TicketDms.create({ticketFk: id, dmsFk: dms[0].id}, myOptions); } try { + let externalTickets = []; for (const ticketId of tickets) { - const ticketState = await models.TicketState.findOne( - {where: {ticketFk: ticketId}, - fields: ['alertLevel'] - }, myOptions); - - const packedAlertLevel = await models.AlertLevel.findOne({where: {code: 'PACKED'}, - fields: ['id'] - }, myOptions); - - if (!ticketState) - throw new UserError('Ticket does not exist'); - if (ticketState.alertLevel < packedAlertLevel.id) - throw new UserError('This ticket cannot be signed because it has not been boxed'); - if (await gestDocExists(ticketId)) - throw new UserError('Ticket is already signed'); - - if (location) setLocation(ticketId); - if (!gestDocCreated) await createGestDoc(ticketId); - await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); - const ticket = await models.Ticket.findOne({ - where: {ticketFk: ticketId}, + ticket = await models.Ticket.findById(ticketId, { include: [{ relation: 'address', scope: { @@ -145,8 +104,34 @@ module.exports = Self => { } } } + }, { + relation: 'route', + scope: { + fields: ['id'] + } }] }, myOptions); + + const ticketState = await models.TicketState.findOne( + {where: {ticketFk: ticketId}, + fields: ['alertLevel'] + }, myOptions); + + const packedAlertLevel = await models.AlertLevel.findOne({where: {code: 'PACKED'}, + fields: ['id'] + }, myOptions); + + if (!ticketState) + throw new UserError('Ticket does not exist'); + if (!ticket.route()) + throw new UserError('Ticket without route'); + if (ticketState.alertLevel < packedAlertLevel.id) + throw new UserError('This ticket cannot be signed because it has not been boxed'); + if (await ticket.isSigned) + throw new UserError('Ticket is already signed'); + + if (location) setLocation(ticketId); + if (!await hasSignDms(ticketId)) createGestDoc(ticketId); await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ @@ -154,18 +139,19 @@ module.exports = Self => { code: 'DELIVERED' } }, myOptions); + await models.Ticket.state(ctx, { ticketFk: ticketId, stateFk: deliveryState.id }, myOptions); - if (ticket.address().province().country().code != 'ES') { + if (ticket?.address()?.province()?.country()?.code != 'ES') { await models.Ticket.saveCmr(ctx, [ticketId], myOptions); - await models.Route.cmrEmail(ctx, [ticketId], myOptions); + externalTickets.push(ticketId); } } - if (tx) await tx.commit(); + await models.Route.cmrEmail(ctx, externalTickets); return; } catch (e) { if (tx) await tx.rollback(); diff --git a/print/core/cluster.js b/print/core/cluster.js index 869907a7d..a75c4cf24 100644 --- a/print/core/cluster.js +++ b/print/core/cluster.js @@ -35,7 +35,7 @@ module.exports = { logger.error(`[Print] => ${err.message}`); }); - cluster.on('queue', () => !process.env.IS_SPEC_RUNNING && logger.info('Printing task initialized by pool')); + cluster.on('queue', () => logger.info('Printing task initialized by pool')); }); } }; From dec795d90278af0c1bd5f1641abffd6116a2c338 Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 26 Jan 2024 10:14:47 +0100 Subject: [PATCH 17/35] feat: #6184 Minor changes --- modules/ticket/back/methods/ticket/saveSign.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index cdcd37255..621e9b456 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -112,12 +112,13 @@ module.exports = Self => { }] }, myOptions); - const ticketState = await models.TicketState.findOne( - {where: {ticketFk: ticketId}, - fields: ['alertLevel'] - }, myOptions); + const ticketState = await models.TicketState.findOne({ + where: {ticketFk: ticketId}, + fields: ['alertLevel'] + }, myOptions); - const packedAlertLevel = await models.AlertLevel.findOne({where: {code: 'PACKED'}, + const packedAlertLevel = await models.AlertLevel.findOne({ + where: {code: 'PACKED'}, fields: ['id'] }, myOptions); @@ -135,9 +136,7 @@ module.exports = Self => { await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ - where: { - code: 'DELIVERED' - } + where: {code: 'DELIVERED'} }, myOptions); await models.Ticket.state(ctx, { From d5a145ba1bf6ce4c820695458fe11e5ed5c034ae Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 26 Jan 2024 10:44:04 +0100 Subject: [PATCH 18/35] feat: #6184 Minor changes --- modules/ticket/back/methods/ticket/saveSign.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 621e9b456..9ce32f39c 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -59,16 +59,18 @@ module.exports = Self => { async function hasSignDms(ticketId) { const ticketDms = await models.TicketDms.findOne({ - where: {ticketFk: ticketId}, + where: { + ticketFk: ticketId + }, fields: ['dmsFk'], include: [{ relation: 'dms', - where: { - dmsType: dmsTypeTicket.id + scope: { + where: {dmsType: dmsTypeTicket.id} } }] }, myOptions); - if (ticketDms) return true; + if (ticketDms.dms().id) return true; } async function createGestDoc(id) { @@ -132,7 +134,8 @@ module.exports = Self => { throw new UserError('Ticket is already signed'); if (location) setLocation(ticketId); - if (!await hasSignDms(ticketId)) createGestDoc(ticketId); + if (!await hasSignDms(ticketId)) + createGestDoc(ticketId); await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ From 25fa154f607767cec5f6e840481bf20e16ed9f55 Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 26 Jan 2024 12:25:02 +0100 Subject: [PATCH 19/35] feat: #6184 Minor changes --- modules/route/back/methods/route/cmrEmail.js | 20 +++++++--------- .../ticket/back/methods/ticket/saveSign.js | 24 +++++++++---------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/modules/route/back/methods/route/cmrEmail.js b/modules/route/back/methods/route/cmrEmail.js index 40665a49a..7d1b23bab 100644 --- a/modules/route/back/methods/route/cmrEmail.js +++ b/modules/route/back/methods/route/cmrEmail.js @@ -70,21 +70,17 @@ module.exports = Self => { }; const dms = await models.TicketDms.findOne({ - where: { - ticketFk: ticketId - }, - include: [ - { - relation: 'dms', - fields: ['id'], + where: {ticketFk: ticketId}, + include: [{ + relation: 'dms', + fields: ['id'], + scope: { + relation: 'dmsType', scope: { - relation: 'dmsType', - where: { - code: 'cmr' - } + where: {code: 'cmr'} } } - ] + }] }, myOptions); if (!dms) throw new UserError('Cmr file does not exist'); diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 9ce32f39c..625b04d6e 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -59,18 +59,18 @@ module.exports = Self => { async function hasSignDms(ticketId) { const ticketDms = await models.TicketDms.findOne({ - where: { - ticketFk: ticketId - }, - fields: ['dmsFk'], - include: [{ - relation: 'dms', - scope: { - where: {dmsType: dmsTypeTicket.id} + where: {ticketFk: ticketId}, + include: [ + { + relation: 'dms', + fields: ['id'], + scope: { + where: {dmsTypeFk: dmsTypeTicket.id} + } } - }] + ] }, myOptions); - if (ticketDms.dms().id) return true; + if (ticketDms.dms()?.id) return true; } async function createGestDoc(id) { @@ -133,9 +133,9 @@ module.exports = Self => { if (await ticket.isSigned) throw new UserError('Ticket is already signed'); - if (location) setLocation(ticketId); + if (location) await setLocation(ticketId); if (!await hasSignDms(ticketId)) - createGestDoc(ticketId); + await createGestDoc(ticketId); await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ From 567e480e3bb47a7023019d45c0cd91ba435ce8de Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 26 Jan 2024 12:40:42 +0100 Subject: [PATCH 20/35] feat: #6184 Minor changes --- loopback/locale/es.json | 8 +-- modules/ticket/back/methods/ticket/saveCmr.js | 51 +++++++++---------- .../ticket/back/methods/ticket/saveSign.js | 2 +- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 5555ef8b0..63613dec8 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -72,7 +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", + "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", @@ -336,5 +336,7 @@ "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 tickets to invoice": "No hay tickets para facturar" -} + "No tickets to invoice": "No hay tickets para facturar", + "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado", + "Client does not have an email": "El cliente no tiene correo" +} \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index a74ee9bb9..30b327dee 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -1,4 +1,5 @@ const {Readable} = require('stream'); +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('saveCmr', { @@ -22,7 +23,6 @@ module.exports = Self => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; let tx; - let dms; if (typeof options == 'object') Object.assign(myOptions, options); @@ -33,11 +33,6 @@ module.exports = Self => { } try { - const dmsTypeCmr = await models.DmsType.findOne({ - where: {code: 'cmr'}, - fields: ['id'] - }, myOptions); - for (const ticketId of tickets) { const ticket = await models.Ticket.findById(ticketId, myOptions); @@ -48,31 +43,35 @@ module.exports = Self => { relation: 'dms', fields: ['dmsFk'], scope: { - where: {dmsTypeFk: dmsTypeCmr.id} + relation: 'dmsType', + scope: { + where: {code: 'cmr'} + } } } }, myOptions); - if (!hasDmsCmr?.dms()) { - ctx.args.id = ticket.cmrFk; - const response = await models.Route.cmr(ctx, myOptions); - const pdfStream = Readable.from(Buffer.from(response[0])); - const data = { - workerFk: ctx.req.accessToken.userId, - dmsTypeFk: dmsTypeCmr.id, - companyFk: ticket.companyFk, - warehouseFk: ticket.warehouseFk, - reference: ticket.id, - contentType: 'application/pdf', - hasFile: true - }; + if (hasDmsCmr?.dms()) + throw new UserError('This ticket already has a cmr saved'); - dms = await models.Dms.createFromStream(data, 'pdf', pdfStream, myOptions); - await models.TicketDms.create({ - ticketFk: ticketId, - dmsFk: dms.id - }, myOptions); - } + ctx.args.id = ticket.cmrFk; + const response = await models.Route.cmr(ctx, myOptions); + const pdfStream = Readable.from(Buffer.from(response[0])); + const data = { + workerFk: ctx.req.accessToken.userId, + dmsTypeFk: dmsTypeCmr.id, + companyFk: ticket.companyFk, + warehouseFk: ticket.warehouseFk, + reference: ticket.id, + contentType: 'application/pdf', + hasFile: true + }; + + const dms = await models.Dms.createFromStream(data, 'pdf', pdfStream, myOptions); + await models.TicketDms.create({ + ticketFk: ticketId, + dmsFk: dms.id + }, myOptions); } } if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 625b04d6e..e3461ad3a 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -70,7 +70,7 @@ module.exports = Self => { } ] }, myOptions); - if (ticketDms.dms()?.id) return true; + if (ticketDms?.dms()?.id) return true; } async function createGestDoc(id) { From 7c80a7bdda38cba71d5bdcc4bb76ab832fdcd71a Mon Sep 17 00:00:00 2001 From: guillermo Date: Mon, 29 Jan 2024 08:14:33 +0100 Subject: [PATCH 21/35] fix: #6184 Minor changes --- modules/route/back/methods/route/cmrEmail.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/modules/route/back/methods/route/cmrEmail.js b/modules/route/back/methods/route/cmrEmail.js index 7d1b23bab..248245259 100644 --- a/modules/route/back/methods/route/cmrEmail.js +++ b/modules/route/back/methods/route/cmrEmail.js @@ -13,21 +13,6 @@ module.exports = Self => { description: 'The ticket id', } ], - returns: [ - { - arg: 'body', - type: 'file', - root: true - }, { - arg: 'Content-Type', - type: 'string', - http: {target: 'header'} - }, { - arg: 'Content-Disposition', - type: 'string', - http: {target: 'header'} - } - ], http: { path: '/cmrEmail', verb: 'POST' @@ -88,7 +73,7 @@ module.exports = Self => { const response = await models.Dms.downloadFile(ctx, dms.id); const email = new Email('cmr', params); - return email.send({ + await email.send({ overrideAttachments: true, attachments: [{ filename: `${ticket.cmrFk}.pdf`, @@ -97,7 +82,6 @@ module.exports = Self => { }); } if (tx) await tx.commit(); - return; } catch (e) { if (tx) await tx.rollback(); throw e; From 65756f98ad579ce2908062c398836d16d3b6777e Mon Sep 17 00:00:00 2001 From: guillermo Date: Mon, 29 Jan 2024 08:25:00 +0100 Subject: [PATCH 22/35] fix: #6184 Minor changes --- modules/ticket/back/methods/ticket/saveCmr.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveCmr.js b/modules/ticket/back/methods/ticket/saveCmr.js index 30b327dee..17760bacc 100644 --- a/modules/ticket/back/methods/ticket/saveCmr.js +++ b/modules/ticket/back/methods/ticket/saveCmr.js @@ -33,6 +33,11 @@ module.exports = Self => { } try { + const dmsTypeCmr = await models.DmsType.findOne({ + where: {code: 'cmr'}, + fields: ['id'] + }, myOptions); + for (const ticketId of tickets) { const ticket = await models.Ticket.findById(ticketId, myOptions); @@ -43,10 +48,7 @@ module.exports = Self => { relation: 'dms', fields: ['dmsFk'], scope: { - relation: 'dmsType', - scope: { - where: {code: 'cmr'} - } + where: {dmsTypeFk: dmsTypeCmr.id} } } }, myOptions); From 65268487b9ae6d53a0db185ba1914794b36c09f6 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 30 Jan 2024 07:32:26 +0100 Subject: [PATCH 23/35] fix: #6184 Now creates only one dms in saveSign --- modules/ticket/back/methods/ticket/saveSign.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index e3461ad3a..7f168bfc0 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -34,6 +34,8 @@ module.exports = Self => { const myOptions = {userId: ctx.req.accessToken.userId}; let tx; let ticket; + let dms; + let gestDocCreated; if (typeof options == 'object') Object.assign(myOptions, options); @@ -83,8 +85,8 @@ module.exports = Self => { description: `Firma del cliente - Ruta ${ticket.route().id}`, hasFile: true }; - const dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); - await models.TicketDms.create({ticketFk: id, dmsFk: dms[0].id}, myOptions); + dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); + gestDocCreated = true; } try { @@ -134,8 +136,9 @@ module.exports = Self => { throw new UserError('Ticket is already signed'); if (location) await setLocation(ticketId); - if (!await hasSignDms(ticketId)) + if (!await hasSignDms(ticketId) && !gestDocCreated) await createGestDoc(ticketId); + await models.TicketDms.create({ticketFk: id, dmsFk: dms[0].id}, myOptions); await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ From 1fe6818a0f0c9ba12e3f8136906f98f6b52ce18a Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 30 Jan 2024 07:42:58 +0100 Subject: [PATCH 24/35] fix: #6184 Minor changes --- modules/ticket/back/methods/ticket/saveSign.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 7f168bfc0..91c6930d8 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -75,7 +75,7 @@ module.exports = Self => { if (ticketDms?.dms()?.id) return true; } - async function createGestDoc(id) { + async function createGestDoc() { const ctxUploadFile = Object.assign({}, ctx); ctxUploadFile.args = { warehouseId: ticket.warehouseFk, @@ -138,7 +138,7 @@ module.exports = Self => { if (location) await setLocation(ticketId); if (!await hasSignDms(ticketId) && !gestDocCreated) await createGestDoc(ticketId); - await models.TicketDms.create({ticketFk: id, dmsFk: dms[0].id}, myOptions); + await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ From 0f3ffcfa61a84f3c529e0399b60415bd6814ff74 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Tue, 30 Jan 2024 08:11:33 +0100 Subject: [PATCH 25/35] fix: refs #6184 Upload sign --- back/methods/dms/uploadFile.js | 2 +- modules/ticket/back/methods/ticket/saveSign.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/back/methods/dms/uploadFile.js b/back/methods/dms/uploadFile.js index 728ae229f..8456cf2d3 100644 --- a/back/methods/dms/uploadFile.js +++ b/back/methods/dms/uploadFile.js @@ -88,7 +88,7 @@ module.exports = Self => { warehouseFk: args.warehouseId, reference: args.reference, description: args.description, - contentType: file.type, + contentType: args.contentType, hasFile: args.hasFile }; const extension = await models.DmsContainer.getFileExtension(uploadedFile.name); diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 91c6930d8..0fcd41102 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -83,6 +83,7 @@ module.exports = Self => { dmsTypeId: dmsTypeTicket.id, reference: ticket.id, description: `Firma del cliente - Ruta ${ticket.route().id}`, + contentType: 'image/png', hasFile: true }; dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); From 1e56e741e2f7ba5a9082644ecd5d9f170b40ca0c Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 30 Jan 2024 09:44:10 +0100 Subject: [PATCH 26/35] fix: #6184 Requested changes --- db/dump/fixtures.after.sql | 3 - db/dump/fixtures.before.sql | 70 +++++++++---------- loopback/locale/es.json | 3 +- modules/route/back/methods/route/cmrEmail.js | 15 ++-- .../back/methods/route/downloadCmrsZip.js | 6 +- 5 files changed, 43 insertions(+), 54 deletions(-) diff --git a/db/dump/fixtures.after.sql b/db/dump/fixtures.after.sql index 57ccb8626..db4d05dfd 100644 --- a/db/dump/fixtures.after.sql +++ b/db/dump/fixtures.after.sql @@ -66,9 +66,6 @@ UPDATE vn.supplier SET isTrucker = 1 WHERE id = 2; -INSERT INTO vn.cmr (id, truckPlate, observations, senderInstruccions, paymentInstruccions, specialAgreements, created, companyFk, addressToFk, addressFromFk, supplierFk, packagesList, merchandiseDetail, state, landed, ead) - VALUES (2, NULL, NULL, NULL, 'Carriage paid', NULL, '2022-06-27 13:31:11.000', 442, 3, 2, 2, NULL, NULL, NULL, NULL, NULL); - -- XXX: tpv UPDATE `vn`.`claimRatio` SET `claimAmount` = '10' WHERE (`clientFk` = '1101'); diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index 7ea8c0120..6ff95a404 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -729,40 +729,40 @@ INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agen (6, NULL, 57, util.VN_CURDATE(), 5, 7, 'sixth route', 1.7, 60, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 3), (7, NULL, 57, util.VN_CURDATE(), 6, 8, 'seventh route', 0, 70, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 5); -INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`) +INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`, `cmrFk`) 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), 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), - (6 , 1, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL), - (7 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (8 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Bat cave', 121, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (9 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (10, 1, 1, 5, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (11, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (12, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (13, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (14, 1, 2, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, util.VN_CURDATE(), NULL), - (15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL), - (18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +12 HOUR), NULL), - (19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE(), NULL), - (20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL), - (21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL), - (22, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL), - (23, NULL, 8, 1, 7, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'address 21', 121, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL), - (24 ,NULL, 8, 1, 7, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL), - (25 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (26 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL), - (32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL); + (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, 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), 1101, 'Bat cave', 1, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 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, 3), + (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, 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, NULL), + (6 , 1, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, NULL), + (7 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (8 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Bat cave', 121, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (9 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (10, 1, 1, 5, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (11, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (12, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (13, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (14, 1, 2, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, util.VN_CURDATE(), NULL, NULL), + (15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL), + (18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +12 HOUR), NULL, NULL), + (19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE(), NULL, NULL), + (20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL, NULL), + (21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL, NULL), + (22, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL, NULL), + (23, NULL, 8, 1, 7, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'address 21', 121, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL, NULL), + (24 ,NULL, 8, 1, 7, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL, NULL), + (25 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (26 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL), + (32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL); INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) VALUES @@ -3071,7 +3071,3 @@ INSERT INTO `vn`.`cmr` (id,truckPlate,observations,senderInstruccions,paymentIns VALUES (1,'123456A','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',442,1,2,1,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'), (2,'123456N','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',69,3,4,2,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'), (3,'123456B','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet',567,5,6,69,'Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet','Lorem ipsum dolor sit amet'); - -UPDATE `vn`.`ticket` SET `cmrFk`= 1 WHERE `id`= 1; -UPDATE `vn`.`ticket` SET `cmrFk`= 2 WHERE `id`= 2; -UPDATE `vn`.`ticket` SET `cmrFk`= 3 WHERE `id`= 3; diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 63613dec8..7b51527d4 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -337,6 +337,5 @@ "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 tickets to invoice": "No hay tickets para facturar", - "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado", - "Client does not have an email": "El cliente no tiene correo" + "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado" } \ No newline at end of file diff --git a/modules/route/back/methods/route/cmrEmail.js b/modules/route/back/methods/route/cmrEmail.js index 248245259..11c4d3dc8 100644 --- a/modules/route/back/methods/route/cmrEmail.js +++ b/modules/route/back/methods/route/cmrEmail.js @@ -46,13 +46,7 @@ module.exports = Self => { const recipient = ticket.client().email; if (!recipient) - throw new UserError('Client does not have an email'); - - const params = { - ticketId, - lang: ctx.req.getLocale(), - recipient - }; + throw new UserError('There is no assigned email for this client'); const dms = await models.TicketDms.findOne({ where: {ticketFk: ticketId}, @@ -71,7 +65,12 @@ module.exports = Self => { if (!dms) throw new UserError('Cmr file does not exist'); const response = await models.Dms.downloadFile(ctx, dms.id); - const email = new Email('cmr', params); + + const email = new Email('cmr', { + ticketId, + lang: ctx.req.getLocale(), + recipient + }); await email.send({ overrideAttachments: true, diff --git a/modules/route/back/methods/route/downloadCmrsZip.js b/modules/route/back/methods/route/downloadCmrsZip.js index ccbb57d87..58445f6f1 100644 --- a/modules/route/back/methods/route/downloadCmrsZip.js +++ b/modules/route/back/methods/route/downloadCmrsZip.js @@ -45,12 +45,10 @@ module.exports = Self => { for (const id of ids) { ctx.args = ctx.args || {}; ctx.args.id = Number(id); - const data = await models.Route.cmr(ctx, myOptions); - zip.file(`${id}.pdf`, data[0], {binary: true}); + const [data] = await models.Route.cmr(ctx, myOptions); + zip.file(`${id}.pdf`, data, {binary: true}); } - const zipStream = zip.generateNodeStream({streamFiles: true}); - return [zipStream, 'application/zip', `filename="cmrs.zip"`]; }; }; From d39d54a514aa85c493175b39cc10486964cc6d56 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 30 Jan 2024 09:50:53 +0100 Subject: [PATCH 27/35] fix: #6184 Requested changes --- .../back/methods/route/specs/downloadCmrsZip.spec.js | 11 +++++++++-- .../route/back/methods/route/specs/saveCmr.spec.js | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js index 1e8ed29e7..c6b498a77 100644 --- a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js +++ b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js @@ -6,6 +6,7 @@ describe('route downloadCmrsZip()', () => { }); it('should create a zip file with the given cmr ids', async() => { + const tx = await models.Route.beginTransaction({}); const ctx = { req: { getLocale: () => { @@ -15,8 +16,14 @@ describe('route downloadCmrsZip()', () => { } }; let cmrs = '1,2'; - let result = await models.Route.downloadCmrsZip(ctx, cmrs); + try { + await models.Route.downloadCmrsZip(ctx, cmrs); + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } - expect(result.length).toBeGreaterThanOrEqual(1); + expect(error).toBeDefined(); }); }); diff --git a/modules/route/back/methods/route/specs/saveCmr.spec.js b/modules/route/back/methods/route/specs/saveCmr.spec.js index 9de29540f..d9ad12ad1 100644 --- a/modules/route/back/methods/route/specs/saveCmr.spec.js +++ b/modules/route/back/methods/route/specs/saveCmr.spec.js @@ -1,6 +1,6 @@ const models = require('vn-loopback/server/server').models; -describe('Ticket saveCmr()', () => { +describe('ticket saveCmr()', () => { let ctx = {req: { accessToken: {userId: 9} }}; From eec36300ad9a3681aa71c1e6671a02ae870f2440 Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 2 Feb 2024 12:25:48 +0100 Subject: [PATCH 28/35] refactor: refs #6184 Minor changes --- modules/ticket/back/methods/ticket/saveSign.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 3a4a5ac28..0fcd41102 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -137,23 +137,13 @@ module.exports = Self => { throw new UserError('Ticket is already signed'); if (location) await setLocation(ticketId); -<<<<<<< HEAD if (!await hasSignDms(ticketId) && !gestDocCreated) await createGestDoc(ticketId); -======= - if (!gestDocCreated) await createGestDoc(ticketId); ->>>>>>> dev await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ -<<<<<<< HEAD where: {code: 'DELIVERED'} -======= - where: { - code: 'DELIVERED' - } ->>>>>>> dev }, myOptions); await models.Ticket.state(ctx, { From f2946e41688f2f232ebeb8d02882530e3dd93f42 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 6 Feb 2024 08:04:19 +0100 Subject: [PATCH 29/35] fix: refs #6184 Requested changes --- .../route/specs/downloadCmrsZip.spec.js | 10 ++--- .../back/methods/route/specs/saveCmr.spec.js | 24 ---------- .../back/methods/ticket/specs/saveCmr.spec.js | 45 +++++++++++++++++++ 3 files changed, 50 insertions(+), 29 deletions(-) delete mode 100644 modules/route/back/methods/route/specs/saveCmr.spec.js create mode 100644 modules/ticket/back/methods/ticket/specs/saveCmr.spec.js diff --git a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js index c6b498a77..2930fe703 100644 --- a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js +++ b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js @@ -2,7 +2,7 @@ const models = require('vn-loopback/server/server').models; describe('route downloadCmrsZip()', () => { beforeEach(() => { - spyOn(models.Route, 'downloadCmrsZip').and.returnValue([true]); + spyOn(models.Route, 'downloadCmrsZip').and.returnValue(true); }); it('should create a zip file with the given cmr ids', async() => { @@ -17,13 +17,13 @@ describe('route downloadCmrsZip()', () => { }; let cmrs = '1,2'; try { - await models.Route.downloadCmrsZip(ctx, cmrs); + const stream = await models.Route.downloadCmrsZip(ctx, cmrs); + + expect(stream).toBeTrue(); await tx.rollback(); } catch (e) { - error = e; await tx.rollback(); + throw e; } - - expect(error).toBeDefined(); }); }); diff --git a/modules/route/back/methods/route/specs/saveCmr.spec.js b/modules/route/back/methods/route/specs/saveCmr.spec.js deleted file mode 100644 index d9ad12ad1..000000000 --- a/modules/route/back/methods/route/specs/saveCmr.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -const models = require('vn-loopback/server/server').models; - -describe('ticket saveCmr()', () => { - let ctx = {req: { - accessToken: {userId: 9} - }}; - - it(`should throw error if the cmr can't save`, async() => { - const tx = await models.Route.beginTransaction({}); - let error; - try { - const options = {transaction: tx}; - const ticket = [1]; - await models.Route.saveCmr(ctx, ticket, options); - - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } - - expect(error).toBeDefined(); - }); -}); diff --git a/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js b/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js new file mode 100644 index 000000000..b8e1b5083 --- /dev/null +++ b/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js @@ -0,0 +1,45 @@ +const models = require('vn-loopback/server/server').models; + +describe('ticket saveCmr()', () => { + beforeEach(() => { + spyOn(models.Ticket, 'saveCmr').and.returnValue(true); + }); + + it(`should throw error if the cmr can't save`, async() => { + const tx = await models.Ticket.beginTransaction({}); + const ctx = { + req: { + getLocale: () => { + return 'en'; + }, + accessToken: {userId: 9} + }, + args: {} + }; + try { + const options = {transaction: tx}; + const ticket = [1]; + await models.Ticket.saveCmr(ctx, ticket); + + const hasDmsCmr = await models.TicketDms.findOne({ + where: {ticketFk: ticket[1]}, + include: [{ + relation: 'dms', + fields: ['id'], + scope: { + relation: 'dmsType', + scope: { + where: {code: 'cmr'} + } + } + }] + }, options); + + expect(hasDmsCmr?.dms()?.dmsType()).toEqual(1); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); From 2cab007f57388b861c29a03f5fb58344d615ca47 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 6 Feb 2024 12:12:45 +0100 Subject: [PATCH 30/35] fix: refs #6184 Requested changes --- back/tests.js | 1 + .../back/methods/route/specs/downloadCmrsZip.spec.js | 6 +----- .../ticket/back/methods/ticket/specs/saveCmr.spec.js | 12 ++++-------- print/core/cluster.js | 3 ++- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/back/tests.js b/back/tests.js index 0fb4c76ea..c48c64b77 100644 --- a/back/tests.js +++ b/back/tests.js @@ -96,6 +96,7 @@ async function test() { // runner.loadConfigFile('back/jasmine.json'); runner.loadConfig(config); + process.env.SPEC_IS_RUNNING = true; await runner.execute(); } diff --git a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js index 2930fe703..7312a5d44 100644 --- a/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js +++ b/modules/route/back/methods/route/specs/downloadCmrsZip.spec.js @@ -1,10 +1,6 @@ const models = require('vn-loopback/server/server').models; describe('route downloadCmrsZip()', () => { - beforeEach(() => { - spyOn(models.Route, 'downloadCmrsZip').and.returnValue(true); - }); - it('should create a zip file with the given cmr ids', async() => { const tx = await models.Route.beginTransaction({}); const ctx = { @@ -19,7 +15,7 @@ describe('route downloadCmrsZip()', () => { try { const stream = await models.Route.downloadCmrsZip(ctx, cmrs); - expect(stream).toBeTrue(); + expect(stream[0]).toBeDefined(); await tx.rollback(); } catch (e) { await tx.rollback(); diff --git a/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js b/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js index b8e1b5083..441aae68b 100644 --- a/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js @@ -1,10 +1,6 @@ const models = require('vn-loopback/server/server').models; describe('ticket saveCmr()', () => { - beforeEach(() => { - spyOn(models.Ticket, 'saveCmr').and.returnValue(true); - }); - it(`should throw error if the cmr can't save`, async() => { const tx = await models.Ticket.beginTransaction({}); const ctx = { @@ -18,11 +14,11 @@ describe('ticket saveCmr()', () => { }; try { const options = {transaction: tx}; - const ticket = [1]; - await models.Ticket.saveCmr(ctx, ticket); + const ticket = [2]; + await models.Ticket.saveCmr(ctx, ticket, options); const hasDmsCmr = await models.TicketDms.findOne({ - where: {ticketFk: ticket[1]}, + where: {ticketFk: ticket[0]}, include: [{ relation: 'dms', fields: ['id'], @@ -35,7 +31,7 @@ describe('ticket saveCmr()', () => { }] }, options); - expect(hasDmsCmr?.dms()?.dmsType()).toEqual(1); + expect(hasDmsCmr?.dms()?.id).toBeGreaterThanOrEqual(1); await tx.rollback(); } catch (e) { await tx.rollback(); diff --git a/print/core/cluster.js b/print/core/cluster.js index a75c4cf24..f2b2c3f21 100644 --- a/print/core/cluster.js +++ b/print/core/cluster.js @@ -35,7 +35,8 @@ module.exports = { logger.error(`[Print] => ${err.message}`); }); - cluster.on('queue', () => logger.info('Printing task initialized by pool')); + cluster.on('queue', () => + process.env.SPEC_IS_RUNNING === 'false' && logger.info('Printing task initialized by pool')); }); } }; From ffa9212861e494a7676b1c7a01ddeafde0c2e4ec Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 7 Feb 2024 10:29:42 +0100 Subject: [PATCH 31/35] fix: refs #6184 Requested changes --- modules/ticket/back/methods/ticket/specs/saveCmr.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js b/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js index 441aae68b..e7d1e5ad2 100644 --- a/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveCmr.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('ticket saveCmr()', () => { - it(`should throw error if the cmr can't save`, async() => { + it(`should save cmr`, async() => { const tx = await models.Ticket.beginTransaction({}); const ctx = { req: { From 534b5bb05a021488fac049abc411590caebc6976 Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 12 Feb 2024 11:26:00 +0100 Subject: [PATCH 32/35] fix: refs #6106 where filter --- modules/route/back/methods/route/getTickets.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/route/back/methods/route/getTickets.js b/modules/route/back/methods/route/getTickets.js index d1ebf9ee7..59ba389ed 100644 --- a/modules/route/back/methods/route/getTickets.js +++ b/modules/route/back/methods/route/getTickets.js @@ -1,5 +1,5 @@ -const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const {ParameterizedSQL} = require('loopback-connector'); module.exports = Self => { Self.remoteMethod('getTickets', { @@ -83,13 +83,15 @@ module.exports = Self => { const where = filter.where; where['r.id'] = filter.id; + where.and = [{or: [ + {'t.packages': {gt: 0}}, + {and: [{'ot.code': 'delivery'}, {'tob.observationTypeFk': {neq: null}}]} + ]}]; stmt.merge(conn.makeWhere(filter.where)); stmt.merge(conn.makeGroupBy('t.id')); stmt.merge(conn.makeOrderBy(filter.order)); - const tickets = await conn.executeStmt(stmt, myOptions); - - return tickets; + return conn.executeStmt(stmt, myOptions); }; }; From a897a05e8b6a931b0288a67bf61964738cc170ca Mon Sep 17 00:00:00 2001 From: josepd Date: Tue, 13 Feb 2024 07:52:09 +0100 Subject: [PATCH 33/35] feat: refs#6685RestoreViewCredit --- db/routines/vn2008/views/credit.sql | 9 +++++++++ db/versions/10883-azureRuscus/00-firstScript.sql | 1 + 2 files changed, 10 insertions(+) create mode 100644 db/routines/vn2008/views/credit.sql create mode 100644 db/versions/10883-azureRuscus/00-firstScript.sql diff --git a/db/routines/vn2008/views/credit.sql b/db/routines/vn2008/views/credit.sql new file mode 100644 index 000000000..4bd3cef39 --- /dev/null +++ b/db/routines/vn2008/views/credit.sql @@ -0,0 +1,9 @@ +CREATE OR REPLACE DEFINER=`root`@`localhost` + SQL SECURITY DEFINER + VIEW `vn2008`.`credit` +AS SELECT `c`.`id` AS `id`, + `c`.`clientFk` AS `Id_Cliente`, + `c`.`workerFk` AS `Id_Trabajador`, + `c`.`amount` AS `amount`, + `c`.`created` AS `odbc_date` +FROM `vn`.`clientCredit` `c` \ No newline at end of file diff --git a/db/versions/10883-azureRuscus/00-firstScript.sql b/db/versions/10883-azureRuscus/00-firstScript.sql new file mode 100644 index 000000000..8e046d95b --- /dev/null +++ b/db/versions/10883-azureRuscus/00-firstScript.sql @@ -0,0 +1 @@ +GRANT SELECT ON TABLE vn2008.credit TO financialBoss; \ No newline at end of file From e08fb3d229485a9d0453a7e4e35cbe0a66ab44c4 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 13 Feb 2024 08:59:58 +0100 Subject: [PATCH 34/35] fix: refs #6184 Minor change --- loopback/locale/es.json | 5 +++-- modules/ticket/back/methods/ticket/saveSign.js | 11 ++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index b48772f0d..b0eb59cd5 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -339,8 +339,9 @@ "No tickets to invoice": "No hay tickets para facturar", "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado", "Name should be uppercase": "El nombre debe ir en mayúscula", - "Bank entity must be specified": "La entidad bancaria es obligatoria", + "Bank entity must be specified": "La entidad bancaria es obligatoria", "An email is necessary": "Es necesario un email", "You cannot update these fields": "No puedes actualizar estos campos", - "CountryFK cannot be empty": "El país no puede estar vacío" + "CountryFK cannot be empty": "El país no puede estar vacío", + "Cmr file does not exist": "El archivo del cmr no existe" } \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 0fcd41102..3718dfcda 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -34,8 +34,6 @@ module.exports = Self => { const myOptions = {userId: ctx.req.accessToken.userId}; let tx; let ticket; - let dms; - let gestDocCreated; if (typeof options == 'object') Object.assign(myOptions, options); @@ -86,8 +84,8 @@ module.exports = Self => { contentType: 'image/png', hasFile: true }; - dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); - gestDocCreated = true; + const dms = await models.Dms.uploadFile(ctxUploadFile, myOptions); + await models.TicketDms.create({ticketFk: ticket.id, dmsFk: dms[0].id}, myOptions); } try { @@ -137,9 +135,8 @@ module.exports = Self => { throw new UserError('Ticket is already signed'); if (location) await setLocation(ticketId); - if (!await hasSignDms(ticketId) && !gestDocCreated) + if (!await hasSignDms(ticketId)) await createGestDoc(ticketId); - await models.TicketDms.create({ticketFk: ticketId, dmsFk: dms[0].id}, myOptions); await ticket.updateAttribute('isSigned', true, myOptions); const deliveryState = await models.State.findOne({ @@ -160,7 +157,7 @@ module.exports = Self => { await models.Route.cmrEmail(ctx, externalTickets); return; } catch (e) { - if (tx) await tx.rollback(); + if (tx && tx.isActive()) await tx.rollback(); throw e; } }; From 744171dd4c33af9e2bfd94e5d9cf06628471b99e Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 13 Feb 2024 09:41:26 +0100 Subject: [PATCH 35/35] fix: refs #6184 Requested changes --- modules/ticket/back/methods/ticket/saveSign.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 3718dfcda..9c6e8181a 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -34,6 +34,7 @@ module.exports = Self => { const myOptions = {userId: ctx.req.accessToken.userId}; let tx; let ticket; + let externalTickets = []; if (typeof options == 'object') Object.assign(myOptions, options); @@ -89,7 +90,6 @@ module.exports = Self => { } try { - let externalTickets = []; for (const ticketId of tickets) { ticket = await models.Ticket.findById(ticketId, { include: [{ @@ -154,11 +154,10 @@ module.exports = Self => { } } if (tx) await tx.commit(); - await models.Route.cmrEmail(ctx, externalTickets); - return; } catch (e) { - if (tx && tx.isActive()) await tx.rollback(); + if (tx) await tx.rollback(); throw e; } + await models.Route.cmrEmail(ctx, externalTickets); }; };