From 197ed2009f7f13135f6f30043807539920ecad8f Mon Sep 17 00:00:00 2001 From: joan Date: Wed, 29 Sep 2021 12:15:42 +0200 Subject: [PATCH 1/2] fix(invoicePdf): Create PDF document on invoice download Refs: 3109, 3110 --- loopback/locale/en.json | 3 +- loopback/locale/es.json | 3 +- .../back/methods/client/hasCustomerRole.js | 6 ++- .../client/specs/hasCustomerRole.spec.js | 16 +++--- modules/client/front/web-access/index.js | 2 +- .../back/methods/invoiceOut/createPdf.js | 4 +- .../back/methods/invoiceOut/download.js | 52 ++++++++++++------- .../methods/invoiceOut/specs/download.spec.js | 15 +++++- 8 files changed, 64 insertions(+), 37 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 70f3984a6..bc97eae19 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -115,5 +115,6 @@ "A ticket with a negative base can't be invoiced": "A ticket with a negative base can't be invoiced", "This client is not invoiceable": "This client is not invoiceable", "INACTIVE_PROVIDER": "Inactive provider", - "reference duplicated": "reference duplicated" + "reference duplicated": "reference duplicated", + "The PDF document does not exists": "The PDF document does not exists. Try regenerating it from 'Regenerate invoice PDF' option" } \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 7a670d2ed..cdf15c674 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -209,5 +209,6 @@ "Wasn't able to invoice the following clients": "No se han podido facturar los siguientes clientes", "Can't verify data unless the client has a business type": "No se puede verificar datos de un cliente que no tiene tipo de negocio", "You don't have enough privileges to set this credit amount": "No tienes suficientes privilegios para establecer esta cantidad de crédito", - "You can't change the credit set to zero from a manager": "No puedes cambiar el cŕedito establecido a cero por un gerente" + "You can't change the credit set to zero from a manager": "No puedes cambiar el cŕedito establecido a cero por un gerente", + "The PDF document does not exists": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'" } \ No newline at end of file diff --git a/modules/client/back/methods/client/hasCustomerRole.js b/modules/client/back/methods/client/hasCustomerRole.js index d66839936..e790d6e3a 100644 --- a/modules/client/back/methods/client/hasCustomerRole.js +++ b/modules/client/back/methods/client/hasCustomerRole.js @@ -19,7 +19,7 @@ module.exports = Self => { } }); - Self.hasCustomerRole = (id, options) => { + Self.hasCustomerRole = async(id, options) => { const myOptions = {}; if (typeof options == 'object') @@ -31,7 +31,9 @@ module.exports = Self => { JOIN salix.Role r ON r.id = A.roleFK WHERE r.name = 'customer' AND A.id IN (?)`; + const [result] = await Self.rawSql(query, [id], myOptions); + const {isCustomer} = result; - return Self.rawSql(query, [id], myOptions); + return isCustomer; }; }; diff --git a/modules/client/back/methods/client/specs/hasCustomerRole.spec.js b/modules/client/back/methods/client/specs/hasCustomerRole.spec.js index 08b13a88e..0fe83b738 100644 --- a/modules/client/back/methods/client/specs/hasCustomerRole.spec.js +++ b/modules/client/back/methods/client/specs/hasCustomerRole.spec.js @@ -9,9 +9,9 @@ describe('Client hasCustomerRole', () => { const id = 1101; - const [result] = await models.Client.hasCustomerRole(id, options); + const result = await models.Client.hasCustomerRole(id, options); - expect(result).toEqual(jasmine.objectContaining({isCustomer: 1})); + expect(result).toBeTruthy(); await tx.rollback(); } catch (e) { @@ -27,9 +27,9 @@ describe('Client hasCustomerRole', () => { const options = {transaction: tx}; const id = 8; - const [result] = await models.Client.hasCustomerRole(id, options); + const result = await models.Client.hasCustomerRole(id, options); - expect(result).toEqual(jasmine.objectContaining({isCustomer: 0})); + expect(result).toBeFalsy(); await tx.rollback(); } catch (e) { @@ -46,9 +46,9 @@ describe('Client hasCustomerRole', () => { const id = 999; - const [result] = await models.Client.hasCustomerRole(id, options); + const result = await models.Client.hasCustomerRole(id, options); - expect(result).toEqual(jasmine.objectContaining({isCustomer: 0})); + expect(result).toBeFalsy(); await tx.rollback(); } catch (e) { @@ -65,9 +65,9 @@ describe('Client hasCustomerRole', () => { const id = 'WRONG!'; - const [result] = await models.Client.hasCustomerRole(id, options); + const result = await models.Client.hasCustomerRole(id, options); - expect(result).toEqual(jasmine.objectContaining({isCustomer: 0})); + expect(result).toBeFalsy(); await tx.rollback(); } catch (e) { diff --git a/modules/client/front/web-access/index.js b/modules/client/front/web-access/index.js index 03c1292d0..a37e72a9d 100644 --- a/modules/client/front/web-access/index.js +++ b/modules/client/front/web-access/index.js @@ -19,7 +19,7 @@ export default class Controller extends Section { isCustomer() { if (this.client.id) { this.$http.get(`Clients/${this.client.id}/hasCustomerRole`).then(res => { - this.canChangePassword = res.data && res.data.isCustomer; + this.canChangePassword = res.data && res.data; }); } } diff --git a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js index a787e48a1..15ba79ba0 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js @@ -28,8 +28,8 @@ module.exports = Self => { Self.createPdf = async function(ctx, id, options) { const models = Self.app.models; const headers = ctx.req.headers; - const origin = headers.origin; - const authorization = headers.authorization; + const origin = headers.origin || headers.referer; + const authorization = ctx.req.accessToken.id; if (process.env.NODE_ENV == 'test') throw new UserError(`Action not allowed on the test environment`); diff --git a/modules/invoiceOut/back/methods/invoiceOut/download.js b/modules/invoiceOut/back/methods/invoiceOut/download.js index 983647982..21459e228 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/download.js +++ b/modules/invoiceOut/back/methods/invoiceOut/download.js @@ -1,8 +1,9 @@ const fs = require('fs-extra'); const path = require('path'); +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethod('download', { + Self.remoteMethodCtx('download', { description: 'Download an invoice PDF', accessType: 'READ', accepts: [ @@ -34,34 +35,45 @@ module.exports = Self => { } }); - Self.download = async function(id, options) { + Self.download = async function(ctx, id, options) { const models = Self.app.models; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - const invoiceOut = await models.InvoiceOut.findById(id, null, myOptions); + try { + const invoiceOut = await models.InvoiceOut.findById(id, null, myOptions); - const created = invoiceOut.created; - const year = created.getFullYear().toString(); - const month = created.getMonth().toString(); - const day = created.getDate().toString(); + const created = invoiceOut.created; + const year = created.getFullYear().toString(); + const month = created.getMonth().toString(); + const day = created.getDate().toString(); - const container = await models.InvoiceContainer.container(year); - const rootPath = container.client.root; - const src = path.join(rootPath, year, month, day); - const fileName = `${invoiceOut.ref}.pdf`; - const fileSrc = path.join(src, fileName); + const container = await models.InvoiceContainer.container(year); + const rootPath = container.client.root; + const src = path.join(rootPath, year, month, day); + const fileName = `${invoiceOut.ref}.pdf`; + const fileSrc = path.join(src, fileName); - const file = { - path: fileSrc, - contentType: 'application/pdf', - name: `${id}.pdf` - }; + // Creates PDF document if it has not been created + if (!invoiceOut.hasPdf || !fs.existsSync(fileSrc)) + await Self.createPdf(ctx, invoiceOut.id, myOptions); - await fs.access(file.path); - let stream = fs.createReadStream(file.path); - return [stream, file.contentType, `filename="${file.name}"`]; + const file = { + path: fileSrc, + contentType: 'application/pdf', + name: `${id}.pdf` + }; + + await fs.access(file.path); + let stream = fs.createReadStream(file.path); + return [stream, file.contentType, `filename="${file.name}"`]; + } catch (error) { + if (error.code === 'ENOENT') + throw new UserError('The PDF document does not exists'); + + throw error; + } }; }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/download.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/download.spec.js index c053adde1..631991161 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/download.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/download.spec.js @@ -2,14 +2,25 @@ const models = require('vn-loopback/server/server').models; const fs = require('fs-extra'); describe('InvoiceOut download()', () => { - it('should return the downloaded fine name', async() => { + const userId = 9; + const invoiceId = 1; + const ctx = { + req: { + + accessToken: {userId: userId}, + headers: {origin: 'http://localhost:5000'}, + } + }; + + it('should return the downloaded file name', async() => { spyOn(models.InvoiceContainer, 'container').and.returnValue({ client: {root: '/path'} }); spyOn(fs, 'createReadStream').and.returnValue(new Promise(resolve => resolve('streamObject'))); spyOn(fs, 'access').and.returnValue(true); + spyOn(models.InvoiceOut, 'createPdf').and.returnValue(new Promise(resolve => resolve(true))); - const result = await models.InvoiceOut.download(1); + const result = await models.InvoiceOut.download(ctx, invoiceId); expect(result[1]).toEqual('application/pdf'); expect(result[2]).toEqual('filename="1.pdf"'); From 458d2670b3aa5db0c6987f3ea141f8ea99187e35 Mon Sep 17 00:00:00 2001 From: joan Date: Wed, 29 Sep 2021 12:17:21 +0200 Subject: [PATCH 2/2] Updated unit test --- modules/client/front/web-access/index.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/client/front/web-access/index.spec.js b/modules/client/front/web-access/index.spec.js index 73c4f1043..00fa12781 100644 --- a/modules/client/front/web-access/index.spec.js +++ b/modules/client/front/web-access/index.spec.js @@ -33,7 +33,7 @@ describe('Component VnClientWebAccess', () => { it('should return true if the password can be modified', () => { controller.client = {id: '1234'}; - $httpBackend.expectGET(`Clients/${controller.client.id}/hasCustomerRole`).respond({isCustomer: true}); + $httpBackend.expectGET(`Clients/${controller.client.id}/hasCustomerRole`).respond(true); controller.isCustomer(); $httpBackend.flush(); @@ -43,7 +43,7 @@ describe('Component VnClientWebAccess', () => { it(`should return a false if the password can't be modified`, () => { controller.client = {id: '1234'}; - $httpBackend.expectGET(`Clients/${controller.client.id}/hasCustomerRole`).respond({isCustomer: false}); + $httpBackend.expectGET(`Clients/${controller.client.id}/hasCustomerRole`).respond(false); controller.isCustomer(); $httpBackend.flush();