3109-download_invoice #743

Merged
joan merged 2 commits from 3109-download_invoice into dev 2021-09-29 10:25:49 +00:00
8 changed files with 64 additions and 37 deletions
Showing only changes of commit 197ed2009f - Show all commits

View File

@ -115,5 +115,6 @@
"A ticket with a negative base can't be invoiced": "A ticket with a negative base can't be invoiced", "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", "This client is not invoiceable": "This client is not invoiceable",
"INACTIVE_PROVIDER": "Inactive provider", "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"
} }

View File

@ -209,5 +209,6 @@
"Wasn't able to invoice the following clients": "No se han podido facturar los siguientes clientes", "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", "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 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'"
} }

View File

@ -19,7 +19,7 @@ module.exports = Self => {
} }
}); });
Self.hasCustomerRole = (id, options) => { Self.hasCustomerRole = async(id, options) => {
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
@ -31,7 +31,9 @@ module.exports = Self => {
JOIN salix.Role r ON r.id = A.roleFK JOIN salix.Role r ON r.id = A.roleFK
WHERE r.name = 'customer' WHERE r.name = 'customer'
AND A.id IN (?)`; AND A.id IN (?)`;
const [result] = await Self.rawSql(query, [id], myOptions);
const {isCustomer} = result;
return Self.rawSql(query, [id], myOptions); return isCustomer;
}; };
}; };

View File

@ -9,9 +9,9 @@ describe('Client hasCustomerRole', () => {
const id = 1101; 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(); await tx.rollback();
} catch (e) { } catch (e) {
@ -27,9 +27,9 @@ describe('Client hasCustomerRole', () => {
const options = {transaction: tx}; const options = {transaction: tx};
const id = 8; 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(); await tx.rollback();
} catch (e) { } catch (e) {
@ -46,9 +46,9 @@ describe('Client hasCustomerRole', () => {
const id = 999; 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(); await tx.rollback();
} catch (e) { } catch (e) {
@ -65,9 +65,9 @@ describe('Client hasCustomerRole', () => {
const id = 'WRONG!'; 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(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -19,7 +19,7 @@ export default class Controller extends Section {
isCustomer() { isCustomer() {
if (this.client.id) { if (this.client.id) {
this.$http.get(`Clients/${this.client.id}/hasCustomerRole`).then(res => { this.$http.get(`Clients/${this.client.id}/hasCustomerRole`).then(res => {
this.canChangePassword = res.data && res.data.isCustomer; this.canChangePassword = res.data && res.data;
}); });
} }
} }

View File

@ -28,8 +28,8 @@ module.exports = Self => {
Self.createPdf = async function(ctx, id, options) { Self.createPdf = async function(ctx, id, options) {
const models = Self.app.models; const models = Self.app.models;
const headers = ctx.req.headers; const headers = ctx.req.headers;
const origin = headers.origin; const origin = headers.origin || headers.referer;
const authorization = headers.authorization; const authorization = ctx.req.accessToken.id;
if (process.env.NODE_ENV == 'test') if (process.env.NODE_ENV == 'test')
throw new UserError(`Action not allowed on the test environment`); throw new UserError(`Action not allowed on the test environment`);

View File

@ -1,8 +1,9 @@
const fs = require('fs-extra'); const fs = require('fs-extra');
const path = require('path'); const path = require('path');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('download', { Self.remoteMethodCtx('download', {
description: 'Download an invoice PDF', description: 'Download an invoice PDF',
accessType: 'READ', accessType: 'READ',
accepts: [ 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 models = Self.app.models;
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); 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 created = invoiceOut.created;
const year = created.getFullYear().toString(); const year = created.getFullYear().toString();
const month = created.getMonth().toString(); const month = created.getMonth().toString();
const day = created.getDate().toString(); const day = created.getDate().toString();
const container = await models.InvoiceContainer.container(year); const container = await models.InvoiceContainer.container(year);
const rootPath = container.client.root; const rootPath = container.client.root;
const src = path.join(rootPath, year, month, day); const src = path.join(rootPath, year, month, day);
const fileName = `${invoiceOut.ref}.pdf`; const fileName = `${invoiceOut.ref}.pdf`;
const fileSrc = path.join(src, fileName); const fileSrc = path.join(src, fileName);
const file = { // Creates PDF document if it has not been created
path: fileSrc, if (!invoiceOut.hasPdf || !fs.existsSync(fileSrc))
contentType: 'application/pdf', await Self.createPdf(ctx, invoiceOut.id, myOptions);
name: `${id}.pdf`
};
await fs.access(file.path); const file = {
let stream = fs.createReadStream(file.path); path: fileSrc,
return [stream, file.contentType, `filename="${file.name}"`]; 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;
}
}; };
}; };

View File

@ -2,14 +2,25 @@ const models = require('vn-loopback/server/server').models;
const fs = require('fs-extra'); const fs = require('fs-extra');
describe('InvoiceOut download()', () => { 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({ spyOn(models.InvoiceContainer, 'container').and.returnValue({
client: {root: '/path'} client: {root: '/path'}
}); });
spyOn(fs, 'createReadStream').and.returnValue(new Promise(resolve => resolve('streamObject'))); spyOn(fs, 'createReadStream').and.returnValue(new Promise(resolve => resolve('streamObject')));
spyOn(fs, 'access').and.returnValue(true); 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[1]).toEqual('application/pdf');
expect(result[2]).toEqual('filename="1.pdf"'); expect(result[2]).toEqual('filename="1.pdf"');