2019-01-14 16:26:59 +00:00
|
|
|
const fs = require('fs-extra');
|
2021-07-27 07:07:04 +00:00
|
|
|
const path = require('path');
|
2024-05-21 13:11:32 +00:00
|
|
|
const isProduction = require('vn-loopback/server/boot/isProduction');
|
2019-01-14 16:26:59 +00:00
|
|
|
|
|
|
|
module.exports = Self => {
|
2021-09-29 10:15:42 +00:00
|
|
|
Self.remoteMethodCtx('download', {
|
2019-01-14 16:26:59 +00:00
|
|
|
description: 'Download an invoice PDF',
|
|
|
|
accessType: 'READ',
|
|
|
|
accepts: [
|
|
|
|
{
|
|
|
|
arg: 'id',
|
2022-07-11 09:25:31 +00:00
|
|
|
type: 'string',
|
2019-01-14 16:26:59 +00:00
|
|
|
description: 'The invoice id',
|
|
|
|
http: {source: 'path'}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
returns: [
|
|
|
|
{
|
|
|
|
arg: 'body',
|
|
|
|
type: 'file',
|
|
|
|
root: true
|
|
|
|
}, {
|
|
|
|
arg: 'Content-Type',
|
2022-07-11 09:25:31 +00:00
|
|
|
type: 'string',
|
2019-01-14 16:26:59 +00:00
|
|
|
http: {target: 'header'}
|
|
|
|
}, {
|
|
|
|
arg: 'Content-Disposition',
|
2022-07-11 09:25:31 +00:00
|
|
|
type: 'string',
|
2019-01-14 16:26:59 +00:00
|
|
|
http: {target: 'header'}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
http: {
|
2022-07-11 09:25:31 +00:00
|
|
|
path: '/:id/download',
|
2019-01-14 16:26:59 +00:00
|
|
|
verb: 'GET'
|
2024-02-26 05:57:17 +00:00
|
|
|
},
|
2024-04-19 08:49:57 +00:00
|
|
|
accessScopes: ['DEFAULT', 'read:multimedia']
|
2019-01-14 16:26:59 +00:00
|
|
|
});
|
|
|
|
|
2021-09-29 10:15:42 +00:00
|
|
|
Self.download = async function(ctx, id, options) {
|
2021-07-27 07:07:04 +00:00
|
|
|
const models = Self.app.models;
|
2023-06-23 20:52:03 +00:00
|
|
|
options = typeof options == 'object'
|
|
|
|
? Object.assign({}, options) : {};
|
2021-07-27 07:07:04 +00:00
|
|
|
|
2023-06-23 20:52:03 +00:00
|
|
|
const pdfFile = await Self.filePath(id, options);
|
2021-07-27 07:07:04 +00:00
|
|
|
|
2023-06-23 20:52:03 +00:00
|
|
|
const container = await models.InvoiceContainer.container(pdfFile.year);
|
2023-06-23 20:02:33 +00:00
|
|
|
const rootPath = container.client.root;
|
2022-10-05 11:26:18 +00:00
|
|
|
|
2023-06-23 20:02:33 +00:00
|
|
|
const file = {
|
2023-06-23 20:52:03 +00:00
|
|
|
path: path.join(rootPath, pdfFile.path, pdfFile.name),
|
2023-06-23 20:02:33 +00:00
|
|
|
contentType: 'application/pdf',
|
2023-06-23 20:52:03 +00:00
|
|
|
name: pdfFile.name
|
2023-06-23 20:02:33 +00:00
|
|
|
};
|
2022-10-05 11:26:18 +00:00
|
|
|
|
2023-06-23 20:02:33 +00:00
|
|
|
try {
|
|
|
|
await fs.access(file.path);
|
2021-09-29 10:15:42 +00:00
|
|
|
} catch (error) {
|
2023-06-23 20:52:03 +00:00
|
|
|
await Self.createPdf(ctx, id, options);
|
2021-09-29 10:15:42 +00:00
|
|
|
}
|
2023-06-23 20:02:33 +00:00
|
|
|
|
2023-06-23 20:52:03 +00:00
|
|
|
let stream = await fs.createReadStream(file.path);
|
2023-06-23 20:02:33 +00:00
|
|
|
// XXX: To prevent unhandled ENOENT error
|
|
|
|
// https://stackoverflow.com/questions/17136536/is-enoent-from-fs-createreadstream-uncatchable
|
|
|
|
stream.on('error', err => {
|
|
|
|
const e = new Error(err.message);
|
|
|
|
err.stack = e.stack;
|
|
|
|
console.error(err);
|
|
|
|
});
|
|
|
|
|
2024-05-21 13:11:32 +00:00
|
|
|
if (!isProduction()) {
|
2023-06-23 20:52:03 +00:00
|
|
|
try {
|
|
|
|
await fs.access(file.path);
|
|
|
|
} catch (error) {
|
|
|
|
stream = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return [stream, file.contentType, `filename="${pdfFile.name}"`];
|
2019-01-14 16:26:59 +00:00
|
|
|
};
|
|
|
|
};
|