From 8105c12a18605aa329bd58e76b30c9938c240a68 Mon Sep 17 00:00:00 2001 From: joan Date: Thu, 22 Sep 2022 08:48:29 +0200 Subject: [PATCH] Campaign metrics --- db/changes/10490-august/00-ACL.sql | 6 ++ front/core/services/email.js | 4 +- front/core/services/report.js | 4 +- loopback/locale/es.json | 3 +- .../methods/client/campaignMetricsEmail.js | 68 +++++++++++++++++++ .../back/methods/client/campaignMetricsPdf.js | 65 ++++++++++++++++++ modules/client/back/models/client.js | 2 + modules/client/front/consumption/index.js | 6 +- .../back/methods/ticket/deliveryNoteEmail.js | 19 ++---- .../back/methods/ticket/deliveryNotePdf.js | 21 ++---- .../campaign-metrics/assets/css/import.js | 15 ++-- .../campaign-metrics/campaign-metrics.js | 4 +- .../email/delivery-note/delivery-note.html | 2 +- .../email/delivery-note/delivery-note.js | 2 +- .../campaign-metrics/assets/css/import.js | 13 ++-- .../campaign-metrics/campaign-metrics.js | 16 ++--- .../reports/delivery-note/delivery-note.js | 52 +++++++------- 17 files changed, 217 insertions(+), 85 deletions(-) create mode 100644 db/changes/10490-august/00-ACL.sql create mode 100644 modules/client/back/methods/client/campaignMetricsEmail.js create mode 100644 modules/client/back/methods/client/campaignMetricsPdf.js diff --git a/db/changes/10490-august/00-ACL.sql b/db/changes/10490-august/00-ACL.sql new file mode 100644 index 000000000..f7d984e37 --- /dev/null +++ b/db/changes/10490-august/00-ACL.sql @@ -0,0 +1,6 @@ +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('Ticket', 'deliveryNotePdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Ticket', 'deliveryNoteEmail', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'campaignMetricsPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'campaignMetricsEmail', 'READ', 'ALLOW', 'ROLE', 'employee'); \ No newline at end of file diff --git a/front/core/services/email.js b/front/core/services/email.js index 500b10f54..b39627573 100644 --- a/front/core/services/email.js +++ b/front/core/services/email.js @@ -14,8 +14,8 @@ class Email { * @param {Object} params The email parameters * @return {Promise} Promise resolved when it's sent */ - send(url, params) { - return this.$http.post(url, params) + send(path, params) { + return this.$http.post(path, params) .then(() => this.vnApp.showMessage(this.$t('Notification sent!'))); } diff --git a/front/core/services/report.js b/front/core/services/report.js index 1b21a84d2..d28959d47 100644 --- a/front/core/services/report.js +++ b/front/core/services/report.js @@ -13,12 +13,12 @@ class Report { * @param {String} report The report name * @param {Object} params The report parameters */ - show(url, params) { + show(path, params) { params = Object.assign({ access_token: this.vnToken.token }, params); const serializedParams = this.$httpParamSerializer(params); - window.open(`api/${url}?${serializedParams}`); + window.open(`api/${path}?${serializedParams}`); } /** diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 01861490b..07a00024a 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -232,6 +232,5 @@ "Fichadas impares": "Fichadas impares", "Descanso diario 12h.": "Descanso diario 12h.", "Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.", - "Dirección incorrecta": "Dirección incorrecta", - "deliveryNote": "albaran-{{ticketId}}" + "Dirección incorrecta": "Dirección incorrecta" } \ No newline at end of file diff --git a/modules/client/back/methods/client/campaignMetricsEmail.js b/modules/client/back/methods/client/campaignMetricsEmail.js new file mode 100644 index 000000000..6bbff0a6c --- /dev/null +++ b/modules/client/back/methods/client/campaignMetricsEmail.js @@ -0,0 +1,68 @@ +const {Report, Email, smtp} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('campaignMetricsEmail', { + description: 'Sends the campaign metrics email with an attached PDF', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The client id', + http: {source: 'path'} + }, + { + arg: 'recipient', + type: 'string', + description: 'The recipient email', + required: true, + }, + { + arg: 'replyTo', + type: 'string', + description: 'The sender email to reply to', + required: false + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id to send to the recipient preferred language', + required: false + }, + { + arg: 'from', + type: 'string', + required: true + }, + { + arg: 'to', + type: 'string', + required: true + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/campaign-metrics-email', + verb: 'POST' + } + }); + + Self.campaignMetricsEmail = async(ctx, id) => { + 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]; + + const email = new Email('campaign-metrics', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/campaignMetricsPdf.js b/modules/client/back/methods/client/campaignMetricsPdf.js new file mode 100644 index 000000000..994fce254 --- /dev/null +++ b/modules/client/back/methods/client/campaignMetricsPdf.js @@ -0,0 +1,65 @@ +const { Report } = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('campaignMetricsPdf', { + description: 'Returns the delivery note pdf', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The client id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + required: false + }, + { + arg: 'from', + type: 'string', + required: true + }, + { + arg: 'to', + type: 'string', + required: true + } + ], + 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: '/:id/campaign-metrics-pdf', + verb: 'GET' + } + }); + + Self.campaignMetricsPdf = async(ctx, id) => { + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + const report = new Report('campaign-metrics', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 746261626..84997e204 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -34,6 +34,8 @@ module.exports = Self => { require('../methods/client/updatePortfolio')(Self); require('../methods/client/updateUser')(Self); require('../methods/client/uploadFile')(Self); + require('../methods/client/campaignMetricsPdf')(Self); + require('../methods/client/campaignMetricsEmail')(Self); // Validations diff --git a/modules/client/front/consumption/index.js b/modules/client/front/consumption/index.js index 7017fed41..d9b657318 100644 --- a/modules/client/front/consumption/index.js +++ b/modules/client/front/consumption/index.js @@ -45,11 +45,13 @@ class Controller extends Section { } showReport() { - this.vnReport.show('campaign-metrics', this.reportParams); + const path = `Clients/${this.client.id}/campaign-metrics-pdf`; + this.vnReport.show(path, this.reportParams); } sendEmail() { - this.vnEmail.send('campaign-metrics', this.reportParams); + const path = `Clients/${this.client.id}/campaign-metrics-email`; + this.vnEmail.send(path, this.reportParams); } changeGrouped(value) { diff --git a/modules/ticket/back/methods/ticket/deliveryNoteEmail.js b/modules/ticket/back/methods/ticket/deliveryNoteEmail.js index 1e7ef43b9..5926fba58 100644 --- a/modules/ticket/back/methods/ticket/deliveryNoteEmail.js +++ b/modules/ticket/back/methods/ticket/deliveryNoteEmail.js @@ -1,8 +1,8 @@ -const {Report, Email, smtp} = require('vn-print'); +const { Email } = require('vn-print'); module.exports = Self => { Self.remoteMethodCtx('deliveryNoteEmail', { - description: '', + description: 'Sends the delivery note email with an attached PDF', accepts: [ { arg: 'id', @@ -47,22 +47,15 @@ module.exports = Self => { }); Self.deliveryNoteEmail = async(ctx, id) => { - const args = ctx.args; - + const args = Object.assign({}, ctx.args); const params = { - ticketId: id, recipient: args.recipient, lang: ctx.req.getLocale() }; - if (args.recipientId) - params.recipientId = args.recipientId; - - if (args.replyTo) - params.replyTo = args.replyTo; - - if (args.type) - params.type = args.type; + delete args.ctx; + for (const param in args) + params[param] = args[param]; const email = new Email('delivery-note', params); diff --git a/modules/ticket/back/methods/ticket/deliveryNotePdf.js b/modules/ticket/back/methods/ticket/deliveryNotePdf.js index d1e288a98..373d96d1f 100644 --- a/modules/ticket/back/methods/ticket/deliveryNotePdf.js +++ b/modules/ticket/back/methods/ticket/deliveryNotePdf.js @@ -46,25 +46,16 @@ module.exports = Self => { }); Self.deliveryNotePdf = async(ctx, id) => { - const args = ctx.args; - const $t = ctx.req.__; + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; - const params = { - ticketId: id, - lang: ctx.req.getLocale() - }; - - if (args.recipientId) - params.recipientId = args.recipientId; - - if (args.type) - params.type = args.type; + delete args.ctx; + for (const param in args) + params[param] = args[param]; const report = new Report('delivery-note', params); const stream = await report.toPdfStream(); - const fileName = $t('deliveryNote', {ticketId: id}); - - return [stream, 'application/pdf', `filename="${fileName}.pdf"`]; + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; }; }; diff --git a/print/templates/email/campaign-metrics/assets/css/import.js b/print/templates/email/campaign-metrics/assets/css/import.js index b44d6bd37..89b2afaa5 100644 --- a/print/templates/email/campaign-metrics/assets/css/import.js +++ b/print/templates/email/campaign-metrics/assets/css/import.js @@ -1,8 +1,11 @@ -const Stylesheet = require(`${appPath}/core/stylesheet`); +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); module.exports = new Stylesheet([ - `${appPath}/common/css/spacing.css`, - `${appPath}/common/css/misc.css`, - `${appPath}/common/css/layout.css`, - `${appPath}/common/css/email.css`]) - .mergeStyles(); + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`]) + .mergeStyles(); \ No newline at end of file diff --git a/print/templates/email/campaign-metrics/campaign-metrics.js b/print/templates/email/campaign-metrics/campaign-metrics.js index 2bd93b725..0c3a01991 100755 --- a/print/templates/email/campaign-metrics/campaign-metrics.js +++ b/print/templates/email/campaign-metrics/campaign-metrics.js @@ -1,4 +1,4 @@ -const Component = require(`${appPath}/core/component`); +const Component = require(`vn-print/core/component`); const emailHeader = new Component('email-header'); const emailFooter = new Component('email-footer'); @@ -20,7 +20,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], required: true }, diff --git a/print/templates/email/delivery-note/delivery-note.html b/print/templates/email/delivery-note/delivery-note.html index 96c53b1d7..eaa154336 100644 --- a/print/templates/email/delivery-note/delivery-note.html +++ b/print/templates/email/delivery-note/delivery-note.html @@ -25,7 +25,7 @@

{{ $t('title') }}

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

-

+

diff --git a/print/templates/email/delivery-note/delivery-note.js b/print/templates/email/delivery-note/delivery-note.js index a6d1547de..ba3d44001 100755 --- a/print/templates/email/delivery-note/delivery-note.js +++ b/print/templates/email/delivery-note/delivery-note.js @@ -9,7 +9,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - ticketId: { + id: { type: [Number, String], required: true } diff --git a/print/templates/reports/campaign-metrics/assets/css/import.js b/print/templates/reports/campaign-metrics/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/campaign-metrics/assets/css/import.js +++ b/print/templates/reports/campaign-metrics/assets/css/import.js @@ -1,9 +1,12 @@ -const Stylesheet = require(`${appPath}/core/stylesheet`); +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); module.exports = new Stylesheet([ - `${appPath}/common/css/spacing.css`, - `${appPath}/common/css/misc.css`, - `${appPath}/common/css/layout.css`, - `${appPath}/common/css/report.css`, + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/report.css`, `${__dirname}/style.css`]) .mergeStyles(); diff --git a/print/templates/reports/campaign-metrics/campaign-metrics.js b/print/templates/reports/campaign-metrics/campaign-metrics.js index 6669ce067..da7cdd9ae 100755 --- a/print/templates/reports/campaign-metrics/campaign-metrics.js +++ b/print/templates/reports/campaign-metrics/campaign-metrics.js @@ -1,22 +1,22 @@ -const Component = require(`${appPath}/core/component`); +const Component = require(`vn-print/core/component`); const reportHeader = new Component('report-header'); const reportFooter = new Component('report-footer'); module.exports = { name: 'campaign-metrics', async serverPrefetch() { - this.client = await this.fetchClient(this.recipientId); - this.sales = await this.fetchSales(this.recipientId, this.from, this.to); + this.client = await this.fetchClient(this.id); + this.sales = await this.fetchSales(this.id, this.from, this.to); if (!this.client) throw new Error('Something went wrong'); }, methods: { - fetchClient(clientId) { - return this.findOneFromDef('client', [clientId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); }, - fetchSales(clientId, from, to) { - return this.rawSqlFromDef('sales', [clientId, from, to]); + fetchSales(id, from, to) { + return this.rawSqlFromDef('sales', [id, from, to]); }, }, components: { @@ -24,7 +24,7 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], required: true }, diff --git a/print/templates/reports/delivery-note/delivery-note.js b/print/templates/reports/delivery-note/delivery-note.js index e33b10765..d92329ac8 100755 --- a/print/templates/reports/delivery-note/delivery-note.js +++ b/print/templates/reports/delivery-note/delivery-note.js @@ -8,14 +8,14 @@ const fs = require('fs-extra'); module.exports = { name: 'delivery-note', async serverPrefetch() { - this.client = await this.fetchClient(this.ticketId); - this.ticket = await this.fetchTicket(this.ticketId); - this.sales = await this.fetchSales(this.ticketId); - this.address = await this.fetchAddress(this.ticketId); - this.services = await this.fetchServices(this.ticketId); - this.taxes = await this.fetchTaxes(this.ticketId); - this.packagings = await this.fetchPackagings(this.ticketId); - this.signature = await this.fetchSignature(this.ticketId); + this.client = await this.fetchClient(this.id); + this.ticket = await this.fetchTicket(this.id); + this.sales = await this.fetchSales(this.id); + this.address = await this.fetchAddress(this.id); + this.services = await this.fetchServices(this.id); + this.taxes = await this.fetchTaxes(this.id); + this.packagings = await this.fetchPackagings(this.id); + this.signature = await this.fetchSignature(this.id); if (!this.ticket) throw new Error('Something went wrong'); @@ -53,33 +53,33 @@ module.exports = { }, footerType() { const translatedType = this.$t(this.deliverNoteType); - return `${translatedType} ${this.ticketId}`; + return `${translatedType} ${this.id}`; } }, methods: { - fetchClient(ticketId) { - return this.findOneFromDef('client', [ticketId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); }, - fetchTicket(ticketId) { - return this.findOneFromDef('ticket', [ticketId]); + fetchTicket(id) { + return this.findOneFromDef('ticket', [id]); }, - fetchAddress(ticketId) { - return this.findOneFromDef(`address`, [ticketId]); + fetchAddress(id) { + return this.findOneFromDef(`address`, [id]); }, - fetchSignature(ticketId) { - return this.findOneFromDef('signature', [ticketId]); + fetchSignature(id) { + return this.findOneFromDef('signature', [id]); }, - fetchTaxes(ticketId) { - return this.findOneFromDef(`taxes`, [ticketId]); + fetchTaxes(id) { + return this.findOneFromDef(`taxes`, [id]); }, - fetchSales(ticketId) { - return this.rawSqlFromDef('sales', [ticketId]); + fetchSales(id) { + return this.rawSqlFromDef('sales', [id]); }, - fetchPackagings(ticketId) { - return this.rawSqlFromDef('packagings', [ticketId]); + fetchPackagings(id) { + return this.rawSqlFromDef('packagings', [id]); }, - fetchServices(ticketId) { - return this.rawSqlFromDef('services', [ticketId]); + fetchServices(id) { + return this.rawSqlFromDef('services', [id]); }, getSubTotal() { @@ -126,7 +126,7 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - ticketId: { + id: { type: [Number, String], required: true },