diff --git a/back/methods/osticket/osTicketReportEmail.js b/back/methods/osticket/osTicketReportEmail.js new file mode 100644 index 000000000..ebb74c385 --- /dev/null +++ b/back/methods/osticket/osTicketReportEmail.js @@ -0,0 +1,29 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('osTicketReportEmail', { + description: 'Sends the buyer waste email', + accessType: 'WRITE', + accepts: [], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/osticket-report-email', + verb: 'POST' + } + }); + + Self.osTicketReportEmail = async ctx => { + const models = Self.app.models; + const printConfig = await models.PrintConfig.findOne(); + + const email = new Email('osticket-report', { + recipient: printConfig.itRecipient, + lang: ctx.req.getLocale() + }); + + return email.send(); + }; +}; diff --git a/back/model-config.json b/back/model-config.json index f4adc954b..830a78fd4 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -121,6 +121,9 @@ }, "Edi": { "dataSource": "vn" + }, + "PrintConfig": { + "dataSource": "vn" } } diff --git a/back/models/osticket.js b/back/models/osticket.js index 58923e08e..50e429160 100644 --- a/back/models/osticket.js +++ b/back/models/osticket.js @@ -1,3 +1,4 @@ module.exports = Self => { + require('../methods/osticket/osTicketReportEmail')(Self); require('../methods/osticket/closeTicket')(Self); }; diff --git a/back/models/osticket.json b/back/models/osticket.json index 0c673d004..6ba80b30e 100644 --- a/back/models/osticket.json +++ b/back/models/osticket.json @@ -1,12 +1,5 @@ { "name": "OsTicket", - "base": "VnModel", - "acls": [{ - "property": "validations", - "accessType": "EXECUTE", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" - }] + "base": "VnModel" } \ No newline at end of file diff --git a/back/models/print-config.json b/back/models/print-config.json new file mode 100644 index 000000000..badb57083 --- /dev/null +++ b/back/models/print-config.json @@ -0,0 +1,29 @@ +{ + "name": "PrintConfig", + "description": "Print config", + "base": "VnModel", + "options": { + "mysql": { + "table": "salix.printConfig" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "itRecipient": { + "type": "string" + }, + "incidencesEmail": { + "type": "string" + } + }, + "acls": [{ + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + }] +} \ No newline at end of file diff --git a/db/changes/10490-august/00-ACL.sql b/db/changes/10490-august/00-ACL.sql index e07610c60..2cce197b2 100644 --- a/db/changes/10490-august/00-ACL.sql +++ b/db/changes/10490-august/00-ACL.sql @@ -1,3 +1,48 @@ +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('ClientConsumptionQueue', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Ticket', 'deliveryNotePdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Ticket', 'deliveryNoteEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Ticket', 'deliveryNoteCsvPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Ticket', 'deliveryNoteCsvEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'campaignMetricsPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'campaignMetricsEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'clientWelcomeHtml', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'clientWelcomeEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'creditRequestPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'creditRequestHtml', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'creditRequestEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'printerSetupHtml', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'printerSetupEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'sepaCoreEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'letterDebtorPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'letterDebtorStHtml', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'letterDebtorStEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'letterDebtorNdHtml', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'letterDebtorNdEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'clientDebtStatementPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'clientDebtStatementHtml', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'clientDebtStatementEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'incotermsAuthorizationPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'incotermsAuthorizationHtml', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'incotermsAuthorizationEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Client', 'consumptionSendQueued', 'WRITE', 'ALLOW', 'ROLE', 'system'), + ('InvoiceOut', 'invoiceEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('InvoiceOut', 'exportationPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('InvoiceOut', 'sendQueued', 'WRITE', 'ALLOW', 'ROLE', 'system'), + ('Ticket', 'invoiceCsvPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Ticket', 'invoiceCsvEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Supplier', 'campaignMetricsPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Supplier', 'campaignMetricsEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Travel', 'extraCommunityPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Travel', 'extraCommunityEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Entry', 'entryOrderPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('OsTicket', 'osTicketReportEmail', 'WRITE', 'ALLOW', 'ROLE', 'system'), + ('Item', 'buyerWasteEmail', 'WRITE', 'ALLOW', 'ROLE', 'system'), + ('Claim', 'claimPickupPdf', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Claim', 'claimPickupEmail', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'), + ('Item', 'labelPdf', 'READ', 'ALLOW', 'ROLE', 'employee'); + INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) VALUES ('Sector','*','READ','ALLOW','ROLE','employee'); INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) diff --git a/db/changes/10490-august/00-clientConsumptionQueue.sql b/db/changes/10490-august/00-clientConsumptionQueue.sql new file mode 100644 index 000000000..2734d32cc --- /dev/null +++ b/db/changes/10490-august/00-clientConsumptionQueue.sql @@ -0,0 +1,9 @@ +create table `vn`.`clientConsumptionQueue` +( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + params json not null, + queued datetime default current_timestamp() not null, + printed datetime null, + status varchar(50) default '' null +) + comment 'Queue for client consumption PDF mailing'; diff --git a/db/changes/10490-august/00-invoiceOutQueue.sql b/db/changes/10490-august/00-invoiceOutQueue.sql new file mode 100644 index 000000000..52ed4a113 --- /dev/null +++ b/db/changes/10490-august/00-invoiceOutQueue.sql @@ -0,0 +1 @@ +rename table `vn`.`invoiceOut_queue` to `vn`.`invoiceOutQueue`; diff --git a/db/changes/10490-august/00-itemConfig.sql b/db/changes/10490-august/00-itemConfig.sql new file mode 100644 index 000000000..b148aa094 --- /dev/null +++ b/db/changes/10490-august/00-itemConfig.sql @@ -0,0 +1,5 @@ +ALTER TABLE `vn`.`itemConfig` + ADD id int null PRIMARY KEY first; + +ALTER TABLE `vn`.`itemConfig` + ADD wasteRecipients VARCHAR(50) NOT NULL comment 'Weekly waste report schedule recipients'; diff --git a/db/changes/10490-august/00-printConfig.sql b/db/changes/10490-august/00-printConfig.sql new file mode 100644 index 000000000..c5af09ac9 --- /dev/null +++ b/db/changes/10490-august/00-printConfig.sql @@ -0,0 +1,10 @@ +create table `salix`.`printConfig` +( + id int auto_increment, + itRecipient varchar(50) null comment 'IT recipients for report mailing', + incidencesEmail varchar(50) null comment 'CAU destinatary email', + constraint printConfig_pk + primary key (id) +) + comment 'Print service config'; + diff --git a/db/changes/10490-august/00-sample.sql b/db/changes/10490-august/00-sample.sql new file mode 100644 index 000000000..f84cd723e --- /dev/null +++ b/db/changes/10490-august/00-sample.sql @@ -0,0 +1,6 @@ +alter table `vn`.`sample` + add model VARCHAR(25) null comment 'Model name in plural'; + +UPDATE vn.sample t + SET t.model = 'Clients' + WHERE t.id IN(12, 13, 14, 15, 16, 18, 19, 20); \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 1f66a53cf..73a6ef687 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -13,7 +13,11 @@ INSERT INTO `salix`.`AccessToken` (`id`, `ttl`, `created`, `userId`) VALUES ('DEFAULT_TOKEN', '1209600', util.VN_CURDATE(), 66); -INSERT INTO `vn`.`ticketConfig` (`id`, `scopeDays`) +INSERT INTO `salix`.`printConfig` (`id`, `itRecipient`, `incidencesEmail`) + VALUES + (1, 'it@gotamcity.com', 'incidences@gotamcity.com'); + +INSERT INTO `vn`.`ticketConfig` (`id`, `scopeDays`) VALUES ('1', '6'); @@ -916,16 +920,19 @@ INSERT INTO `vn`.`expeditionStateType`(`id`, `description`, `code`) INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `workerFk`, `externalId`, `packagingFk`, `stateTypeFk`) VALUES - (1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 15, 1, 18, 'UR9000006041', 94, 1), - (2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 16, 2, 18, 'UR9000006041', 94, 1), - (3, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 3, 18, 'UR9000006041', 94, 2), - (4, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 4, 18, 'UR9000006041', 94, 2), - (5, 1, 2, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 1, 18, NULL, 94, 3), - (6, 7, 3, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL, 1, 18, NULL, 94, 3), - (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL, 1, 18, NULL, 94, NULL), - (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL, 1, 18, NULL, 94, 1), - (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 1, 18, NULL, 94, 2), - (10, 7, 7, 71, NOW(), NULL, 1, 18, NULL, 94, 3); + (1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 15, 1, 18, 'UR9000006041', 94, 1), + (2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 16, 2, 18, 'UR9000006041', 94, 1), + (3, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 3, 18, 'UR9000006041', 94, 2), + (4, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 4, 18, 'UR9000006041', 94, 2), + (5, 1, 2, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 1, 18, NULL, 94, 3), + (6, 7, 3, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL, 1, 18, NULL, 94, 3), + (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL, 1, 18, NULL, 94, NULL), + (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL, 1, 18, NULL, 94, 1), + (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL, 1, 18, NULL, 94, 2), + (10, 7, 7, 71, NOW(), NULL, 1, 18, NULL, 94, 3), + (11, 7, 8, 71, NOW(), NULL, 1, 18, NULL, 94, 3), + (12, 7, 9, 71, NOW(), NULL, 1, 18, NULL, 94, 3), + (13, 1, 10, 71, NOW(), NULL, 1, 18, NULL, 94, 3); INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`) @@ -1778,6 +1785,11 @@ INSERT INTO `vn`.`claimEnd`(`id`, `saleFk`, `claimFk`, `workerFk`, `claimDestina (1, 31, 4, 21, 2), (2, 32, 3, 21, 3); +INSERT INTO `vn`.`claimConfig`(`id`, `pickupContact`, `maxResponsibility`) + VALUES + (1, 'Contact description', 50), + (2, 'Contact description', 30); + INSERT INTO `hedera`.`tpvMerchant`(`id`, `description`, `companyFk`, `bankFk`, `secretKey`) VALUES (1, 'Arkham Bank', 442, 1, 'h12387193H10238'), diff --git a/front/core/services/email.js b/front/core/services/email.js index 633b13a26..02aa9051b 100644 --- a/front/core/services/email.js +++ b/front/core/services/email.js @@ -10,24 +10,12 @@ class Email { /** * Sends an email displaying a notification when it's sent. * - * @param {String} template The email report name + * @param {String} path The email report name * @param {Object} params The email parameters * @return {Promise} Promise resolved when it's sent */ - send(template, params) { - return this.$http.get(`email/${template}`, {params}) - .then(() => this.vnApp.showMessage(this.$t('Notification sent!'))); - } - - /** - * Sends an email displaying a notification when it's sent. - * - * @param {String} template The email report name - * @param {Object} params The email parameters - * @return {Promise} Promise resolved when it's sent - */ - sendCsv(template, params) { - return this.$http.get(`csv/${template}/send`, {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 c58a0ee0e..d6eb28ea4 100644 --- a/front/core/services/report.js +++ b/front/core/services/report.js @@ -10,30 +10,16 @@ class Report { * Shows a report in another window, automatically adds the authorization * token to params. * - * @param {String} report The report name + * @param {String} path The report name * @param {Object} params The report parameters */ - show(report, params) { + show(path, params) { params = Object.assign({ - authorization: this.vnToken.token + access_token: this.vnToken.token }, params); const serializedParams = this.$httpParamSerializer(params); - window.open(`api/report/${report}?${serializedParams}`); - } - - /** - * Shows a report in another window, automatically adds the authorization - * token to params. - * - * @param {String} report The report name - * @param {Object} params The report parameters - */ - showCsv(report, params) { - params = Object.assign({ - authorization: this.vnToken.token - }, params); - const serializedParams = this.$httpParamSerializer(params); - window.open(`api/csv/${report}/download?${serializedParams}`); + const query = serializedParams ? `?${serializedParams}` : ''; + window.open(`api/${path}${query}`); } } Report.$inject = ['$httpParamSerializer', 'vnToken']; diff --git a/loopback/server/boot/print.js b/loopback/server/boot/print.js index 0f6af4d56..7558c3ef8 100644 --- a/loopback/server/boot/print.js +++ b/loopback/server/boot/print.js @@ -1,3 +1,3 @@ module.exports = function(app) { - require('../../../print/boot.js')(app); + require('vn-print').boot(app); }; diff --git a/print/methods/csv/csv.js b/loopback/util/csv.js similarity index 85% rename from print/methods/csv/csv.js rename to loopback/util/csv.js index d8725582d..e79c18da8 100644 --- a/print/methods/csv/csv.js +++ b/loopback/util/csv.js @@ -1,3 +1,9 @@ +/** + * Transforms an object to a raw data CSV file. + * + * @param {Object} rows Data + * @return {String} Formatted CSV data + */ function toCSV(rows) { const [columns] = rows; let content = Object.keys(columns).join('\t'); diff --git a/modules/claim/back/methods/claim/claimPickupEmail.js b/modules/claim/back/methods/claim/claimPickupEmail.js new file mode 100644 index 000000000..b946353d6 --- /dev/null +++ b/modules/claim/back/methods/claim/claimPickupEmail.js @@ -0,0 +1,58 @@ +const {Report, Email, smtp} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('claimPickupEmail', { + description: 'Sends the the claim pickup order 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 + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/claim-pickup-email', + verb: 'POST' + } + }); + + Self.claimPickupEmail = 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('claim-pickup-order', params); + + return email.send(); + }; +}; diff --git a/modules/claim/back/methods/claim/claimPickupPdf.js b/modules/claim/back/methods/claim/claimPickupPdf.js new file mode 100644 index 000000000..0e3abe908 --- /dev/null +++ b/modules/claim/back/methods/claim/claimPickupPdf.js @@ -0,0 +1,55 @@ +const { Report } = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('claimPickupPdf', { + description: 'Returns the claim pickup order pdf', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The claim id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + 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: '/:id/claim-pickup-pdf', + verb: 'GET' + } + }); + + Self.claimPickupPdf = 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('claim-pickup-order', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/claim/back/models/claim.js b/modules/claim/back/models/claim.js index e6dc50073..c9d7ee7d4 100644 --- a/modules/claim/back/models/claim.js +++ b/modules/claim/back/models/claim.js @@ -9,4 +9,6 @@ module.exports = Self => { require('../methods/claim/isEditable')(Self); require('../methods/claim/updateClaimDestination')(Self); require('../methods/claim/downloadFile')(Self); + require('../methods/claim/claimPickupPdf')(Self); + require('../methods/claim/claimPickupEmail')(Self); }; diff --git a/modules/claim/front/descriptor/index.html b/modules/claim/front/descriptor/index.html index 56fd0bb35..0bbacf94b 100644 --- a/modules/claim/front/descriptor/index.html +++ b/modules/claim/front/descriptor/index.html @@ -10,6 +10,8 @@ Send Pickup order diff --git a/modules/claim/front/descriptor/index.js b/modules/claim/front/descriptor/index.js index 674ac91e1..0dddadbe1 100644 --- a/modules/claim/front/descriptor/index.js +++ b/modules/claim/front/descriptor/index.js @@ -11,17 +11,15 @@ class Controller extends Descriptor { } showPickupOrder() { - this.vnReport.show('claim-pickup-order', { - recipientId: this.claim.clientFk, - claimId: this.claim.id + this.vnReport.show(`Claims/${this.claim.id}/claim-pickup-pdf`, { + recipientId: this.claim.clientFk }); } sendPickupOrder() { - return this.vnEmail.send('claim-pickup-order', { + return this.vnEmail.send(`Claims/${this.claim.id}/claim-pickup-email`, { recipient: this.claim.client.email, - recipientId: this.claim.clientFk, - claimId: this.claim.id + recipientId: this.claim.clientFk }); } diff --git a/modules/claim/front/descriptor/index.spec.js b/modules/claim/front/descriptor/index.spec.js index 669a73954..e6785d3d8 100644 --- a/modules/claim/front/descriptor/index.spec.js +++ b/modules/claim/front/descriptor/index.spec.js @@ -24,12 +24,13 @@ describe('Item Component vnClaimDescriptor', () => { window.open = jasmine.createSpy('open'); const params = { - recipientId: claim.clientFk, - claimId: claim.id + recipientId: claim.clientFk }; controller.showPickupOrder(); - expect(controller.vnReport.show).toHaveBeenCalledWith('claim-pickup-order', params); + const expectedPath = `Claims/${claim.id}/claim-pickup-pdf`; + + expect(controller.vnReport.show).toHaveBeenCalledWith(expectedPath, params); }); }); @@ -39,12 +40,13 @@ describe('Item Component vnClaimDescriptor', () => { const params = { recipient: claim.client.email, - recipientId: claim.clientFk, - claimId: claim.id + recipientId: claim.clientFk }; controller.sendPickupOrder(); - expect(controller.vnEmail.send).toHaveBeenCalledWith('claim-pickup-order', params); + const expectedPath = `Claims/${claim.id}/claim-pickup-email`; + + expect(controller.vnEmail.send).toHaveBeenCalledWith(expectedPath, params); }); }); diff --git a/modules/client/back/methods/client/campaignMetricsEmail.js b/modules/client/back/methods/client/campaignMetricsEmail.js new file mode 100644 index 000000000..bb57f90a0 --- /dev/null +++ b/modules/client/back/methods/client/campaignMetricsEmail.js @@ -0,0 +1,69 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('campaignMetricsEmail', { + description: 'Sends the campaign metrics email with an attached PDF', + accessType: 'WRITE', + 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 => { + 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..14194d62b --- /dev/null +++ b/modules/client/back/methods/client/campaignMetricsPdf.js @@ -0,0 +1,66 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('campaignMetricsPdf', { + description: 'Returns the campaign metrics pdf', + accessType: 'READ', + 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/methods/client/clientDebtStatementEmail.js b/modules/client/back/methods/client/clientDebtStatementEmail.js new file mode 100644 index 000000000..8bcdc900f --- /dev/null +++ b/modules/client/back/methods/client/clientDebtStatementEmail.js @@ -0,0 +1,64 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('clientDebtStatementEmail', { + description: 'Sends the client debt statement email with an attached PDF', + accessType: 'WRITE', + 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 + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/client-debt-statement-email', + verb: 'POST' + } + }); + + Self.clientDebtStatementEmail = async ctx => { + 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('client-debt-statement', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/clientDebtStatementHtml.js b/modules/client/back/methods/client/clientDebtStatementHtml.js new file mode 100644 index 000000000..bfed696bc --- /dev/null +++ b/modules/client/back/methods/client/clientDebtStatementHtml.js @@ -0,0 +1,65 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('clientDebtStatementHtml', { + description: 'Returns the client debt statement email preview', + accessType: 'READ', + 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 + } + ], + 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/client-debt-statement-html', + verb: 'GET' + } + }); + + Self.clientDebtStatementHtml = async(ctx, id) => { + const {accessToken} = ctx.req; + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + params.isPreview = true; + params.access_token = accessToken.id; + + const report = new Email('client-debt-statement', params); + const html = await report.render(); + + return [html, 'text/html', `filename="mail-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/clientDebtStatementPdf.js b/modules/client/back/methods/client/clientDebtStatementPdf.js new file mode 100644 index 000000000..8e2dca314 --- /dev/null +++ b/modules/client/back/methods/client/clientDebtStatementPdf.js @@ -0,0 +1,61 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('clientDebtStatementPdf', { + description: 'Returns the client debt statement pdf', + accessType: 'READ', + 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 + } + ], + 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/client-debt-statement-pdf', + verb: 'GET' + } + }); + + Self.clientDebtStatementPdf = 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('client-debt-statement', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/clientWelcomeEmail.js b/modules/client/back/methods/client/clientWelcomeEmail.js new file mode 100644 index 000000000..318ee18e6 --- /dev/null +++ b/modules/client/back/methods/client/clientWelcomeEmail.js @@ -0,0 +1,59 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('clientWelcomeEmail', { + description: 'Sends the client welcome email with an attached PDF', + accessType: 'WRITE', + 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 + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/client-welcome-email', + verb: 'POST' + } + }); + + Self.clientWelcomeEmail = async ctx => { + 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('client-welcome', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/clientWelcomeHtml.js b/modules/client/back/methods/client/clientWelcomeHtml.js new file mode 100644 index 000000000..dfb560326 --- /dev/null +++ b/modules/client/back/methods/client/clientWelcomeHtml.js @@ -0,0 +1,58 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('clientWelcomeHtml', { + description: 'Returns the client welcome email preview', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The client id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + 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: '/:id/client-welcome-html', + verb: 'GET' + } + }); + + Self.clientWelcomeHtml = 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]; + + params.isPreview = true; + + const report = new Email('client-welcome', params); + const html = await report.render(); + + return [html, 'text/html', `filename="mail-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/consumptionSendQueued.js b/modules/client/back/methods/client/consumptionSendQueued.js new file mode 100644 index 000000000..3f551d3d2 --- /dev/null +++ b/modules/client/back/methods/client/consumptionSendQueued.js @@ -0,0 +1,80 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethod('consumptionSendQueued', { + description: 'Send all queued invoices', + accessType: 'WRITE', + accepts: [], + returns: { + type: 'object', + root: true + }, + http: { + path: '/consumption-send-queued', + verb: 'POST' + } + }); + + Self.consumptionSendQueued = async() => { + const queues = await Self.rawSql(` + SELECT + ccq.id, + c.id AS clientFk, + c.email AS clientEmail, + eu.email salesPersonEmail, + REPLACE(json_extract(params, '$.from'), '"', '') AS fromDate, + REPLACE(json_extract(params, '$.to'), '"', '') AS toDate + FROM clientConsumptionQueue ccq + JOIN client c ON ( + JSON_SEARCH( + JSON_ARRAY( + json_extract(params, '$.clients') + ) + , 'all', c.id) IS NOT NULL) + JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk + JOIN ticket t ON t.clientFk = c.id + JOIN sale s ON s.ticketFk = t.id + JOIN item i ON i.id = s.itemFk + JOIN itemType it ON it.id = i.typeFk + WHERE status = '' + AND it.isPackaging = FALSE + AND DATE(t.shipped) BETWEEN + REPLACE(json_extract(params, '$.from'), '"', '') AND + REPLACE(json_extract(params, '$.to'), '"', '') + GROUP BY c.id`); + + for (const queue of queues) { + try { + const args = { + id: queue.clientFk, + recipient: queue.clientEmail, + replyTo: queue.salesPersonEmail, + from: queue.fromDate, + to: queue.toDate + }; + + const email = new Email('campaign-metrics', args); + await email.send(); + + await Self.rawSql(` + UPDATE clientConsumptionQueue + SET status = 'printed', + printed = ? + WHERE id = ?`, + [new Date(), queue.id]); + } catch (error) { + await Self.rawSql(` + UPDATE clientConsumptionQueue + SET status = ? + WHERE id = ?`, + [error.message, queue.id]); + + throw e; + } + } + + return { + message: 'Success' + }; + }; +}; diff --git a/modules/client/back/methods/client/creditRequestEmail.js b/modules/client/back/methods/client/creditRequestEmail.js new file mode 100644 index 000000000..b6a60e971 --- /dev/null +++ b/modules/client/back/methods/client/creditRequestEmail.js @@ -0,0 +1,59 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('clientCreditEmail', { + description: 'Sends the credit request email with an attached PDF', + accessType: 'WRITE', + 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 + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/credit-request-email', + verb: 'POST' + } + }); + + Self.clientCreditEmail = async ctx => { + 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('credit-request', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/creditRequestHtml.js b/modules/client/back/methods/client/creditRequestHtml.js new file mode 100644 index 000000000..6b2d7fe4e --- /dev/null +++ b/modules/client/back/methods/client/creditRequestHtml.js @@ -0,0 +1,60 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('creditRequestHtml', { + description: 'Returns the credit request email preview', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The client id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + 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: '/:id/credit-request-html', + verb: 'GET' + } + }); + + Self.creditRequestHtml = async(ctx, id) => { + const {accessToken} = ctx.req; + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + params.isPreview = true; + params.access_token = accessToken.id; + + const report = new Email('credit-request', params); + const html = await report.render(); + + return [html, 'text/html', `filename="mail-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/creditRequestPdf.js b/modules/client/back/methods/client/creditRequestPdf.js new file mode 100644 index 000000000..2e3dc0619 --- /dev/null +++ b/modules/client/back/methods/client/creditRequestPdf.js @@ -0,0 +1,56 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('creditRequestPdf', { + description: 'Returns the credit request pdf', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The client id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + 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: '/:id/credit-request-pdf', + verb: 'GET' + } + }); + + Self.creditRequestPdf = 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('credit-request', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/incotermsAuthorizationEmail.js b/modules/client/back/methods/client/incotermsAuthorizationEmail.js new file mode 100644 index 000000000..2a4fe593a --- /dev/null +++ b/modules/client/back/methods/client/incotermsAuthorizationEmail.js @@ -0,0 +1,65 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('incotermsAuthorizationEmail', { + description: 'Sends the incoterms authorization email with an attached PDF', + accessType: 'WRITE', + 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: 'companyId', + type: 'number', + description: 'The company id', + required: true + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/incoterms-authorization-email', + verb: 'POST' + } + }); + + Self.incotermsAuthorizationEmail = async ctx => { + 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('incoterms-authorization', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/incotermsAuthorizationHtml.js b/modules/client/back/methods/client/incotermsAuthorizationHtml.js new file mode 100644 index 000000000..875495d93 --- /dev/null +++ b/modules/client/back/methods/client/incotermsAuthorizationHtml.js @@ -0,0 +1,66 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('incotermsAuthorizationHtml', { + description: 'Returns the incoterms authorization email preview', + accessType: 'READ', + 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: 'companyId', + type: 'number', + description: 'The company id', + 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/incoterms-authorization-html', + verb: 'GET' + } + }); + + Self.incotermsAuthorizationHtml = async(ctx, id) => { + const {accessToken} = ctx.req; + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + params.isPreview = true; + params.access_token = accessToken.id; + + const report = new Email('incoterms-authorization', params); + const html = await report.render(); + + return [html, 'text/html', `filename="mail-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/incotermsAuthorizationPdf.js b/modules/client/back/methods/client/incotermsAuthorizationPdf.js new file mode 100644 index 000000000..9a8a8d296 --- /dev/null +++ b/modules/client/back/methods/client/incotermsAuthorizationPdf.js @@ -0,0 +1,62 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('incotermsAuthorizationPdf', { + description: 'Returns the incoterms authorization pdf', + accessType: 'READ', + 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: 'companyId', + type: 'number', + description: 'The company id', + 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/incoterms-authorization-pdf', + verb: 'GET' + } + }); + + Self.incotermsAuthorizationPdf = 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('incoterms-authorization', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/letterDebtorNdEmail.js b/modules/client/back/methods/client/letterDebtorNdEmail.js new file mode 100644 index 000000000..e188c6e0a --- /dev/null +++ b/modules/client/back/methods/client/letterDebtorNdEmail.js @@ -0,0 +1,65 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('letterDebtorNdEmail', { + description: 'Sends the second debtor letter email with an attached PDF', + accessType: 'WRITE', + 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: 'companyId', + type: 'number', + description: 'The company id', + required: true + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/letter-debtor-nd-email', + verb: 'POST' + } + }); + + Self.letterDebtorNdEmail = async ctx => { + 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('letter-debtor-nd', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/letterDebtorNdHtml.js b/modules/client/back/methods/client/letterDebtorNdHtml.js new file mode 100644 index 000000000..320fbaef3 --- /dev/null +++ b/modules/client/back/methods/client/letterDebtorNdHtml.js @@ -0,0 +1,66 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('letterDebtorNdHtml', { + description: 'Returns the second letter debtor email preview', + accessType: 'READ', + 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: 'companyId', + type: 'number', + description: 'The company id', + 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/letter-debtor-nd-html', + verb: 'GET' + } + }); + + Self.letterDebtorNdHtml = async(ctx, id) => { + const {accessToken} = ctx.req; + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + params.isPreview = true; + params.access_token = accessToken.id; + + const report = new Email('letter-debtor-nd', params); + const html = await report.render(); + + return [html, 'text/html', `filename="mail-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/letterDebtorPdf.js b/modules/client/back/methods/client/letterDebtorPdf.js new file mode 100644 index 000000000..421d531e6 --- /dev/null +++ b/modules/client/back/methods/client/letterDebtorPdf.js @@ -0,0 +1,62 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('letterDebtorPdf', { + description: 'Returns the letter debtor pdf', + accessType: 'READ', + 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: 'companyId', + type: 'number', + description: 'The company id', + 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/letter-debtor-pdf', + verb: 'GET' + } + }); + + Self.letterDebtorPdf = 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('letter-debtor', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/letterDebtorStEmail.js b/modules/client/back/methods/client/letterDebtorStEmail.js new file mode 100644 index 000000000..ee39a101b --- /dev/null +++ b/modules/client/back/methods/client/letterDebtorStEmail.js @@ -0,0 +1,65 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('letterDebtorStEmail', { + description: 'Sends the printer setup email with an attached PDF', + accessType: 'WRITE', + 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: 'companyId', + type: 'number', + description: 'The company id', + required: true + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/letter-debtor-st-email', + verb: 'POST' + } + }); + + Self.letterDebtorStEmail = async ctx => { + 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('letter-debtor-st', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/letterDebtorStHtml.js b/modules/client/back/methods/client/letterDebtorStHtml.js new file mode 100644 index 000000000..acf75272b --- /dev/null +++ b/modules/client/back/methods/client/letterDebtorStHtml.js @@ -0,0 +1,66 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('letterDebtorStHtml', { + description: 'Returns the letter debtor email preview', + accessType: 'READ', + 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: 'companyId', + type: 'number', + description: 'The company id', + 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/letter-debtor-st-html', + verb: 'GET' + } + }); + + Self.letterDebtorStHtml = async(ctx, id) => { + const {accessToken} = ctx.req; + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + params.isPreview = true; + params.access_token = accessToken.id; + + const report = new Email('letter-debtor-st', params); + const html = await report.render(); + + return [html, 'text/html', `filename="mail-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/printerSetupEmail.js b/modules/client/back/methods/client/printerSetupEmail.js new file mode 100644 index 000000000..254948659 --- /dev/null +++ b/modules/client/back/methods/client/printerSetupEmail.js @@ -0,0 +1,59 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('printerSetupEmail', { + description: 'Sends the printer setup email with an attached PDF', + accessType: 'WRITE', + 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 + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/printer-setup-email', + verb: 'POST' + } + }); + + Self.printerSetupEmail = async ctx => { + 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('printer-setup', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/methods/client/printerSetupHtml.js b/modules/client/back/methods/client/printerSetupHtml.js new file mode 100644 index 000000000..1ef1843e0 --- /dev/null +++ b/modules/client/back/methods/client/printerSetupHtml.js @@ -0,0 +1,58 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('printerSetupHtml', { + description: 'Returns the printer setup email preview', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The client id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + 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: '/:id/printer-setup-html', + verb: 'GET' + } + }); + + Self.printerSetupHtml = 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]; + + params.isPreview = true; + + const report = new Email('printer-setup', params); + const html = await report.render(); + + return [html, 'text/html', `filename="mail-${id}.pdf"`]; + }; +}; diff --git a/modules/client/back/methods/client/sepaCoreEmail.js b/modules/client/back/methods/client/sepaCoreEmail.js new file mode 100644 index 000000000..93c9d4302 --- /dev/null +++ b/modules/client/back/methods/client/sepaCoreEmail.js @@ -0,0 +1,65 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('sepaCoreEmail', { + description: 'Sends the campaign metrics email with an attached PDF', + accessType: 'WRITE', + 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: 'companyId', + type: 'number', + description: 'The company id', + required: true + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/sepa-core-email', + verb: 'POST' + } + }); + + Self.sepaCoreEmail = async ctx => { + 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('sepa-core', params); + + return email.send(); + }; +}; diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json index 4feb3b168..b2e600610 100644 --- a/modules/client/back/model-config.json +++ b/modules/client/back/model-config.json @@ -26,6 +26,9 @@ "ClientCreditLimit": { "dataSource": "vn" }, + "ClientConsumptionQueue": { + "dataSource": "vn" + }, "ClientLog": { "dataSource": "vn" }, diff --git a/modules/client/back/models/client-consumption-queue.json b/modules/client/back/models/client-consumption-queue.json new file mode 100644 index 000000000..e423f218c --- /dev/null +++ b/modules/client/back/models/client-consumption-queue.json @@ -0,0 +1,30 @@ +{ + "name": "ClientConsumptionQueue", + "base": "VnModel", + "options": { + "mysql": { + "table": "clientConsumptionQueue" + } + }, + "properties": { + "params": { + "type": "string" + }, + "queued": { + "type": "date" + }, + "printed": { + "type": "date" + }, + "status": { + "type": "string" + } + }, + "relations": { + "client": { + "type": "belongsTo", + "model": "Client", + "foreignKey": "clientFk" + } + } +} diff --git a/modules/client/back/models/client-methods.js b/modules/client/back/models/client-methods.js new file mode 100644 index 000000000..04d10413a --- /dev/null +++ b/modules/client/back/models/client-methods.js @@ -0,0 +1,50 @@ +module.exports = Self => { + require('../methods/client/addressesPropagateRe')(Self); + require('../methods/client/canBeInvoiced')(Self); + require('../methods/client/canCreateTicket')(Self); + require('../methods/client/checkDuplicated')(Self); + require('../methods/client/confirmTransaction')(Self); + require('../methods/client/consumption')(Self); + require('../methods/client/createAddress')(Self); + require('../methods/client/createReceipt')(Self); + require('../methods/client/createWithUser')(Self); + require('../methods/client/extendedListFilter')(Self); + require('../methods/client/getAverageInvoiced')(Self); + require('../methods/client/getCard')(Self); + require('../methods/client/getDebt')(Self); + require('../methods/client/getMana')(Self); + require('../methods/client/getTransactions')(Self); + require('../methods/client/hasCustomerRole')(Self); + require('../methods/client/isValidClient')(Self); + require('../methods/client/lastActiveTickets')(Self); + require('../methods/client/sendSms')(Self); + require('../methods/client/setPassword')(Self); + require('../methods/client/summary')(Self); + require('../methods/client/updateAddress')(Self); + require('../methods/client/updateFiscalData')(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); + require('../methods/client/clientWelcomeHtml')(Self); + require('../methods/client/clientWelcomeEmail')(Self); + require('../methods/client/printerSetupHtml')(Self); + require('../methods/client/printerSetupEmail')(Self); + require('../methods/client/sepaCoreEmail')(Self); + require('../methods/client/letterDebtorPdf')(Self); + require('../methods/client/letterDebtorStHtml')(Self); + require('../methods/client/letterDebtorStEmail')(Self); + require('../methods/client/letterDebtorNdHtml')(Self); + require('../methods/client/letterDebtorNdEmail')(Self); + require('../methods/client/clientDebtStatementPdf')(Self); + require('../methods/client/clientDebtStatementHtml')(Self); + require('../methods/client/clientDebtStatementEmail')(Self); + require('../methods/client/creditRequestPdf')(Self); + require('../methods/client/creditRequestHtml')(Self); + require('../methods/client/creditRequestEmail')(Self); + require('../methods/client/incotermsAuthorizationPdf')(Self); + require('../methods/client/incotermsAuthorizationHtml')(Self); + require('../methods/client/incotermsAuthorizationEmail')(Self); + require('../methods/client/consumptionSendQueued')(Self); +}; diff --git a/modules/client/back/models/client-sample.js b/modules/client/back/models/client-sample.js index c7cda2412..787cc2ad8 100644 --- a/modules/client/back/models/client-sample.js +++ b/modules/client/back/models/client-sample.js @@ -1,4 +1,5 @@ const UserError = require('vn-loopback/util/user-error'); +const LoopBackContext = require('loopback-context'); module.exports = Self => { Self.validatesPresenceOf('typeFk', { @@ -6,10 +7,10 @@ module.exports = Self => { }); Self.observe('before save', async function(ctx) { - let models = Self.app.models; - let changes = ctx.data || ctx.instance; + const models = Self.app.models; + const changes = ctx.data || ctx.instance; - let sample = await models.Sample.findById(changes.typeFk); + const sample = await models.Sample.findById(changes.typeFk); if (sample.hasCompany && !changes.companyFk) throw new UserError('Choose a company'); @@ -25,11 +26,11 @@ module.exports = Self => { // Renew mandate if (mandate) { - let mandateType = await models.MandateType.findOne({ + const mandateType = await models.MandateType.findOne({ where: {name: mandate.type} }); - let oldMandate = await models.Mandate.findOne({ + const oldMandate = await models.Mandate.findOne({ where: { clientFk: changes.clientFk, companyFk: changes.companyFk, @@ -50,10 +51,8 @@ module.exports = Self => { }); } - // Apply workerFk - let filter = {where: {userFk: ctx.options.accessToken.userId}}; - let worker = await Self.app.models.Worker.findOne(filter); + const loopBackContext = LoopBackContext.getCurrentContext(); - changes.workerFk = worker.id; + changes.userFk = loopBackContext.active.accessToken.userId; }); }; diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index c54f56367..3bd89eff1 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -1,4 +1,3 @@ -const got = require('got'); const UserError = require('vn-loopback/util/user-error'); const getFinalState = require('vn-loopback/util/hook').getFinalState; const isMultiple = require('vn-loopback/util/hook').isMultiple; @@ -8,32 +7,7 @@ const LoopBackContext = require('loopback-context'); module.exports = Self => { // Methods - require('../methods/client/addressesPropagateRe')(Self); - require('../methods/client/canBeInvoiced')(Self); - require('../methods/client/canCreateTicket')(Self); - require('../methods/client/checkDuplicated')(Self); - require('../methods/client/confirmTransaction')(Self); - require('../methods/client/consumption')(Self); - require('../methods/client/createAddress')(Self); - require('../methods/client/createReceipt')(Self); - require('../methods/client/createWithUser')(Self); - require('../methods/client/extendedListFilter')(Self); - require('../methods/client/getAverageInvoiced')(Self); - require('../methods/client/getCard')(Self); - require('../methods/client/getDebt')(Self); - require('../methods/client/getMana')(Self); - require('../methods/client/getTransactions')(Self); - require('../methods/client/hasCustomerRole')(Self); - require('../methods/client/isValidClient')(Self); - require('../methods/client/lastActiveTickets')(Self); - require('../methods/client/sendSms')(Self); - require('../methods/client/setPassword')(Self); - require('../methods/client/summary')(Self); - require('../methods/client/updateAddress')(Self); - require('../methods/client/updateFiscalData')(Self); - require('../methods/client/updatePortfolio')(Self); - require('../methods/client/updateUser')(Self); - require('../methods/client/uploadFile')(Self); + require('./client-methods')(Self); // Validations @@ -317,23 +291,22 @@ module.exports = Self => { const $t = httpRequest.__; const headers = httpRequest.headers; const origin = headers.origin; - const authorization = headers.authorization; const salesPersonId = instance.salesPersonFk; if (salesPersonId) { // Send email to client if (instance.email) { + const {Email} = require('vn-print'); const worker = await models.EmailUser.findById(salesPersonId); const params = { - authorization: authorization, + id: instance.id, recipientId: instance.id, recipient: instance.email, replyTo: worker.email }; - await got.get(`${origin}/api/email/payment-update`, { - searchParams: params - }); + const email = new Email('payment-update', params); + await email.send(); } const fullUrl = `${origin}/#!/client/${instance.id}/billing-data`; diff --git a/modules/client/back/models/sample.json b/modules/client/back/models/sample.json index cfb127ab2..011e8bf24 100644 --- a/modules/client/back/models/sample.json +++ b/modules/client/back/models/sample.json @@ -29,6 +29,9 @@ }, "datepickerEnabled": { "type": "boolean" + }, + "model": { + "type": "string" } }, "scopes": { 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/client/front/consumption/index.spec.js b/modules/client/front/consumption/index.spec.js index 16b764b56..33cbce58f 100644 --- a/modules/client/front/consumption/index.spec.js +++ b/modules/client/front/consumption/index.spec.js @@ -34,15 +34,16 @@ describe('Client', () => { controller.showReport(); + const clientId = controller.client.id; const expectedParams = { - recipientId: 1101, + recipientId: clientId, from: now, to: now }; const serializedParams = $httpParamSerializer(expectedParams); - const path = `api/report/campaign-metrics?${serializedParams}`; + const expectedPath = `api/Clients/${clientId}/campaign-metrics-pdf?${serializedParams}`; - expect(window.open).toHaveBeenCalledWith(path); + expect(window.open).toHaveBeenCalledWith(expectedPath); }); }); @@ -53,16 +54,10 @@ describe('Client', () => { from: now, to: now }; - const expectedParams = { - recipientId: 1101, - from: now, - to: now - }; + const clientId = controller.client.id; + const expectedPath = `Clients/${clientId}/campaign-metrics-email`; - const serializedParams = $httpParamSerializer(expectedParams); - const path = `email/campaign-metrics?${serializedParams}`; - - $httpBackend.expect('GET', path).respond({}); + $httpBackend.expect('POST', expectedPath).respond({}); controller.sendEmail(); $httpBackend.flush(); }); diff --git a/modules/client/front/notification/index.js b/modules/client/front/notification/index.js index 336005783..e70af12b2 100644 --- a/modules/client/front/notification/index.js +++ b/modules/client/front/notification/index.js @@ -77,11 +77,13 @@ export default class Controller extends Section { onSendClientConsumption() { const clientIds = this.checked.map(client => client.id); - const params = Object.assign({ - clientIds: clientIds - }, this.campaign); + const params = { + clients: clientIds, + from: this.campaign.from, + to: this.campaign.to + }; - this.$http.post('schedule/consumption', params) + this.$http.post('ClientConsumptionQueues', {params}) .then(() => this.$.filters.hide()) .then(() => this.vnApp.showSuccess(this.$t('Notifications sent!'))); } diff --git a/modules/client/front/notification/index.spec.js b/modules/client/front/notification/index.spec.js index 8847357f7..ea082c403 100644 --- a/modules/client/front/notification/index.spec.js +++ b/modules/client/front/notification/index.spec.js @@ -61,7 +61,6 @@ describe('Client notification', () => { controller.$.filters = {hide: () => {}}; controller.campaign = { - id: 1, from: new Date(), to: new Date() }; @@ -71,10 +70,10 @@ describe('Client notification', () => { data[1].$checked = true; const params = Object.assign({ - clientIds: [1101, 1102] + clients: [1101, 1102] }, controller.campaign); - $httpBackend.expect('POST', `schedule/consumption`, params).respond(200, params); + $httpBackend.expect('POST', `ClientConsumptionQueues`, {params}).respond(200, params); controller.onSendClientConsumption(); $httpBackend.flush(); diff --git a/modules/client/front/sample/create/index.html b/modules/client/front/sample/create/index.html index 2d0f3d29c..5df2b29ef 100644 --- a/modules/client/front/sample/create/index.html +++ b/modules/client/front/sample/create/index.html @@ -7,6 +7,15 @@ @@ -77,7 +86,7 @@ + ng-click="$ctrl.preview()"> - this.sendSample() - ); + + const validationMessage = this.validate(); + if (validationMessage) + return this.vnApp.showError(this.$t(validationMessage)); + + this.$.watcher.realSubmit().then(() => this.send()); } - showPreview() { - this.send(true, res => { - this.$.showPreview.show(); - const dialog = document.body.querySelector('div.vn-dialog'); - const body = dialog.querySelector('tpl-body'); - const scroll = dialog.querySelector('div:first-child'); - - body.innerHTML = res.data; - scroll.scrollTop = 0; - }); - } - - sendSample() { - this.send(false, () => { - this.vnApp.showSuccess(this.$t('Notification sent!')); - this.$state.go('client.card.sample.index'); - }); - } - - send(isPreview, cb) { + validate() { const sampleType = this.$.sampleType.selection; - const params = { - recipientId: this.$params.id, - recipient: this.clientSample.recipient, - replyTo: this.clientSample.replyTo - }; - if (!params.recipient) - return this.vnApp.showError(this.$t('Email cannot be blank')); + if (!this.clientSample.recipient) + return 'Email cannot be blank'; if (!sampleType) - return this.vnApp.showError(this.$t('Choose a sample')); + return 'Choose a sample'; if (sampleType.hasCompany && !this.clientSample.companyFk) - return this.vnApp.showError(this.$t('Choose a company')); + return 'Choose a company'; + + if (sampleType.datepickerEnabled && !this.clientSample.from) + return 'Choose a date'; + + return; + } + + setParams(params) { + const sampleType = this.$.sampleType.selection; if (sampleType.hasCompany) params.companyId = this.clientSample.companyFk; - if (sampleType.datepickerEnabled && !this.clientSample.from) - return this.vnApp.showError(this.$t('Choose a date')); - if (sampleType.datepickerEnabled) params.from = this.clientSample.from; + } - let query = `email/${sampleType.code}`; - if (isPreview) - query = `email/${sampleType.code}/preview`; + preview() { + const sampleType = this.$.sampleType.selection; - this.$http.get(query, {params}).then(cb); + const params = { + recipientId: this.$params.id + }; + + const validationMessage = this.validate(); + if (validationMessage) + return this.vnApp.showError(this.$t(validationMessage)); + + this.setParams(params); + + const path = `${sampleType.model}/${this.$params.id}/${sampleType.code}-html`; + this.$http.get(path, {params}) + .then(response => { + this.$.showPreview.show(); + const dialog = document.body.querySelector('div.vn-dialog'); + const body = dialog.querySelector('tpl-body'); + const scroll = dialog.querySelector('div:first-child'); + + body.innerHTML = response.data; + scroll.scrollTop = 0; + }); + } + + send() { + const sampleType = this.$.sampleType.selection; + + const params = { + recipientId: this.client.id, + recipient: this.clientSample.recipient, + replyTo: this.clientSample.replyTo + }; + + const validationMessage = this.validate(); + if (validationMessage) + return this.vnApp.showError(this.$t(validationMessage)); + + this.setParams(params); + + const path = `${sampleType.model}/${this.$params.id}/${sampleType.code}-email`; + this.vnEmail.send(path, params) + .then(() => this.$state.go('client.card.sample.index')); } getWorkerEmail() { @@ -103,7 +129,7 @@ class Controller extends Section { } } -Controller.$inject = ['$element', '$scope']; +Controller.$inject = ['$element', '$scope', 'vnEmail']; ngModule.vnComponent('vnClientSampleCreate', { template: require('./index.html'), diff --git a/modules/client/front/sample/create/index.spec.js b/modules/client/front/sample/create/index.spec.js index 781025fd2..8e33a1075 100644 --- a/modules/client/front/sample/create/index.spec.js +++ b/modules/client/front/sample/create/index.spec.js @@ -40,6 +40,7 @@ describe('Client', () => { $httpParamSerializer = _$httpParamSerializer_; $element = angular.element(''); controller = $componentController('vnClientSampleCreate', {$element, $scope}); + controller._client = {id: 1101}; const element = document.createElement('div'); document.body.querySelector = () => { return { @@ -48,14 +49,26 @@ describe('Client', () => { } }; }; + // $httpBackend.expectGET('EmailUsers?filter=%7B%22where%22:%7B%7D%7D').respond(); })); describe('onSubmit()', () => { - it(`should call sendSample() method`, () => { - jest.spyOn(controller, 'sendSample'); + it(`should call send() method`, () => { + controller.send = jest.fn(); + + controller.$.sampleType.selection = { + hasCompany: false, + code: 'MyReport', + model: 'Clients' + }; + + controller.clientSample = { + recipient: 'email@email' + }; + controller.onSubmit(); - expect(controller.sendSample).toHaveBeenCalledWith(); + expect(controller.send).toHaveBeenCalledWith(); }); }); @@ -65,13 +78,14 @@ describe('Client', () => { controller.$.sampleType.selection = { hasCompany: false, - code: 'MyReport' + code: 'MyReport', + model: 'Clients' }; controller.clientSample = { recipientId: 1101 }; - controller.send(false, () => {}); + controller.send(); expect(controller.$http.get).not.toHaveBeenCalled(); }); @@ -85,7 +99,7 @@ describe('Client', () => { recipient: 'client@email.com' }; - controller.send(false, () => {}); + controller.send(); expect(controller.$http.get).not.toHaveBeenCalled(); }); @@ -102,84 +116,81 @@ describe('Client', () => { recipient: 'client@email.com' }; - controller.send(false, () => {}); + controller.send(); expect(controller.$http.get).not.toHaveBeenCalled(); }); it(`should perform an HTTP query without passing companyFk param`, () => { + $state.go = jest.fn(); + controller.$.sampleType.selection = { hasCompany: false, - code: 'MyReport' + code: 'my-report', + model: 'Clients' }; controller.clientSample = { recipientId: 1101, recipient: 'client@email.com' }; - const expectedParams = { - recipientId: 1101, - recipient: 'client@email.com' - }; - const serializedParams = $httpParamSerializer(expectedParams); - $httpBackend.expect('GET', `email/MyReport?${serializedParams}`).respond(true); - controller.send(false, () => {}); + const expectedPath = `Clients/${controller.client.id}/my-report-email`; + $httpBackend.expect('POST', expectedPath).respond(true); + controller.send(); $httpBackend.flush(); }); it(`should perform an HTTP query passing companyFk param`, () => { + $state.go = jest.fn(); + controller.$.sampleType.selection = { hasCompany: true, - code: 'MyReport' + code: 'my-report', + model: 'Clients' }; controller.clientSample = { recipientId: 1101, recipient: 'client@email.com', companyFk: 442 }; - const expectedParams = { - recipientId: 1101, - recipient: 'client@email.com', - companyId: 442 - }; - const serializedParams = $httpParamSerializer(expectedParams); - $httpBackend.expect('GET', `email/MyReport?${serializedParams}`).respond(true); - controller.send(false, () => {}); + const expectedPath = `Clients/${controller.client.id}/my-report-email`; + $httpBackend.expect('POST', expectedPath).respond(true); + controller.send(); $httpBackend.flush(); }); }); - describe('showPreview()', () => { + describe('preview()', () => { it(`should open a sample preview`, () => { jest.spyOn(controller.$.showPreview, 'show'); - controller.send = (isPreview, cb) => { - cb({ - data: '
' - }); + controller.$.sampleType.selection = { + hasCompany: true, + code: 'my-report', + model: 'Clients' }; - controller.showPreview(); + controller.clientSample = { + recipientId: 1101, + recipient: 'client@email.com', + companyFk: 442 + }; + + const expectedParams = { + companyId: 442, + recipientId: 1101 + }; + const serializedParams = $httpParamSerializer(expectedParams); + + const expectedPath = `Clients/${controller.client.id}/my-report-html?${serializedParams}`; + $httpBackend.expect('GET', expectedPath).respond(true); + controller.preview(); + $httpBackend.flush(); expect(controller.$.showPreview.show).toHaveBeenCalledWith(); }); }); - describe('sendSample()', () => { - it(`should perform a query (GET) and call go() method`, () => { - jest.spyOn(controller.$state, 'go'); - - controller.send = (isPreview, cb) => { - cb({ - data: true - }); - }; - controller.sendSample(); - - expect(controller.$state.go).toHaveBeenCalledWith('client.card.sample.index'); - }); - }); - describe('getWorkerEmail()', () => { it(`should perform a query and then set the replyTo property to the clientSample object`, () => { const expectedEmail = 'batman@arkhamcity.com'; diff --git a/modules/entry/back/methods/entry/entryOrderPdf.js b/modules/entry/back/methods/entry/entryOrderPdf.js new file mode 100644 index 000000000..e6d37fdb6 --- /dev/null +++ b/modules/entry/back/methods/entry/entryOrderPdf.js @@ -0,0 +1,54 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('entryOrderPdf', { + description: 'Returns the entry order pdf', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + 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: '/:id/entry-order-pdf', + verb: 'GET' + } + }); + + Self.entryOrderPdf = 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('entry-order', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/entry/back/models/entry.js b/modules/entry/back/models/entry.js index 573e5b1cb..4854bc3d3 100644 --- a/modules/entry/back/models/entry.js +++ b/modules/entry/back/models/entry.js @@ -6,4 +6,5 @@ module.exports = Self => { require('../methods/entry/importBuys')(Self); require('../methods/entry/importBuysPreview')(Self); require('../methods/entry/lastItemBuys')(Self); + require('../methods/entry/entryOrderPdf')(Self); }; diff --git a/modules/entry/front/descriptor/index.js b/modules/entry/front/descriptor/index.js index 34aa162f9..3452a6d34 100644 --- a/modules/entry/front/descriptor/index.js +++ b/modules/entry/front/descriptor/index.js @@ -86,9 +86,7 @@ class Controller extends Descriptor { } showEntryReport() { - this.vnReport.show('entry-order', { - entryId: this.entry.id - }); + this.vnReport.show(`Entries/${this.id}/entry-order-pdf`); } } diff --git a/modules/entry/front/descriptor/index.spec.js b/modules/entry/front/descriptor/index.spec.js index 84defea3b..714bb9f3c 100644 --- a/modules/entry/front/descriptor/index.spec.js +++ b/modules/entry/front/descriptor/index.spec.js @@ -17,13 +17,10 @@ describe('Entry Component vnEntryDescriptor', () => { jest.spyOn(controller.vnReport, 'show'); window.open = jasmine.createSpy('open'); - const params = { - clientId: controller.vnConfig.storage.currentUserWorkerId, - entryId: entry.id - }; controller.showEntryReport(); + const expectedPath = `Entries/${entry.id}/entry-order-pdf`; - expect(controller.vnReport.show).toHaveBeenCalledWith('entry-order', params); + expect(controller.vnReport.show).toHaveBeenCalledWith(expectedPath); }); }); diff --git a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js index c2fdbcbba..3ab5f526c 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js @@ -1,7 +1,5 @@ const UserError = require('vn-loopback/util/user-error'); -const fs = require('fs-extra'); -const path = require('path'); -const axios = require('axios'); +const {Report, storage} = require('vn-print'); module.exports = Self => { Self.remoteMethodCtx('createPdf', { @@ -27,9 +25,7 @@ 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 auth = ctx.req.accessToken; + const userId = ctx.req.accessToken.userId; if (process.env.NODE_ENV == 'test') throw new UserError(`Action not allowed on the test environment`); @@ -45,10 +41,9 @@ module.exports = Self => { myOptions.transaction = tx; } - let fileSrc; try { const invoiceOut = await Self.findById(id, null, myOptions); - const hasInvoicing = await models.Account.hasRole(auth.userId, 'invoicing', myOptions); + const hasInvoicing = await models.Account.hasRole(userId, 'invoicing', myOptions); if (invoiceOut.hasPdf && !hasInvoicing) throw new UserError(`You don't have enough privileges`); @@ -57,35 +52,27 @@ module.exports = Self => { hasPdf: true }, myOptions); - return axios.get(`${origin}/api/report/invoice`, { - responseType: 'stream', - params: { - authorization: auth.id, - refFk: invoiceOut.ref - } - }).then(async response => { - const issued = invoiceOut.issued; - const year = issued.getFullYear().toString(); - const month = (issued.getMonth() + 1).toString(); - const day = issued.getDate().toString(); - - const container = await models.InvoiceContainer.container(year); - const rootPath = container.client.root; - const fileName = `${year}${invoiceOut.ref}.pdf`; - const src = path.join(rootPath, year, month, day); - fileSrc = path.join(src, fileName); - - await fs.mkdir(src, {recursive: true}); - - if (tx) await tx.commit(); - - response.data.pipe(fs.createWriteStream(fileSrc)); - }).catch(async e => { - if (fs.existsSync(fileSrc)) - await fs.unlink(fileSrc); - - throw e; + const invoiceReport = new Report('invoice', { + reference: invoiceOut.ref, + recipientId: invoiceOut.clientFk }); + const stream = await invoiceReport.toPdfStream(); + + const issued = invoiceOut.issued; + const year = issued.getFullYear().toString(); + const month = (issued.getMonth() + 1).toString(); + const day = issued.getDate().toString(); + + const fileName = `${year}${invoiceOut.ref}.pdf`; + + // Store invoice + storage.write(stream, { + type: 'invoice', + path: `${year}/${month}/${day}`, + fileName: fileName + }); + + if (tx) await tx.commit(); } catch (e) { if (tx) await tx.rollback(); throw e; diff --git a/modules/invoiceOut/back/methods/invoiceOut/exportationPdf.js b/modules/invoiceOut/back/methods/invoiceOut/exportationPdf.js new file mode 100644 index 000000000..e947c5144 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/exportationPdf.js @@ -0,0 +1,55 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('exportationPdf', { + description: 'Returns the exportation pdf', + accessType: 'READ', + accepts: [ + { + arg: 'reference', + type: 'string', + required: true, + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + 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: '/:reference/exportation-pdf', + verb: 'GET' + } + }); + + Self.exportationPdf = async(ctx, reference) => { + 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('exportation', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${reference}.pdf"`]; + }; +}; diff --git a/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js b/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js index 7f2cbb442..2aa277b6f 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js +++ b/modules/invoiceOut/back/methods/invoiceOut/globalInvoicing.js @@ -138,7 +138,7 @@ module.exports = Self => { if (newInvoice.id) { await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions); - query = `INSERT IGNORE INTO invoiceOut_queue(invoiceFk) VALUES(?)`; + query = `INSERT IGNORE INTO invoiceOutQueue(invoiceFk) VALUES(?)`; await Self.rawSql(query, [newInvoice.id], myOptions); invoicesIds.push(newInvoice.id); diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceCsv.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceCsv.js new file mode 100644 index 000000000..d33df74a2 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceCsv.js @@ -0,0 +1,85 @@ +const {toCSV} = require('vn-loopback/util/csv'); + +module.exports = Self => { + Self.remoteMethod('invoiceCsv', { + description: 'Returns the delivery note csv', + accessType: 'READ', + accepts: [ + { + arg: 'reference', + type: 'string', + required: true, + description: 'The invoice reference', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The client id', + 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: '/:reference/invoice-csv', + verb: 'GET' + } + }); + + Self.invoiceCsv = async reference => { + const sales = await Self.rawSql(` + SELECT io.ref Invoice, + io.issued InvoiceDate, + s.ticketFk Ticket, + s.itemFk Item, + s.concept Description, + i.size, + i.subName Producer, + s.quantity Quantity, + s.price Price, + s.discount Discount, + s.created Created, + tc.code Taxcode, + tc.description TaxDescription, + i.tag5, + i.value5, + i.tag6, + i.value6, + i.tag7, + i.value7, + i.tag8, + i.value8, + i.tag9, + i.value9, + i.tag10, + i.value10 + FROM sale s + JOIN ticket t ON t.id = s.ticketFk + JOIN item i ON i.id = s.itemFk + JOIN supplier s2 ON s2.id = t.companyFk + JOIN itemTaxCountry itc ON itc.itemFk = i.id + AND itc.countryFk = s2.countryFk + JOIN taxClass tc ON tc.id = itc.taxClassFk + JOIN invoiceOut io ON io.ref = t.refFk + WHERE t.refFk = ? + ORDER BY s.ticketFk, s.created`, [reference]); + + const content = toCSV(sales); + + return [content, 'text/csv', `inline; filename="doc-${reference}.pdf"`]; + }; +}; diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceCsvEmail.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceCsvEmail.js new file mode 100644 index 000000000..38d451595 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceCsvEmail.js @@ -0,0 +1,117 @@ +const {Email} = require('vn-print'); +const {toCSV} = require('vn-loopback/util/csv'); + +module.exports = Self => { + Self.remoteMethodCtx('invoiceCsvEmail', { + description: 'Returns the delivery note csv', + accessType: 'READ', + accepts: [ + { + arg: 'reference', + type: 'string', + required: true, + description: 'The invoice reference', + 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 client id', + 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: '/:reference/invoice-csv-email', + verb: 'POST' + } + }); + + Self.invoiceCsvEmail = async(ctx, reference) => { + 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 sales = await Self.rawSql(` + SELECT io.ref Invoice, + io.issued InvoiceDate, + s.ticketFk Ticket, + s.itemFk Item, + s.concept Description, + i.size, + i.subName Producer, + s.quantity Quantity, + s.price Price, + s.discount Discount, + s.created Created, + tc.code Taxcode, + tc.description TaxDescription, + i.tag5, + i.value5, + i.tag6, + i.value6, + i.tag7, + i.value7, + i.tag8, + i.value8, + i.tag9, + i.value9, + i.tag10, + i.value10 + FROM sale s + JOIN ticket t ON t.id = s.ticketFk + JOIN item i ON i.id = s.itemFk + JOIN supplier s2 ON s2.id = t.companyFk + JOIN itemTaxCountry itc ON itc.itemFk = i.id + AND itc.countryFk = s2.countryFk + JOIN taxClass tc ON tc.id = itc.taxClassFk + JOIN invoiceOut io ON io.ref = t.refFk + WHERE t.refFk = ? + ORDER BY s.ticketFk, s.created`, [reference]); + + const content = toCSV(sales); + const fileName = `invoice_${reference}.csv`; + const email = new Email('invoice', params); + + return email.send({ + overrideAttachments: true, + attachments: [{ + filename: fileName, + content: content + }] + }); + }; +}; diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js new file mode 100644 index 000000000..83564e3ab --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceEmail.js @@ -0,0 +1,58 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('invoiceEmail', { + description: 'Sends the invoice email with an attached PDF', + accessType: 'WRITE', + accepts: [ + { + arg: 'reference', + type: 'string', + required: true, + 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 + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:reference/invoice-email', + verb: 'POST' + } + }); + + Self.invoiceEmail = async ctx => { + 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('invoice', params); + + return email.send(); + }; +}; diff --git a/print/methods/schedule/invoice.js b/modules/invoiceOut/back/methods/invoiceOut/sendQueued.js similarity index 69% rename from print/methods/schedule/invoice.js rename to modules/invoiceOut/back/methods/invoiceOut/sendQueued.js index 87c696075..a1730ac81 100644 --- a/print/methods/schedule/invoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/sendQueued.js @@ -1,15 +1,22 @@ -const db = require('vn-print/core/database'); -const Email = require('vn-print/core/email'); -const Report = require('vn-print/core/report'); -const storage = require('vn-print/core/storage'); +const {Email, Report, storage} = require('vn-print'); -module.exports = async function(request, response, next) { - try { - response.status(200).json({ - message: 'Success' - }); +module.exports = Self => { + Self.remoteMethod('sendQueued', { + description: 'Send all queued invoices', + accessType: 'WRITE', + accepts: [], + returns: { + type: 'object', + root: true + }, + http: { + path: '/send-queued', + verb: 'POST' + } + }); - const invoices = await db.rawSql(` + Self.sendQueued = async() => { + const invoices = await Self.rawSql(` SELECT io.id, io.clientFk, @@ -21,7 +28,7 @@ module.exports = async function(request, response, next) { c.hasToInvoice, co.hasDailyInvoice, eu.email salesPersonEmail - FROM invoiceOut_queue ioq + FROM invoiceOutQueue ioq JOIN invoiceOut io ON io.id = ioq.invoiceFk JOIN client c ON c.id = io.clientFk JOIN province p ON p.id = c.provinceFk @@ -29,20 +36,20 @@ module.exports = async function(request, response, next) { LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk WHERE status = ''`); - let connection; let invoiceId; for (const invoiceOut of invoices) { try { - invoiceId = invoiceOut.id; - connection = await db.getConnection(); - connection.query('START TRANSACTION'); + const tx = await Self.beginTransaction({}); + const myOptions = {transaction: tx}; - const args = Object.assign({ - refFk: invoiceOut.ref, + invoiceId = invoiceOut.id; + + const args = { + reference: invoiceOut.ref, recipientId: invoiceOut.clientFk, recipient: invoiceOut.recipient, replyTo: invoiceOut.salesPersonEmail - }, response.locals); + }; const invoiceReport = new Report('invoice', args); const stream = await invoiceReport.toPdfStream(); @@ -61,7 +68,11 @@ module.exports = async function(request, response, next) { fileName: fileName }); - connection.query('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id]); + await Self.rawSql(` + UPDATE invoiceOut + SET hasPdf = true + WHERE id = ?`, + [invoiceOut.id], myOptions); const isToBeMailed = invoiceOut.recipient && invoiceOut.salesPersonFk && invoiceOut.isToBeMailed; @@ -94,22 +105,29 @@ module.exports = async function(request, response, next) { } // Update queue status const date = new Date(); - sql = `UPDATE invoiceOut_queue + await Self.rawSql(` + UPDATE invoiceOutQueue SET status = "printed", printed = ? - WHERE invoiceFk = ?`; - connection.query(sql, [date, invoiceOut.id]); - connection.query('COMMIT'); + WHERE invoiceFk = ?`, + [date, invoiceOut.id], myOptions); + + await tx.commit(); } catch (error) { - connection.query('ROLLBACK'); - connection.release(); - sql = `UPDATE invoiceOut_queue + await tx.rollback(); + + await Self.rawSql(` + UPDATE invoiceOutQueue SET status = ? - WHERE invoiceFk = ?`; - await db.rawSql(sql, [error.message, invoiceId]); + WHERE invoiceFk = ?`, + [error.message, invoiceId]); + + throw e; } } - } catch (error) { - next(error); - } + + return { + message: 'Success' + }; + }; }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/globalInvoicing.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/globalInvoicing.spec.js index e0ed6c91c..f7546b72e 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/globalInvoicing.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/globalInvoicing.spec.js @@ -8,6 +8,9 @@ describe('InvoiceOut globalInvoicing()', () => { const invoiceSerial = 'A'; const activeCtx = { accessToken: {userId: userId}, + __: value => { + return value; + } }; const ctx = {req: activeCtx}; @@ -22,7 +25,7 @@ describe('InvoiceOut globalInvoicing()', () => { invoiceDate: new Date(), maxShipped: new Date(), fromClientId: clientId, - toClientId: clientId, + toClientId: 1106, companyFk: companyFk }; const result = await models.InvoiceOut.globalInvoicing(ctx, options); diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index c8c97702f..5af64de2b 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -9,4 +9,9 @@ module.exports = Self => { require('../methods/invoiceOut/createManualInvoice')(Self); require('../methods/invoiceOut/globalInvoicing')(Self); require('../methods/invoiceOut/refund')(Self); + require('../methods/invoiceOut/invoiceEmail')(Self); + require('../methods/invoiceOut/exportationPdf')(Self); + require('../methods/invoiceOut/sendQueued')(Self); + require('../methods/invoiceOut/invoiceCsv')(Self); + require('../methods/invoiceOut/invoiceCsvEmail')(Self); }; diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js index 2b6d90ebf..456939119 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.js +++ b/modules/invoiceOut/front/descriptor-menu/index.js @@ -81,21 +81,19 @@ class Controller extends Section { }); } - showCsvInvoice() { - this.vnReport.showCsv('invoice', { - recipientId: this.invoiceOut.client.id, - refFk: this.invoiceOut.ref - }); - } - sendPdfInvoice($data) { if (!$data.email) return this.vnApp.showError(this.$t(`The email can't be empty`)); - return this.vnEmail.send('invoice', { + return this.vnEmail.send(`InvoiceOuts/${this.invoiceOut.ref}/invoice-email`, { recipientId: this.invoiceOut.client.id, - recipient: $data.email, - refFk: this.invoiceOut.ref + recipient: $data.email + }); + } + + showCsvInvoice() { + this.vnReport.show(`InvoiceOuts/${this.invoiceOut.ref}/invoice-csv`, { + recipientId: this.invoiceOut.client.id }); } @@ -103,15 +101,14 @@ class Controller extends Section { if (!$data.email) return this.vnApp.showError(this.$t(`The email can't be empty`)); - return this.vnEmail.sendCsv('invoice', { + return this.vnEmail.send(`InvoiceOuts/${this.invoiceOut.ref}/invoice-csv-email`, { recipientId: this.invoiceOut.client.id, - recipient: $data.email, - refFk: this.invoiceOut.ref + recipient: $data.email }); } showExportationLetter() { - this.vnReport.show('exportation', { + this.vnReport.show(`InvoiceOuts/${this.invoiceOut.ref}/exportation-pdf`, { recipientId: this.invoiceOut.client.id, refFk: this.invoiceOut.ref }); diff --git a/modules/invoiceOut/front/descriptor-menu/index.spec.js b/modules/invoiceOut/front/descriptor-menu/index.spec.js index da7c87894..d2ccfa117 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.spec.js +++ b/modules/invoiceOut/front/descriptor-menu/index.spec.js @@ -41,11 +41,10 @@ describe('vnInvoiceOutDescriptorMenu', () => { jest.spyOn(window, 'open').mockReturnThis(); const expectedParams = { - recipientId: invoiceOut.client.id, - refFk: invoiceOut.ref + recipientId: invoiceOut.client.id }; const serializedParams = $httpParamSerializer(expectedParams); - const expectedPath = `api/csv/invoice/download?${serializedParams}`; + const expectedPath = `api/InvoiceOuts/${invoiceOut.ref}/invoice-csv?${serializedParams}`; controller.showCsvInvoice(); expect(window.open).toHaveBeenCalledWith(expectedPath); @@ -84,14 +83,8 @@ describe('vnInvoiceOutDescriptorMenu', () => { jest.spyOn(controller.vnApp, 'showMessage'); const $data = {email: 'brucebanner@gothamcity.com'}; - const expectedParams = { - recipient: $data.email, - recipientId: invoiceOut.client.id, - refFk: invoiceOut.ref - }; - const serializedParams = $httpParamSerializer(expectedParams); - $httpBackend.expectGET(`email/invoice?${serializedParams}`).respond(); + $httpBackend.expectPOST(`InvoiceOuts/${invoiceOut.ref}/invoice-email`).respond(); controller.sendPdfInvoice($data); $httpBackend.flush(); @@ -104,14 +97,8 @@ describe('vnInvoiceOutDescriptorMenu', () => { jest.spyOn(controller.vnApp, 'showMessage'); const $data = {email: 'brucebanner@gothamcity.com'}; - const expectedParams = { - recipient: $data.email, - recipientId: invoiceOut.client.id, - refFk: invoiceOut.ref - }; - const serializedParams = $httpParamSerializer(expectedParams); - $httpBackend.expectGET(`csv/invoice/send?${serializedParams}`).respond(); + $httpBackend.expectPOST(`InvoiceOuts/${invoiceOut.ref}/invoice-csv-email`).respond(); controller.sendCsvInvoice($data); $httpBackend.flush(); diff --git a/modules/item/back/methods/item/buyerWasteEmail.js b/modules/item/back/methods/item/buyerWasteEmail.js new file mode 100644 index 000000000..7f340de0f --- /dev/null +++ b/modules/item/back/methods/item/buyerWasteEmail.js @@ -0,0 +1,29 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('buyerWasteEmail', { + description: 'Sends the buyer waste email', + accessType: 'WRITE', + accepts: [], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/buyer-waste-email', + verb: 'POST' + } + }); + + Self.buyerWasteEmail = async ctx => { + const models = Self.app.models; + const itemConfig = await models.ItemConfig.findOne(); + + const email = new Email('buyer-week-waste', { + recipient: itemConfig.wasteRecipients, + lang: ctx.req.getLocale() + }); + + return email.send(); + }; +}; diff --git a/modules/item/back/methods/item/labelPdf.js b/modules/item/back/methods/item/labelPdf.js new file mode 100644 index 000000000..747869b37 --- /dev/null +++ b/modules/item/back/methods/item/labelPdf.js @@ -0,0 +1,72 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('labelPdf', { + description: 'Returns the item label pdf', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The item id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + required: false + }, + { + arg: 'warehouseId', + type: 'number', + description: 'The warehouse id', + required: true + }, + { + arg: 'labelNumber', + type: 'number', + required: false + }, + { + arg: 'totalLabels', + type: 'number', + 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: '/:id/label-pdf', + verb: 'GET' + } + }); + + Self.labelPdf = 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('item-label', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="item-${id}.pdf"`]; + }; +}; diff --git a/modules/item/back/model-config.json b/modules/item/back/model-config.json index c31f472be..9737d26fc 100644 --- a/modules/item/back/model-config.json +++ b/modules/item/back/model-config.json @@ -23,6 +23,9 @@ "ItemCategory": { "dataSource": "vn" }, + "ItemConfig": { + "dataSource": "vn" + }, "ItemFamily": { "dataSource": "vn" }, diff --git a/modules/item/back/models/item-config.json b/modules/item/back/models/item-config.json new file mode 100644 index 000000000..364879986 --- /dev/null +++ b/modules/item/back/models/item-config.json @@ -0,0 +1,21 @@ +{ + "name": "ItemConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "itemConfig" + } + }, + "properties": { + "isItemTagTriggerDisabled": { + "type": "boolean" + }, + "monthToDeactivate": { + "type": "boolean" + }, + "wasteRecipients": { + "type": "string", + "description": "Buyers waste report recipients" + } + } +} \ No newline at end of file diff --git a/modules/item/back/models/item.js b/modules/item/back/models/item.js index 457cce4f2..b8baa97ea 100644 --- a/modules/item/back/models/item.js +++ b/modules/item/back/models/item.js @@ -15,6 +15,8 @@ module.exports = Self => { require('../methods/item/getWasteByItem')(Self); require('../methods/item/createIntrastat')(Self); require('../methods/item/activeBuyers')(Self); + require('../methods/item/buyerWasteEmail')(Self); + require('../methods/item/labelPdf')(Self); Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'}); diff --git a/modules/item/front/index/style.scss b/modules/item/front/index/style.scss index eaa1a16ed..e9fd9f935 100644 --- a/modules/item/front/index/style.scss +++ b/modules/item/front/index/style.scss @@ -23,10 +23,12 @@ vn-item-product { } } -table { - img { - border-radius: 50%; - width: 50px; - height: 50px; +vn-item-index { + table { + img { + border-radius: 50%; + width: 50px; + height: 50px; + } } } \ No newline at end of file diff --git a/modules/route/back/methods/route/driverRouteEmail.js b/modules/route/back/methods/route/driverRouteEmail.js new file mode 100644 index 000000000..81d770360 --- /dev/null +++ b/modules/route/back/methods/route/driverRouteEmail.js @@ -0,0 +1,58 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('driverRouteEmail', { + description: 'Sends the driver route 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 + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/driver-route-email', + verb: 'POST' + } + }); + + Self.driverRouteEmail = async ctx => { + 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('driver-route', params); + + return email.send(); + }; +}; diff --git a/modules/route/back/methods/route/driverRoutePdf.js b/modules/route/back/methods/route/driverRoutePdf.js new file mode 100644 index 000000000..161eb71af --- /dev/null +++ b/modules/route/back/methods/route/driverRoutePdf.js @@ -0,0 +1,55 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('driverRoutePdf', { + description: 'Returns the driver route 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 + } + ], + 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/driver-route-pdf', + verb: 'GET' + } + }); + + Self.driverRoutePdf = 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('driver-route', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 4050e62fe..f5406728a 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -10,6 +10,8 @@ module.exports = Self => { require('../methods/route/getSuggestedTickets')(Self); require('../methods/route/unlink')(Self); require('../methods/route/updateWorkCenter')(Self); + require('../methods/route/driverRoutePdf')(Self); + require('../methods/route/driverRouteEmail')(Self); Self.validate('kmStart', validateDistance, { message: 'Distance must be lesser than 1000' diff --git a/modules/route/front/agency-term/index/index.js b/modules/route/front/agency-term/index/index.js index f73095e7a..6c3bafc9a 100644 --- a/modules/route/front/agency-term/index/index.js +++ b/modules/route/front/agency-term/index/index.js @@ -1,6 +1,5 @@ import ngModule from '../../module'; import Section from 'salix/components/section'; -import './style.scss'; class Controller extends Section { constructor($element, $) { diff --git a/modules/route/front/agency-term/index/style.scss b/modules/route/front/agency-term/index/style.scss deleted file mode 100644 index eaa1a16ed..000000000 --- a/modules/route/front/agency-term/index/style.scss +++ /dev/null @@ -1,32 +0,0 @@ -@import "variables"; - -vn-item-product { - display: block; - - .id { - background-color: $color-main; - color: $color-font-dark; - margin-bottom: 0; - } - .image { - height: 112px; - width: 112px; - - & > img { - max-height: 100%; - max-width: 100%; - border-radius: 3px; - } - } - vn-label-value:first-of-type section{ - margin-top: 9px; - } -} - -table { - img { - border-radius: 50%; - width: 50px; - height: 50px; - } -} \ No newline at end of file diff --git a/modules/route/front/descriptor/index.js b/modules/route/front/descriptor/index.js index 32411aa58..0573201bf 100644 --- a/modules/route/front/descriptor/index.js +++ b/modules/route/front/descriptor/index.js @@ -11,16 +11,16 @@ class Controller extends Descriptor { } showRouteReport() { - this.vnReport.show('driver-route', { - routeId: this.id + this.vnReport.show(`Routes/${this.id}/driver-route-pdf`, { + id: this.id }); } sendRouteReport() { const workerUser = this.route.worker.user; - this.vnEmail.send('driver-route', { + this.vnEmail.send(`Routes/${this.id}/driver-route-email`, { recipient: workerUser.emailUser.email, - routeId: this.id + id: this.id }); } diff --git a/modules/supplier/back/methods/supplier/campaignMetricsEmail.js b/modules/supplier/back/methods/supplier/campaignMetricsEmail.js new file mode 100644 index 000000000..4a2c843b8 --- /dev/null +++ b/modules/supplier/back/methods/supplier/campaignMetricsEmail.js @@ -0,0 +1,68 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('campaignMetricsEmail', { + description: 'Sends the campaign metrics email with an attached PDF', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + 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 => { + 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('supplier-campaign-metrics', params); + + return email.send(); + }; +}; diff --git a/modules/supplier/back/methods/supplier/campaignMetricsPdf.js b/modules/supplier/back/methods/supplier/campaignMetricsPdf.js new file mode 100644 index 000000000..7bd65ffcb --- /dev/null +++ b/modules/supplier/back/methods/supplier/campaignMetricsPdf.js @@ -0,0 +1,65 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('campaignMetricsPdf', { + description: 'Returns the campaign metrics pdf', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + 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('supplier-campaign-metrics', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js index c1be3488f..c9af7b297 100644 --- a/modules/supplier/back/models/supplier.js +++ b/modules/supplier/back/models/supplier.js @@ -8,6 +8,8 @@ module.exports = Self => { require('../methods/supplier/updateFiscalData')(Self); require('../methods/supplier/consumption')(Self); require('../methods/supplier/freeAgencies')(Self); + require('../methods/supplier/campaignMetricsPdf')(Self); + require('../methods/supplier/campaignMetricsEmail')(Self); Self.validatesPresenceOf('name', { message: 'The social name cannot be empty' diff --git a/modules/supplier/front/consumption/index.js b/modules/supplier/front/consumption/index.js index 21a30929d..8de6a1e71 100644 --- a/modules/supplier/front/consumption/index.js +++ b/modules/supplier/front/consumption/index.js @@ -33,7 +33,8 @@ class Controller extends Section { } showReport() { - this.vnReport.show('supplier-campaign-metrics', this.reportParams); + const path = `Suppliers/${this.supplier.id}/campaign-metrics-pdf`; + this.vnReport.show(path, this.reportParams); } sendEmail() { @@ -52,7 +53,9 @@ class Controller extends Section { const params = Object.assign({ recipient: contact.email }, this.reportParams); - this.vnEmail.send('supplier-campaign-metrics', params); + + const path = `Suppliers/${this.supplier.id}/campaign-metrics-email`; + this.vnEmail.send(path, params); } else { const message = this.$t(`This supplier doesn't have a contact with an email address`); this.vnApp.showError(message); diff --git a/modules/supplier/front/consumption/index.spec.js b/modules/supplier/front/consumption/index.spec.js index d095a174b..ebf19ccec 100644 --- a/modules/supplier/front/consumption/index.spec.js +++ b/modules/supplier/front/consumption/index.spec.js @@ -42,7 +42,7 @@ describe('Supplier', () => { to: now }; const serializedParams = $httpParamSerializer(expectedParams); - const path = `api/report/supplier-campaign-metrics?${serializedParams}`; + const path = `api/Suppliers/${supplierId}/campaign-metrics-pdf?${serializedParams}`; expect(window.open).toHaveBeenCalledWith(path); }); @@ -66,7 +66,8 @@ describe('Supplier', () => { controller.sendEmail(); $httpBackend.flush(); - expect(controller.vnApp.showError).toHaveBeenCalledWith(`This supplier doesn't have a contact with an email address`); + expect(controller.vnApp.showError) + .toHaveBeenCalledWith(`This supplier doesn't have a contact with an email address`); }); it('should make a GET query sending the report', () => { @@ -91,16 +92,15 @@ describe('Supplier', () => { to: now }; const expectedParams = { - recipientId: 2, recipient: 'batman@gothamcity.com', from: now, to: now }; serializedParams = $httpParamSerializer(expectedParams); - const path = `email/supplier-campaign-metrics?${serializedParams}`; + const path = `Suppliers/${supplierId}/campaign-metrics-email`; - $httpBackend.expect('GET', path).respond({}); + $httpBackend.expect('POST', path).respond({}); controller.sendEmail(); $httpBackend.flush(); }); diff --git a/modules/ticket/back/methods/expedition/specs/filter.spec.js b/modules/ticket/back/methods/expedition/specs/filter.spec.js index 85e98da4a..f643462cc 100644 --- a/modules/ticket/back/methods/expedition/specs/filter.spec.js +++ b/modules/ticket/back/methods/expedition/specs/filter.spec.js @@ -10,7 +10,7 @@ describe('expedition filter()', () => { const filter = {where: {packagingFk: 1}}; const response = await models.Expedition.filter(filter, options); - expect(response.length).toEqual(10); + expect(response.length).toBeGreaterThan(1); await tx.rollback(); } catch (e) { diff --git a/print/methods/closure/closeAll.js b/modules/ticket/back/methods/ticket/closeAll.js similarity index 71% rename from print/methods/closure/closeAll.js rename to modules/ticket/back/methods/ticket/closeAll.js index 36b853052..4f3813eb8 100644 --- a/print/methods/closure/closeAll.js +++ b/modules/ticket/back/methods/ticket/closeAll.js @@ -1,28 +1,36 @@ -const db = require('vn-print/core/database'); +const UserError = require('vn-loopback/util/user-error'); const closure = require('./closure'); -module.exports = async function(request, response, next) { - try { - const reqArgs = request.body; +module.exports = Self => { + Self.remoteMethod('closeAll', { + description: 'Makes the closure process from all warehouses', + accessType: 'WRITE', + accepts: [], + returns: { + type: 'object', + root: true + }, + http: { + path: `/close-all`, + verb: 'POST' + } + }); - let toDate = new Date(); + Self.closeAll = async() => { + const toDate = new Date(); toDate.setDate(toDate.getDate() - 1); - if (reqArgs.to) toDate = reqArgs.to; - const todayMinDate = new Date(); todayMinDate.setHours(0, 0, 0, 0); const todayMaxDate = new Date(); - todayMinDate.setHours(23, 59, 59, 59); + todayMaxDate.setHours(23, 59, 59, 59); // Prevent closure for current day if (toDate >= todayMinDate && toDate <= todayMaxDate) - throw new Error('You cannot close tickets for today'); + throw new UserError('You cannot close tickets for today'); - console.log(`Making closure up to ${toDate}...`); - - const tickets = await db.rawSql(` + const tickets = await Self.rawSql(` SELECT t.id, t.clientFk, @@ -47,11 +55,12 @@ module.exports = async function(request, response, next) { AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) AND util.dayEnd(?) AND t.refFk IS NULL - GROUP BY t.id`, [toDate, toDate]); + GROUP BY t.id + `, [toDate, toDate]); - await closure.start(tickets, response.locals); + await closure(Self, tickets); - await db.rawSql(` + await Self.rawSql(` UPDATE ticket t JOIN ticketState ts ON t.id = ts.ticketFk JOIN alertLevel al ON al.id = ts.alertLevel @@ -65,10 +74,8 @@ module.exports = async function(request, response, next) { AND t.routeFk AND z.name LIKE '%MADRID%'`, [toDate, toDate]); - response.status(200).json({ + return { message: 'Success' - }); - } catch (error) { - next(error); - } + }; + }; }; diff --git a/modules/ticket/back/methods/ticket/closeByAgency.js b/modules/ticket/back/methods/ticket/closeByAgency.js new file mode 100644 index 000000000..eb1aee349 --- /dev/null +++ b/modules/ticket/back/methods/ticket/closeByAgency.js @@ -0,0 +1,79 @@ +const closure = require('./closure'); + +module.exports = Self => { + Self.remoteMethodCtx('closeByAgency', { + description: 'Makes the closure process by agency mode', + accessType: 'WRITE', + accepts: [ + { + arg: 'agencyModeFk', + type: ['number'], + required: true, + description: 'The agencies mode ids', + }, + { + arg: 'warehouseFk', + type: 'number', + description: 'The ticket warehouse id', + required: true + }, + { + arg: 'to', + type: 'date', + description: 'Max closure date', + required: true + } + ], + returns: { + type: 'object', + root: true + }, + http: { + path: `/close-by-agency`, + verb: 'POST' + } + }); + + Self.closeByAgency = async ctx => { + const args = ctx.args; + + const tickets = await Self.rawSql(` + SELECT + t.id, + t.clientFk, + t.companyFk, + c.name clientName, + c.email recipient, + c.salesPersonFk, + c.isToBeMailed, + c.hasToInvoice, + co.hasDailyInvoice, + eu.email salesPersonEmail + FROM expedition e + JOIN ticket t ON t.id = e.ticketFk + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN alertLevel al ON al.id = ts.alertLevel + JOIN client c ON c.id = t.clientFk + JOIN province p ON p.id = c.provinceFk + JOIN country co ON co.id = p.countryFk + LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk + WHERE al.code = 'PACKED' + AND t.agencyModeFk IN(?) + AND t.warehouseFk = ? + AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) + AND util.dayEnd(?) + AND t.refFk IS NULL + GROUP BY e.ticketFk`, [ + args.agencyModeFk, + args.warehouseFk, + args.to, + args.to + ]); + + await closure(Self, tickets); + + return { + message: 'Success' + }; + }; +}; diff --git a/print/methods/closure/closeByRoute.js b/modules/ticket/back/methods/ticket/closeByRoute.js similarity index 55% rename from print/methods/closure/closeByRoute.js rename to modules/ticket/back/methods/ticket/closeByRoute.js index 1f5d571f6..58e130b8e 100644 --- a/print/methods/closure/closeByRoute.js +++ b/modules/ticket/back/methods/ticket/closeByRoute.js @@ -1,15 +1,32 @@ -const db = require('vn-print/core/database'); -const Email = require('vn-print/core/email'); const closure = require('./closure'); +const {Email} = require('vn-print'); -module.exports = async function(request, response, next) { - try { - const reqArgs = request.body; +module.exports = Self => { + Self.remoteMethodCtx('closeByRoute', { + description: 'Makes the closure process by route', + accessType: 'WRITE', + accepts: [ + { + arg: 'routeFk', + type: 'number', + required: true, + description: 'The routes ids', + }, + ], + returns: { + type: 'object', + root: true + }, + http: { + path: `/close-by-route`, + verb: 'POST' + } + }); - if (!reqArgs.routeId) - throw new Error('The argument routeId is required'); + Self.closeByRoute = async ctx => { + const args = ctx.args; - const tickets = await db.rawSql(` + const tickets = await Self.rawSql(` SELECT t.id, t.clientFk, @@ -32,31 +49,27 @@ module.exports = async function(request, response, next) { WHERE al.code = 'PACKED' AND t.routeFk = ? AND t.refFk IS NULL - GROUP BY e.ticketFk`, [reqArgs.routeId]); + GROUP BY e.ticketFk`, [args.routeFk]); - await closure.start(tickets, response.locals); + await closure(Self, tickets); // Send route report to the agency - const agencyMail = await db.findValue(` + const [agencyMail] = await Self.rawSql(` SELECT am.reportMail FROM route r JOIN agencyMode am ON am.id = r.agencyModeFk - WHERE r.id = ?`, [reqArgs.routeId]); + WHERE r.id = ?`, [args.routeFk]); if (agencyMail) { - const args = Object.assign({ - routeId: Number.parseInt(reqArgs.routeId), + const email = new Email('driver-route', { + id: args.routeFk, recipient: agencyMail - }, response.locals); - - const email = new Email('driver-route', args); + }); await email.send(); } - response.status(200).json({ + return { message: 'Success' - }); - } catch (error) { - next(error); - } + }; + }; }; diff --git a/print/methods/closure/closeByTicket.js b/modules/ticket/back/methods/ticket/closeByTicket.js similarity index 54% rename from print/methods/closure/closeByTicket.js rename to modules/ticket/back/methods/ticket/closeByTicket.js index 71cadcecf..8884897c2 100644 --- a/print/methods/closure/closeByTicket.js +++ b/modules/ticket/back/methods/ticket/closeByTicket.js @@ -1,14 +1,32 @@ -const db = require('vn-print/core/database'); const closure = require('./closure'); -module.exports = async function(request, response, next) { - try { - const reqArgs = request.body; +module.exports = Self => { + Self.remoteMethodCtx('closeByTicket', { + description: 'Makes the closure process by ticket', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The ticket id', + http: {source: 'path'} + } + ], + returns: { + type: 'object', + root: true + }, + http: { + path: `/:id/close-by-ticket`, + verb: 'POST' + } + }); - if (!reqArgs.ticketId) - throw new Error('The argument ticketId is required'); + Self.closeByTicket = async ctx => { + const args = ctx.args; - const tickets = await db.rawSql(` + const tickets = await Self.rawSql(` SELECT t.id, t.clientFk, @@ -31,14 +49,12 @@ module.exports = async function(request, response, next) { WHERE al.code = 'PACKED' AND t.id = ? AND t.refFk IS NULL - GROUP BY e.ticketFk`, [reqArgs.ticketId]); + GROUP BY e.ticketFk`, [args.id]); - await closure.start(tickets, response.locals); + await closure(Self, tickets); - response.status(200).json({ + return { message: 'Success' - }); - } catch (error) { - next(error); - } + }; + }; }; diff --git a/modules/ticket/back/methods/ticket/closure.js b/modules/ticket/back/methods/ticket/closure.js new file mode 100644 index 000000000..3cbc85f96 --- /dev/null +++ b/modules/ticket/back/methods/ticket/closure.js @@ -0,0 +1,179 @@ +const Report = require('vn-print/core/report'); +const Email = require('vn-print/core/email'); +const smtp = require('vn-print/core/smtp'); +const config = require('vn-print/core/config'); +const storage = require('vn-print/core/storage'); + +module.exports = async function(Self, tickets, reqArgs = {}) { + if (tickets.length == 0) return; + + const failedtickets = []; + for (const ticket of tickets) { + try { + await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id]); + + const [invoiceOut] = await Self.rawSql(` + SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued + FROM ticket t + JOIN invoiceOut io ON io.ref = t.refFk + JOIN company cny ON cny.id = io.companyFk + WHERE t.id = ? + `, [ticket.id]); + + const mailOptions = { + overrideAttachments: true, + attachments: [] + }; + + const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed; + + if (invoiceOut) { + const args = { + reference: invoiceOut.ref, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; + + const invoiceReport = new Report('invoice', args); + const stream = await invoiceReport.toPdfStream(); + + const issued = invoiceOut.issued; + const year = issued.getFullYear().toString(); + const month = (issued.getMonth() + 1).toString(); + const day = issued.getDate().toString(); + + const fileName = `${year}${invoiceOut.ref}.pdf`; + + // Store invoice + storage.write(stream, { + type: 'invoice', + path: `${year}/${month}/${day}`, + fileName: fileName + }); + + await Self.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id]); + + if (isToBeMailed) { + const invoiceAttachment = { + filename: fileName, + content: stream + }; + + if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') { + const exportation = new Report('exportation', args); + const stream = await exportation.toPdfStream(); + const fileName = `CITES-${invoiceOut.ref}.pdf`; + + mailOptions.attachments.push({ + filename: fileName, + content: stream + }); + } + + mailOptions.attachments.push(invoiceAttachment); + + const email = new Email('invoice', args); + await email.send(mailOptions); + } + } else if (isToBeMailed) { + const args = { + id: ticket.id, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; + + const email = new Email('delivery-note-link', args); + await email.send(); + } + + // Incoterms authorization + const [{firstOrder}] = await Self.rawSql(` + SELECT COUNT(*) as firstOrder + FROM ticket t + JOIN client c ON c.id = t.clientFk + WHERE t.clientFk = ? + AND NOT t.isDeleted + AND c.isVies + `, [ticket.clientFk]); + + if (firstOrder == 1) { + const args = { + id: ticket.clientFk, + recipientId: ticket.clientFk, + recipient: ticket.recipient, + replyTo: ticket.salesPersonEmail + }; + + const email = new Email('incoterms-authorization', args); + await email.send(); + + const sample = await Self.rawSql( + `SELECT id + FROM sample + WHERE code = 'incoterms-authorization' + `); + + await Self.rawSql(` + INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) + `, [ticket.clientFk, sample.id, ticket.companyFk]); + } + } catch (error) { + // Domain not found + if (error.responseCode == 450) + return invalidEmail(ticket); + + // Save tickets on a list of failed ids + failedtickets.push({ + id: ticket.id, + stacktrace: error + }); + } + } + + // Send email with failed tickets + if (failedtickets.length > 0) { + let body = 'This following tickets have failed:

'; + + for (const ticket of failedtickets) { + body += `Ticket: ${ticket.id} +
${ticket.stacktrace}

`; + } + + smtp.send({ + to: config.app.reportEmail, + subject: '[API] Nightly ticket closure report', + html: body + }); + } + + async function invalidEmail(ticket) { + await Self.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [ + ticket.clientFk + ]); + + const oldInstance = `{"email": "${ticket.recipient}"}`; + const newInstance = `{"email": ""}`; + await Self.rawSql(` + INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) + VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [ + ticket.clientFk, + oldInstance, + newInstance + ]); + + const body = `No se ha podido enviar el albarán ${ticket.id} + al cliente ${ticket.clientFk} - ${ticket.clientName} + porque la dirección de email "${ticket.recipient}" no es correcta + o no está disponible.

+ Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. + Actualiza la dirección de email con una correcta.`; + + smtp.send({ + to: ticket.salesPersonEmail, + subject: 'No se ha podido enviar el albarán', + html: body + }); + } +}; diff --git a/modules/ticket/back/methods/ticket/deliveryNoteCsv.js b/modules/ticket/back/methods/ticket/deliveryNoteCsv.js new file mode 100644 index 000000000..55ec4089d --- /dev/null +++ b/modules/ticket/back/methods/ticket/deliveryNoteCsv.js @@ -0,0 +1,84 @@ +const {toCSV} = require('vn-loopback/util/csv'); + +module.exports = Self => { + Self.remoteMethod('deliveryNoteCsv', { + description: 'Returns the delivery note csv', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The ticket id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The client id', + 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: '/:id/delivery-note-csv', + verb: 'GET' + } + }); + + Self.deliveryNoteCsv = async id => { + const sales = await Self.rawSql(` + SELECT io.ref Invoice, + io.issued InvoiceDate, + s.ticketFk Ticket, + s.itemFk Item, + s.concept Description, + i.size, + i.subName Producer, + s.quantity Quantity, + s.price Price, + s.discount Discount, + s.created Created, + tc.code Taxcode, + tc.description TaxDescription, + i.tag5, + i.value5, + i.tag6, + i.value6, + i.tag7, + i.value7, + i.tag8, + i.value8, + i.tag9, + i.value9, + i.tag10, + i.value10 + FROM vn.sale s + JOIN vn.ticket t ON t.id = s.ticketFk + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.supplier s2 ON s2.id = t.companyFk + JOIN vn.itemTaxCountry itc ON itc.itemFk = i.id + AND itc.countryFk = s2.countryFk + JOIN vn.taxClass tc ON tc.id = itc.taxClassFk + LEFT JOIN vn.invoiceOut io ON io.id = t.refFk + WHERE s.ticketFk = ? + ORDER BY s.ticketFk, s.created`, [id]); + const content = toCSV(sales); + + return [content, 'text/csv', `inline; filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/ticket/back/methods/ticket/deliveryNoteCsvEmail.js b/modules/ticket/back/methods/ticket/deliveryNoteCsvEmail.js new file mode 100644 index 000000000..79702cbaf --- /dev/null +++ b/modules/ticket/back/methods/ticket/deliveryNoteCsvEmail.js @@ -0,0 +1,117 @@ +const {Email} = require('vn-print'); +const {toCSV} = require('vn-loopback/util/csv'); + +module.exports = Self => { + Self.remoteMethodCtx('deliveryNoteCsvEmail', { + description: 'Returns the delivery note csv', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The ticket 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 client id', + 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: '/:id/delivery-note-csv-email', + verb: 'POST' + } + }); + + Self.deliveryNoteCsvEmail = 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 sales = await Self.rawSql(` + SELECT io.ref Invoice, + io.issued InvoiceDate, + s.ticketFk Ticket, + s.itemFk Item, + s.concept Description, + i.size, + i.subName Producer, + s.quantity Quantity, + s.price Price, + s.discount Discount, + s.created Created, + tc.code Taxcode, + tc.description TaxDescription, + i.tag5, + i.value5, + i.tag6, + i.value6, + i.tag7, + i.value7, + i.tag8, + i.value8, + i.tag9, + i.value9, + i.tag10, + i.value10 + FROM vn.sale s + JOIN vn.ticket t ON t.id = s.ticketFk + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.supplier s2 ON s2.id = t.companyFk + JOIN vn.itemTaxCountry itc ON itc.itemFk = i.id + AND itc.countryFk = s2.countryFk + JOIN vn.taxClass tc ON tc.id = itc.taxClassFk + LEFT JOIN vn.invoiceOut io ON io.id = t.refFk + WHERE s.ticketFk = ? + ORDER BY s.ticketFk, s.created`, [id]); + + const content = toCSV(sales); + const fileName = `ticket_${id}.csv`; + const email = new Email('delivery-note', params); + + return email.send({ + overrideAttachments: true, + attachments: [{ + filename: fileName, + content: content + }] + }); + }; +}; diff --git a/modules/ticket/back/methods/ticket/deliveryNoteEmail.js b/modules/ticket/back/methods/ticket/deliveryNoteEmail.js new file mode 100644 index 000000000..cf9f5dd62 --- /dev/null +++ b/modules/ticket/back/methods/ticket/deliveryNoteEmail.js @@ -0,0 +1,65 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('deliveryNoteEmail', { + description: 'Sends the delivery note email with an attached PDF', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The ticket 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: 'type', + type: 'string', + description: 'The delivery note type [ deliveryNote, proforma, withoutPrices ]', + required: false + }, + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/:id/delivery-note-email', + verb: 'POST' + } + }); + + Self.deliveryNoteEmail = async ctx => { + 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('delivery-note', params); + + return email.send(); + }; +}; diff --git a/modules/ticket/back/methods/ticket/deliveryNotePdf.js b/modules/ticket/back/methods/ticket/deliveryNotePdf.js new file mode 100644 index 000000000..b2b3f7198 --- /dev/null +++ b/modules/ticket/back/methods/ticket/deliveryNotePdf.js @@ -0,0 +1,62 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('deliveryNotePdf', { + description: 'Returns the delivery note pdf', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The ticket id', + http: {source: 'path'} + }, + { + arg: 'recipientId', + type: 'number', + description: 'The client id', + required: false + }, + { + arg: 'type', + type: 'string', + description: 'The delivery note type [ deliveryNote, proforma, withoutPrices ]', + 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: '/:id/delivery-note-pdf', + verb: 'GET' + } + }); + + Self.deliveryNotePdf = 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('delivery-note', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${id}.pdf"`]; + }; +}; diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js new file mode 100644 index 000000000..9255e52e6 --- /dev/null +++ b/modules/ticket/back/models/ticket-methods.js @@ -0,0 +1,36 @@ +module.exports = function(Self) { + require('../methods/ticket/getVolume')(Self); + require('../methods/ticket/getTotalVolume')(Self); + require('../methods/ticket/summary')(Self); + require('../methods/ticket/priceDifference')(Self); + require('../methods/ticket/componentUpdate')(Self); + require('../methods/ticket/new')(Self); + require('../methods/ticket/isEditable')(Self); + require('../methods/ticket/setDeleted')(Self); + require('../methods/ticket/restore')(Self); + require('../methods/ticket/getSales')(Self); + require('../methods/ticket/getSalesPersonMana')(Self); + require('../methods/ticket/filter')(Self); + require('../methods/ticket/canBeInvoiced')(Self); + require('../methods/ticket/makeInvoice')(Self); + require('../methods/ticket/updateEditableTicket')(Self); + require('../methods/ticket/isEmpty')(Self); + require('../methods/ticket/updateDiscount')(Self); + require('../methods/ticket/uploadFile')(Self); + require('../methods/ticket/addSale')(Self); + require('../methods/ticket/transferSales')(Self); + require('../methods/ticket/recalculateComponents')(Self); + require('../methods/ticket/sendSms')(Self); + require('../methods/ticket/isLocked')(Self); + require('../methods/ticket/freightCost')(Self); + require('../methods/ticket/getComponentsSum')(Self); + require('../methods/ticket/refund')(Self); + require('../methods/ticket/deliveryNotePdf')(Self); + require('../methods/ticket/deliveryNoteEmail')(Self); + require('../methods/ticket/deliveryNoteCsv')(Self); + require('../methods/ticket/deliveryNoteCsvEmail')(Self); + require('../methods/ticket/closeAll')(Self); + require('../methods/ticket/closeByTicket')(Self); + require('../methods/ticket/closeByAgency')(Self); + require('../methods/ticket/closeByRoute')(Self); +}; diff --git a/modules/ticket/back/models/ticket.js b/modules/ticket/back/models/ticket.js index 47d105824..c05130552 100644 --- a/modules/ticket/back/models/ticket.js +++ b/modules/ticket/back/models/ticket.js @@ -2,32 +2,8 @@ const LoopBackContext = require('loopback-context'); module.exports = Self => { - require('../methods/ticket/getVolume')(Self); - require('../methods/ticket/getTotalVolume')(Self); - require('../methods/ticket/summary')(Self); - require('../methods/ticket/priceDifference')(Self); - require('../methods/ticket/componentUpdate')(Self); - require('../methods/ticket/new')(Self); - require('../methods/ticket/isEditable')(Self); - require('../methods/ticket/setDeleted')(Self); - require('../methods/ticket/restore')(Self); - require('../methods/ticket/getSales')(Self); - require('../methods/ticket/getSalesPersonMana')(Self); - require('../methods/ticket/filter')(Self); - require('../methods/ticket/canBeInvoiced')(Self); - require('../methods/ticket/makeInvoice')(Self); - require('../methods/ticket/updateEditableTicket')(Self); - require('../methods/ticket/isEmpty')(Self); - require('../methods/ticket/updateDiscount')(Self); - require('../methods/ticket/uploadFile')(Self); - require('../methods/ticket/addSale')(Self); - require('../methods/ticket/transferSales')(Self); - require('../methods/ticket/recalculateComponents')(Self); - require('../methods/ticket/sendSms')(Self); - require('../methods/ticket/isLocked')(Self); - require('../methods/ticket/freightCost')(Self); - require('../methods/ticket/getComponentsSum')(Self); - require('../methods/ticket/refund')(Self); + // Methods + require('./ticket-methods')(Self); Self.observe('before save', async function(ctx) { const loopBackContext = LoopBackContext.getCurrentContext(); diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 379942cdd..f73aae721 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -116,14 +116,6 @@ class Controller extends Section { }); } - showPdfDeliveryNote(type) { - this.vnReport.show('delivery-note', { - recipientId: this.ticket.client.id, - ticketId: this.id, - type: type - }); - } - hasDocuware() { const params = { fileCabinet: 'deliveryClient', @@ -133,26 +125,30 @@ class Controller extends Section { .then(res => this.hasDocuwareFile = res.data); } - showCsvDeliveryNote() { - this.vnReport.showCsv('delivery-note', { + showPdfDeliveryNote(type) { + this.vnReport.show(`tickets/${this.id}/delivery-note-pdf`, { recipientId: this.ticket.client.id, - ticketId: this.id, + type: type }); } sendPdfDeliveryNote($data) { - return this.vnEmail.send('delivery-note', { + return this.vnEmail.send(`tickets/${this.id}/delivery-note-email`, { recipientId: this.ticket.client.id, - recipient: $data.email, - ticketId: this.id + recipient: $data.email + }); + } + + showCsvDeliveryNote() { + this.vnReport.show(`tickets/${this.id}/delivery-note-csv`, { + recipientId: this.ticket.client.id }); } sendCsvDeliveryNote($data) { - return this.vnEmail.sendCsv('delivery-note', { + return this.vnEmail.send(`tickets/${this.id}/delivery-note-csv-email`, { recipientId: this.ticket.client.id, - recipient: $data.email, - ticketId: this.id + recipient: $data.email }); } diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index 2d08a7846..091b9a2cf 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -124,12 +124,11 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { jest.spyOn(window, 'open').mockReturnThis(); const type = 'deliveryNote'; const expectedParams = { - ticketId: ticket.id, recipientId: ticket.client.id, type: type }; const serializedParams = $httpParamSerializer(expectedParams); - const expectedPath = `api/report/delivery-note?${serializedParams}`; + const expectedPath = `api/tickets/${ticket.id}/delivery-note-pdf?${serializedParams}`; controller.showPdfDeliveryNote(type); expect(window.open).toHaveBeenCalledWith(expectedPath); @@ -143,12 +142,13 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { const $data = {email: 'brucebanner@gothamcity.com'}; const params = { recipient: $data.email, - recipientId: ticket.client.id, - ticketId: ticket.id + recipientId: ticket.client.id }; controller.sendPdfDeliveryNote($data); - expect(controller.vnEmail.send).toHaveBeenCalledWith('delivery-note', params); + const expectedPath = `tickets/${ticket.id}/delivery-note-email`; + + expect(controller.vnEmail.send).toHaveBeenCalledWith(expectedPath, params); }); }); @@ -157,11 +157,10 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { jest.spyOn(window, 'open').mockReturnThis(); const expectedParams = { - ticketId: ticket.id, recipientId: ticket.client.id }; const serializedParams = $httpParamSerializer(expectedParams); - const expectedPath = `api/csv/delivery-note/download?${serializedParams}`; + const expectedPath = `api/tickets/${ticket.id}/delivery-note-csv?${serializedParams}`; controller.showCsvDeliveryNote(); expect(window.open).toHaveBeenCalledWith(expectedPath); @@ -170,21 +169,18 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { describe('sendCsvDeliveryNote()', () => { it('should make a query to the csv delivery-note send endpoint and show a message snackbar', () => { - jest.spyOn(controller.vnApp, 'showMessage'); + jest.spyOn(controller.vnEmail, 'send'); const $data = {email: 'brucebanner@gothamcity.com'}; const expectedParams = { - ticketId: ticket.id, recipient: $data.email, recipientId: ticket.client.id, }; - const serializedParams = $httpParamSerializer(expectedParams); - - $httpBackend.expectGET(`csv/delivery-note/send?${serializedParams}`).respond(); controller.sendCsvDeliveryNote($data); - $httpBackend.flush(); - expect(controller.vnApp.showMessage).toHaveBeenCalled(); + const expectedPath = `tickets/${ticket.id}/delivery-note-csv-email`; + + expect(controller.vnEmail.send).toHaveBeenCalledWith(expectedPath, expectedParams); }); }); diff --git a/modules/ticket/front/index/index.js b/modules/ticket/front/index/index.js index 2df4de0a5..3039a2a03 100644 --- a/modules/ticket/front/index/index.js +++ b/modules/ticket/front/index/index.js @@ -29,11 +29,8 @@ export default class Controller extends Section { } openDeliveryNotes(ids) { - for (let id of ids) { - this.vnReport.show('delivery-note', { - ticketId: id, - }); - } + for (let id of ids) + this.vnReport.show(`Tickets/${id}/delivery-note-pdf`); } openBalanceDialog() { diff --git a/modules/ticket/front/index/index.spec.js b/modules/ticket/front/index/index.spec.js index b966ca8c4..03071654e 100644 --- a/modules/ticket/front/index/index.spec.js +++ b/modules/ticket/front/index/index.spec.js @@ -96,8 +96,8 @@ describe('Component vnTicketIndex', () => { controller.setDelivered(); $httpBackend.flush(); - expect($window.open).toHaveBeenCalledWith(`api/report/delivery-note?ticketId=${tickets[1].id}`); - expect($window.open).toHaveBeenCalledWith(`api/report/delivery-note?ticketId=${tickets[2].id}`); + expect($window.open).toHaveBeenCalledWith(`api/Tickets/${tickets[1].id}/delivery-note-pdf`); + expect($window.open).toHaveBeenCalledWith(`api/Tickets/${tickets[2].id}/delivery-note-pdf`); }); }); diff --git a/modules/travel/back/methods/travel/extraCommunityEmail.js b/modules/travel/back/methods/travel/extraCommunityEmail.js new file mode 100644 index 000000000..dd93ed905 --- /dev/null +++ b/modules/travel/back/methods/travel/extraCommunityEmail.js @@ -0,0 +1,92 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('extraCommunityEmail', { + description: 'Sends the extra community email with an attached PDF', + accessType: 'WRITE', + accepts: [ + { + 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: 'landedTo', + type: 'date' + }, + { + arg: 'shippedFrom', + type: 'date' + }, + { + arg: 'continent', + type: 'string' + }, + { + arg: 'reference', + type: 'string' + }, + { + arg: 'id', + type: 'number' + }, + { + arg: 'agencyModeFk', + type: 'number' + }, + { + arg: 'warehouseOutFk', + type: 'number' + }, + { + arg: 'warehouseInFk', + type: 'number' + }, + { + arg: 'totalEntries', + type: 'number' + }, + { + arg: 'cargoSupplierFk', + type: 'number' + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: '/extra-community-email', + verb: 'POST' + } + }); + + Self.extraCommunityEmail = async ctx => { + 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('extra-community', params); + + return email.send(); + }; +}; diff --git a/modules/travel/back/methods/travel/extraCommunityFilter.js b/modules/travel/back/methods/travel/extraCommunityFilter.js index 34e0ff7fa..4078e62cb 100644 --- a/modules/travel/back/methods/travel/extraCommunityFilter.js +++ b/modules/travel/back/methods/travel/extraCommunityFilter.js @@ -54,7 +54,7 @@ module.exports = Self => { description: 'The totalEntries filter' }, { - arg: 'ref', + arg: 'reference', type: 'string', description: 'The reference' }, diff --git a/modules/travel/back/methods/travel/extraCommunityPdf.js b/modules/travel/back/methods/travel/extraCommunityPdf.js new file mode 100644 index 000000000..a68e5cd09 --- /dev/null +++ b/modules/travel/back/methods/travel/extraCommunityPdf.js @@ -0,0 +1,89 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('extraCommunityPdf', { + description: 'Returns the extra community pdf', + accessType: 'READ', + accepts: [ + { + arg: 'recipientId', + type: 'number', + description: 'The recipient id', + required: false + }, + { + arg: 'landedTo', + type: 'date' + }, + { + arg: 'shippedFrom', + type: 'date' + }, + { + arg: 'continent', + type: 'string' + }, + { + arg: 'reference', + type: 'string' + }, + { + arg: 'id', + type: 'number' + }, + { + arg: 'agencyModeFk', + type: 'number' + }, + { + arg: 'warehouseOutFk', + type: 'number' + }, + { + arg: 'warehouseInFk', + type: 'number' + }, + { + arg: 'totalEntries', + type: 'number' + }, + { + arg: 'cargoSupplierFk', + type: 'number' + } + ], + 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: '/extra-community-pdf', + verb: 'GET' + } + }); + + Self.extraCommunityPdf = async ctx => { + 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('extra-community', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="extra-community.pdf"`]; + }; +}; diff --git a/modules/travel/back/models/travel.js b/modules/travel/back/models/travel.js index 046153ee2..4bcf7b31d 100644 --- a/modules/travel/back/models/travel.js +++ b/modules/travel/back/models/travel.js @@ -10,6 +10,8 @@ module.exports = Self => { require('../methods/travel/extraCommunityFilter')(Self); require('../methods/travel/getAverageDays')(Self); require('../methods/travel/cloneWithEntries')(Self); + require('../methods/travel/extraCommunityPdf')(Self); + require('../methods/travel/extraCommunityEmail')(Self); Self.rewriteDbError(function(err) { if (err.code === 'ER_DUP_ENTRY') diff --git a/modules/travel/front/extra-community/index.js b/modules/travel/front/extra-community/index.js index 461712e9c..a4ac487e6 100644 --- a/modules/travel/front/extra-community/index.js +++ b/modules/travel/front/extra-community/index.js @@ -157,7 +157,7 @@ class Controller extends Section { } showReport() { - this.vnReport.show('extra-community', this.reportParams); + this.vnReport.show(`Travels/extra-community-pdf`, this.reportParams); } } diff --git a/print/common/css/email.css b/print/common/css/email.css index 6e6350ff5..5fe3b955e 100644 --- a/print/common/css/email.css +++ b/print/common/css/email.css @@ -31,3 +31,8 @@ h1 { font-weight: 100; font-size: 1.5em } + +h6 { + font-weight: 100; + font-size: 1.2em +} diff --git a/print/core/component.js b/print/core/component.js index 37656c240..06ef3033a 100644 --- a/print/core/component.js +++ b/print/core/component.js @@ -53,21 +53,21 @@ class Component { } async getUserLocale() { - let locale = this.args.auth.locale; + let lang = this.args.lang; // Fetches user locale from mixing method getLocale() if (this.args.recipientId) { const component = await this.component(); - locale = await component.getLocale(this.args.recipientId); + lang = await component.getLocale(this.args.recipientId); } const messages = this.locale.messages; - const userTranslations = messages[locale]; + const userTranslations = messages[lang]; if (!userTranslations) { - const fallbackLocale = config.i18n.fallbackLocale; + const fallbackLang = config.i18n.fallbackLocale; - return messages[fallbackLocale]; + return messages[fallbackLang]; } return userTranslations; diff --git a/print/core/components/attachment/assets/css/import.js b/print/core/components/attachment/assets/css/import.js index c742fdf90..fec23d870 100644 --- a/print/core/components/attachment/assets/css/import.js +++ b/print/core/components/attachment/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/email.css`, + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`, `${__dirname}/style.css`]) .mergeStyles(); diff --git a/print/core/components/attachment/assets/css/style.css b/print/core/components/attachment/assets/css/style.css index 775c43ada..37fde9285 100644 --- a/print/core/components/attachment/assets/css/style.css +++ b/print/core/components/attachment/assets/css/style.css @@ -4,19 +4,22 @@ div { } a { - background-color: #F5F5F5; + background-color: #fcfcfc; border: 1px solid #CCC; display: flex; vertical-align: middle; box-sizing: border-box; min-width: 150px; text-decoration: none; - border-radius: 3px; + border-radius: 8px; color: #8dba25 } a > div.icon { + border-radius: 5px; + padding: 2px 5px; + background-color: red; font-weight: bold; - font-size: 18px; - color: #555 + font-size: 12px; + color: #FFF } \ No newline at end of file diff --git a/print/core/components/attachment/attachment.html b/print/core/components/attachment/attachment.html index 88fa64434..0044190a7 100644 --- a/print/core/components/attachment/attachment.html +++ b/print/core/components/attachment/attachment.html @@ -1,6 +1,10 @@ -
+ \ No newline at end of file diff --git a/print/core/components/attachment/attachment.js b/print/core/components/attachment/attachment.js index 5c78a895c..30e1944a4 100755 --- a/print/core/components/attachment/attachment.js +++ b/print/core/components/attachment/attachment.js @@ -4,10 +4,10 @@ module.exports = { attachmentPath() { const filename = this.attachment.filename; const component = this.attachment.component; - if (this.attachment.cid) + if (this.attachment.cid && component) return `/api/${component}/assets/files/${filename}`; - else - return `/api/report/${component}?${this.getHttpParams()}`; + else if (this.attachment.path) + return `/api/${this.attachment.path}?${this.getHttpParams()}`; } }, methods: { @@ -15,7 +15,7 @@ module.exports = { const props = this.args; let query = ''; for (let param in props) { - if (!(props[param] instanceof Object)) { + if (props[param] && !(props[param] instanceof Object)) { if (query != '') query += '&'; query += `${param}=${props[param]}`; } diff --git a/print/core/components/email-footer/assets/css/import.js b/print/core/components/email-footer/assets/css/import.js index c742fdf90..4f6f631f7 100644 --- a/print/core/components/email-footer/assets/css/import.js +++ b/print/core/components/email-footer/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/email.css`, + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`, `${__dirname}/style.css`]) - .mergeStyles(); + .mergeStyles(); \ No newline at end of file diff --git a/print/core/components/email-header/assets/css/import.js b/print/core/components/email-header/assets/css/import.js index c742fdf90..4f6f631f7 100644 --- a/print/core/components/email-header/assets/css/import.js +++ b/print/core/components/email-header/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/email.css`, + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`, `${__dirname}/style.css`]) - .mergeStyles(); + .mergeStyles(); \ No newline at end of file diff --git a/print/core/components/report-footer/assets/css/import.js b/print/core/components/report-footer/assets/css/import.js index a2a9334cb..71fa00f4b 100644 --- a/print/core/components/report-footer/assets/css/import.js +++ b/print/core/components/report-footer/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/layout.css`, - `${appPath}/common/css/report.css`, - `${appPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/report.css`, + `${vnPrintPath}/common/css/misc.css`, `${__dirname}/style.css`]) - .mergeStyles(); + .mergeStyles(); \ No newline at end of file diff --git a/print/core/components/report-header/assets/css/import.js b/print/core/components/report-header/assets/css/import.js index a2a9334cb..e21d3821a 100644 --- a/print/core/components/report-header/assets/css/import.js +++ b/print/core/components/report-header/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/layout.css`, - `${appPath}/common/css/report.css`, - `${appPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/report.css`, + `${vnPrintPath}/common/css/misc.css`, `${__dirname}/style.css`]) .mergeStyles(); diff --git a/print/core/database.js b/print/core/database.js index 6c690afc6..0e81806f2 100644 --- a/print/core/database.js +++ b/print/core/database.js @@ -1,21 +1,22 @@ const mysql = require('mysql2'); const config = require('./config.js'); const fs = require('fs-extra'); -const PoolConnection = mysql.PoolConnection; module.exports = { - init() { - if (!this.pool) { - const datasources = config.datasources; - const pool = mysql.createPoolCluster(); + defaultDataSource: 'vn', - for (let datasource of datasources) - pool.add(datasource.name, datasource.options); + init(dataSource) { + if (!this.connections) { + this.connections = []; - this.pool = pool; + const dataSources = ['vn', 'osticket']; + for (const name of dataSources) + this.connections[name] = dataSource[name].connector.client; + + this.pool = this.connections[this.defaultDataSource]; } - return this.pool; + return this.connections; }, /** @@ -24,15 +25,8 @@ module.exports = { * * @return {Object} - Pool connection */ - getConnection(name = 'default') { - let pool = this.pool; - return new Promise((resolve, reject) => { - pool.getConnection(name, function(error, connection) { - if (error) return reject(error); - - resolve(connection); - }); - }); + getConnection(name = this.defaultDataSource) { + return this.connections[name]; }, /** @@ -44,28 +38,14 @@ module.exports = { * @return {Object} - Result promise */ rawSql(query, params, connection) { - let pool = this.pool; - if (params instanceof PoolConnection) - connection = params; - if (connection) pool = connection; - return new Promise((resolve, reject) => { - if (!connection) { - pool.getConnection('default', function(error, conn) { - if (error) return reject(error); + let db = this.getConnection(); + if (connection) db = connection; - conn.query(query, params, (error, rows) => { - if (error) return reject(error); - conn.release(); - resolve(rows); - }); - }); - } else { - connection.query(query, params, (error, rows) => { - if (error) return reject(error); - resolve(rows); - }); - } + db.query(query, params, (error, rows) => { + if (error) return reject(error); + resolve(rows); + }); }); }, @@ -87,22 +67,25 @@ module.exports = { * Returns the first row from a given raw sql * @param {String} query - The raw SQL query * @param {Object} params - Parameterized values + * @param {Object} connection - Optional pool connection * * @return {Object} - Result promise */ - findOne(query, params) { - return this.rawSql(query, params).then(([row]) => row); + findOne(query, params, connection) { + return this.rawSql(query, params, connection) + .then(([row]) => row); }, /** * Returns the first row from a given SQL file * @param {String} queryName - The SQL file name * @param {Object} params - Parameterized values + * @param {Object} connection - Optional pool connection * * @return {Object} - Result promise */ - findOneFromDef(queryName, params) { - return this.rawSqlFromDef(queryName, params) + findOneFromDef(queryName, params, connection) { + return this.rawSqlFromDef(queryName, params, connection) .then(([row]) => row); }, @@ -110,11 +93,12 @@ module.exports = { * Returns the first property from a given raw sql * @param {String} query - The raw SQL query * @param {Object} params - Parameterized values + * @param {Object} connection - Optional pool connection * * @return {Object} - Result promise */ - findValue(query, params) { - return this.findOne(query, params).then(row => { + findValue(query, params, connection) { + return this.findOne(query, params, connection).then(row => { return Object.values(row)[0]; }); }, @@ -123,13 +107,13 @@ module.exports = { * Returns the first property from a given SQL file * @param {String} queryName - The SQL file name * @param {Object} params - Parameterized values + * @param {Object} connection - Optional pool connection * * @return {Object} - Result promise */ - findValueFromDef(queryName, params) { - return this.findOneFromDef(queryName, params).then(row => { - return Object.values(row)[0]; - }); + findValueFromDef(queryName, params, connection) { + return this.findOneFromDef(queryName, params, connection) + .then(row => Object.values(row)[0]); }, /** diff --git a/print/core/directives/index.js b/print/core/directives/index.js deleted file mode 100644 index 3ba4d8895..000000000 --- a/print/core/directives/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// Import global directives -require('./pin'); diff --git a/print/core/directives/pin.js b/print/core/directives/pin.js deleted file mode 100644 index bf4bb6e6e..000000000 --- a/print/core/directives/pin.js +++ /dev/null @@ -1,9 +0,0 @@ -// DIRECTIVES NOT WORKING -const Vue = require('vue'); -Vue.directive('pin', { - bind: function(el, binding, vnode) { - el.style.position = 'fixed'; - el.style.top = binding.value + 'px'; - el.style.backgroundColor = 'red'; - } -}); diff --git a/print/core/email.js b/print/core/email.js index bc8345cab..0184e360c 100644 --- a/print/core/email.js +++ b/print/core/email.js @@ -1,6 +1,5 @@ const path = require('path'); const smtp = require('./smtp'); -const config = require('./config'); const Component = require('./component'); const Report = require('./report'); @@ -73,10 +72,9 @@ class Email extends Component { } const localeSubject = await this.getSubject(); - const replyTo = this.args.replyTo || this.args.auth.email; const mailOptions = { to: this.args.recipient, - replyTo: replyTo, + replyTo: this.args.replyTo || '', subject: localeSubject, html: rendered, attachments: attachments diff --git a/print/core/mixins/prop-validator.js b/print/core/mixins/prop-validator.js index 16c71a6db..cb41d3dd8 100644 --- a/print/core/mixins/prop-validator.js +++ b/print/core/mixins/prop-validator.js @@ -4,7 +4,7 @@ const validator = { const props = this.$options.props; const invalidProps = []; - for (prop in props) { + for (const prop in props) { const isObject = typeof props[prop] === 'object'; const isRequired = props[prop].required; const isNotDefined = this[prop] === undefined; @@ -19,7 +19,7 @@ const validator = { throw new Error(`Required properties not found [${required}]`); } }, - props: ['isPreview', 'authorization'] + props: ['isPreview', 'access_token'] }; Vue.mixin(validator); diff --git a/print/core/mixins/user-locale.js b/print/core/mixins/user-locale.js index 0e4727334..18b4c68c5 100644 --- a/print/core/mixins/user-locale.js +++ b/print/core/mixins/user-locale.js @@ -24,7 +24,7 @@ const userLocale = { }); } }, - props: ['auth', 'recipientId'] + props: ['recipientId'] }; Vue.mixin(userLocale); diff --git a/print/core/router.js b/print/core/router.js deleted file mode 100644 index cd64ba07e..000000000 --- a/print/core/router.js +++ /dev/null @@ -1,62 +0,0 @@ -const db = require('./database'); - -module.exports = app => { - const routes = require('../methods/routes'); - - const paths = routes.map(route => route.url); - - app.use(paths, async function(request, response, next) { - try { - const token = getToken(request); - const query = `SELECT at.id, at.userId, eu.email, u.lang, at.ttl, at.created - FROM salix.AccessToken at - JOIN account.user u ON u.id = at.userid - JOIN account.emailUser eu ON eu.userFk = u.id - WHERE at.id = ?`; - - const auth = await db.findOne(query, [token]); - - if (!auth || isTokenExpired(auth.created, auth.ttl)) - throw new Error('Invalid authorization token'); - - const args = Object.assign({}, request.query); - const props = Object.assign(args, request.body); - props.authorization = auth.id; - - response.locals = props; - response.locals.auth = { - userId: auth.userId, - token: auth.id, - email: auth.email, - locale: auth.lang - }; - - next(); - } catch (error) { - next(error); - } - }); - - // Register routes - for (let route of routes) - app.use(route.url, route.cb); - - function getToken(request) { - const headers = request.headers; - const queryParams = request.query; - - return headers.authorization || queryParams.authorization; - } - - function isTokenExpired(created, ttl) { - const date = new Date(created); - const currentDate = new Date(); - - date.setSeconds(date.getSeconds() + ttl); - - if (currentDate > date) - return true; - - return false; - } -}; diff --git a/print/core/stylesheet.js b/print/core/stylesheet.js index 42a44fb57..195044f02 100644 --- a/print/core/stylesheet.js +++ b/print/core/stylesheet.js @@ -1,4 +1,5 @@ const fs = require('fs-extra'); +const path = require('path'); class Stylesheet { constructor(files) { @@ -7,8 +8,9 @@ class Stylesheet { } mergeStyles() { - for (const file of this.files) + for (const file of this.files) { this.css.push(fs.readFileSync(file)); + } return this.css.join('\n'); } diff --git a/print/index.js b/print/index.js new file mode 100644 index 000000000..484aba00e --- /dev/null +++ b/print/index.js @@ -0,0 +1,48 @@ +const express = require('express'); +const path = require('path'); +const fs = require('fs'); + +const templatesPath = path.resolve(__dirname, './templates'); +const componentsPath = path.resolve(__dirname, './core/components'); + +module.exports = { + async boot(app) { + // Init database instance + + require('./core/database').init(app.dataSources); + require('./core/smtp').init(); + require('./core/mixins'); + require('./core/filters'); + + const componentsDir = fs.readdirSync(componentsPath); + componentsDir.forEach(componentName => { + const componentDir = path.join(componentsPath, '/', componentName); + const assetsDir = `${componentDir}/assets`; + + app.use(`/api/${componentName}/assets`, express.static(assetsDir)); + }); + + /** + * Serve static files + */ + const templatesDir = fs.readdirSync(templatesPath); + templatesDir.forEach(directory => { + const templateTypeDir = path.join(templatesPath, '/', directory); + const templates = fs.readdirSync(templateTypeDir); + + templates.forEach(templateName => { + const templateDir = path.join(templatesPath, '/', directory, '/', templateName); + const assetsDir = `${templateDir}/assets`; + + app.use(`/api/${templateName}/assets`, express.static(assetsDir)); + }); + }); + + return true; + }, + Email: require('./core/email'), + Report: require('./core/report'), + storage: require('./core/storage'), + smtp: require('./core/smtp'), + db: require('./core/database') +}; diff --git a/print/methods/closure/closeByAgency.js b/print/methods/closure/closeByAgency.js deleted file mode 100644 index bbf72f137..000000000 --- a/print/methods/closure/closeByAgency.js +++ /dev/null @@ -1,59 +0,0 @@ -const db = require('vn-print/core/database'); -const closure = require('./closure'); - -module.exports = async function(request, response, next) { - try { - const reqArgs = request.body; - - if (!reqArgs.agencyModeId) - throw new Error('The argument agencyModeId is required'); - - if (!reqArgs.warehouseId) - throw new Error('The argument warehouseId is required'); - - if (!reqArgs.to) - throw new Error('The argument to is required'); - - const agencyIds = reqArgs.agencyModeId.split(','); - const tickets = await db.rawSql(` - SELECT - t.id, - t.clientFk, - t.companyFk, - c.name clientName, - c.email recipient, - c.salesPersonFk, - c.isToBeMailed, - c.hasToInvoice, - co.hasDailyInvoice, - eu.email salesPersonEmail - FROM expedition e - JOIN ticket t ON t.id = e.ticketFk - JOIN ticketState ts ON ts.ticketFk = t.id - JOIN alertLevel al ON al.id = ts.alertLevel - JOIN client c ON c.id = t.clientFk - JOIN province p ON p.id = c.provinceFk - JOIN country co ON co.id = p.countryFk - LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk - WHERE al.code = 'PACKED' - AND t.agencyModeFk IN(?) - AND t.warehouseFk = ? - AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) - AND util.dayEnd(?) - AND t.refFk IS NULL - GROUP BY e.ticketFk`, [ - agencyIds, - reqArgs.warehouseId, - reqArgs.to, - reqArgs.to - ]); - - await closure.start(tickets, response.locals); - - response.status(200).json({ - message: 'Success' - }); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/closure/closure.js b/print/methods/closure/closure.js deleted file mode 100644 index fe5aba5e7..000000000 --- a/print/methods/closure/closure.js +++ /dev/null @@ -1,183 +0,0 @@ -const db = require('vn-print/core/database'); -const Report = require('vn-print/core/report'); -const Email = require('vn-print/core/email'); -const smtp = require('vn-print/core/smtp'); -const config = require('vn-print/core/config'); -const storage = require('vn-print/core/storage'); - -module.exports = { - async start(tickets, reqArgs) { - console.log(tickets); - if (tickets.length == 0) return; - - const failedtickets = []; - for (const ticket of tickets) { - try { - console.log(`Closing ticket id ${ticket.id}...`); - await db.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id]); - - const invoiceOut = await db.findOne(` - SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued - FROM ticket t - JOIN invoiceOut io ON io.ref = t.refFk - JOIN company cny ON cny.id = io.companyFk - WHERE t.id = ? - `, [ticket.id]); - - const mailOptions = { - overrideAttachments: true, - attachments: [] - }; - - const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed; - - if (invoiceOut) { - const args = Object.assign({ - refFk: invoiceOut.ref, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }, reqArgs); - - const invoiceReport = new Report('invoice', args); - const stream = await invoiceReport.toPdfStream(); - - const issued = invoiceOut.issued; - const year = issued.getFullYear().toString(); - const month = (issued.getMonth() + 1).toString(); - const day = issued.getDate().toString(); - - const fileName = `${year}${invoiceOut.ref}.pdf`; - - // Store invoice - storage.write(stream, { - type: 'invoice', - path: `${year}/${month}/${day}`, - fileName: fileName - }); - - await db.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id]); - - if (isToBeMailed) { - const invoiceAttachment = { - filename: fileName, - content: stream - }; - - if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') { - const exportation = new Report('exportation', args); - const stream = await exportation.toPdfStream(); - const fileName = `CITES-${invoiceOut.ref}.pdf`; - - mailOptions.attachments.push({ - filename: fileName, - content: stream - }); - } - - mailOptions.attachments.push(invoiceAttachment); - - const email = new Email('invoice', args); - await email.send(mailOptions); - } - } else if (isToBeMailed) { - const args = Object.assign({ - ticketId: ticket.id, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }, reqArgs); - - const email = new Email('delivery-note-link', args); - await email.send(); - } - - // Incoterms authorization - const {firstOrder} = await db.findOne(` - SELECT COUNT(*) as firstOrder - FROM ticket t - JOIN client c ON c.id = t.clientFk - WHERE t.clientFk = ? - AND NOT t.isDeleted - AND c.isVies - `, [ticket.clientFk]); - - if (firstOrder == 1) { - const args = Object.assign({ - ticketId: ticket.id, - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }, reqArgs); - - const email = new Email('incoterms-authorization', args); - await email.send(); - - const sample = await db.findOne( - `SELECT id - FROM sample - WHERE code = 'incoterms-authorization'`); - - await db.rawSql(` - INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?) - `, [ticket.clientFk, sample.id, ticket.companyFk]); - } - } catch (error) { - // Domain not found - if (error.responseCode == 450) - return invalidEmail(ticket); - - // Save tickets on a list of failed ids - failedtickets.push({ - id: ticket.id, - stacktrace: error - }); - } - } - - // Send email with failed tickets - if (failedtickets.length > 0) { - let body = 'This following tickets have failed:

'; - - for (const ticket of failedtickets) { - body += `Ticket: ${ticket.id} -
${ticket.stacktrace}

`; - } - - smtp.send({ - to: config.app.reportEmail, - subject: '[API] Nightly ticket closure report', - html: body - }); - } - }, -}; - -async function invalidEmail(ticket) { - await db.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [ - ticket.clientFk - ]); - - const oldInstance = `{"email": "${ticket.recipient}"}`; - const newInstance = `{"email": ""}`; - await db.rawSql(` - INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) - VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [ - ticket.clientFk, - oldInstance, - newInstance - ]); - - const body = `No se ha podido enviar el albarán ${ticket.id} - al cliente ${ticket.clientFk} - ${ticket.clientName} - porque la dirección de email "${ticket.recipient}" no es correcta - o no está disponible.

- Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. - Actualiza la dirección de email con una correcta.`; - - smtp.send({ - to: ticket.salesPersonEmail, - subject: 'No se ha podido enviar el albarán', - html: body - }); -} diff --git a/print/methods/closure/index.js b/print/methods/closure/index.js deleted file mode 100644 index 2d5eaf4c5..000000000 --- a/print/methods/closure/index.js +++ /dev/null @@ -1,9 +0,0 @@ -const express = require('express'); -const router = new express.Router(); - -router.post('/all', require('./closeAll')); -router.post('/by-ticket', require('./closeByTicket')); -router.post('/by-agency', require('./closeByAgency')); -router.post('/by-route', require('./closeByRoute')); - -module.exports = router; diff --git a/print/methods/csv/delivery-note/download.js b/print/methods/csv/delivery-note/download.js deleted file mode 100644 index d369d5f4a..000000000 --- a/print/methods/csv/delivery-note/download.js +++ /dev/null @@ -1,24 +0,0 @@ -const path = require('path'); -const db = require('vn-print/core/database'); - -const {toCSV} = require('../csv'); -const sqlPath = path.join(__dirname, 'sql'); - -module.exports = async function(request, response, next) { - try { - const reqArgs = request.query; - if (!reqArgs.ticketId) - throw new Error('The argument ticketId is required'); - - const ticketId = reqArgs.ticketId; - const sales = await db.rawSqlFromDef(`${sqlPath}/sales`, [ticketId]); - const content = toCSV(sales); - const fileName = `ticket_${ticketId}.csv`; - - response.setHeader('Content-type', 'text/csv'); - response.setHeader('Content-Disposition', `inline; filename="${fileName}"`); - response.end(content); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/csv/delivery-note/send.js b/print/methods/csv/delivery-note/send.js deleted file mode 100644 index 478f20f57..000000000 --- a/print/methods/csv/delivery-note/send.js +++ /dev/null @@ -1,40 +0,0 @@ -const path = require('path'); -const db = require('vn-print/core/database'); -const Email = require('vn-print/core/email'); - -const {toCSV} = require('../csv'); -const sqlPath = path.join(__dirname, 'sql'); - -module.exports = async function(request, response, next) { - try { - const reqArgs = request.query; - if (!reqArgs.ticketId) - throw new Error('The argument ticketId is required'); - - const ticketId = reqArgs.ticketId; - const ticket = await db.findOneFromDef(`${sqlPath}/ticket`, [ticketId]); - const sales = await db.rawSqlFromDef(`${sqlPath}/sales`, [ticketId]); - - const args = Object.assign({ - ticketId: (String(ticket.id)), - recipientId: ticket.clientFk, - recipient: ticket.recipient, - replyTo: ticket.salesPersonEmail - }, response.locals); - - const content = toCSV(sales); - const fileName = `ticket_${ticketId}.csv`; - const email = new Email('delivery-note', args); - await email.send({ - overrideAttachments: true, - attachments: [{ - filename: fileName, - content: content - }] - }); - - response.status(200).json({message: 'Success'}); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/csv/delivery-note/sql/sales.sql b/print/methods/csv/delivery-note/sql/sales.sql deleted file mode 100644 index e5b419571..000000000 --- a/print/methods/csv/delivery-note/sql/sales.sql +++ /dev/null @@ -1,35 +0,0 @@ -SELECT io.ref Invoice, - io.issued InvoiceDate, - s.ticketFk Ticket, - s.itemFk Item, - s.concept Description, - i.size, - i.subName Producer, - s.quantity Quantity, - s.price Price, - s.discount Discount, - s.created Created, - tc.code Taxcode, - tc.description TaxDescription, - i.tag5, - i.value5, - i.tag6, - i.value6, - i.tag7, - i.value7, - i.tag8, - i.value8, - i.tag9, - i.value9, - i.tag10, - i.value10 -FROM vn.sale s - JOIN vn.ticket t ON t.id = s.ticketFk - JOIN vn.item i ON i.id = s.itemFk - JOIN vn.supplier s2 ON s2.id = t.companyFk - JOIN vn.itemTaxCountry itc ON itc.itemFk = i.id - AND itc.countryFk = s2.countryFk - JOIN vn.taxClass tc ON tc.id = itc.taxClassFk - LEFT JOIN vn.invoiceOut io ON io.id = t.refFk -WHERE s.ticketFk = ? -ORDER BY s.ticketFk, s.created \ No newline at end of file diff --git a/print/methods/csv/delivery-note/sql/ticket.sql b/print/methods/csv/delivery-note/sql/ticket.sql deleted file mode 100644 index b80c7c42c..000000000 --- a/print/methods/csv/delivery-note/sql/ticket.sql +++ /dev/null @@ -1,9 +0,0 @@ -SELECT - t.id, - t.clientFk, - c.email recipient, - eu.email salesPersonEmail -FROM ticket t - JOIN client c ON c.id = t.clientFk - LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk -WHERE t.id = ? \ No newline at end of file diff --git a/print/methods/csv/index.js b/print/methods/csv/index.js deleted file mode 100644 index 6bdd1b60d..000000000 --- a/print/methods/csv/index.js +++ /dev/null @@ -1,9 +0,0 @@ -const express = require('express'); -const router = new express.Router(); - -router.get('/delivery-note/download', require('./delivery-note/download')); -router.get('/delivery-note/send', require('./delivery-note/send')); -router.get('/invoice/download', require('./invoice/download')); -router.get('/invoice/send', require('./invoice/send')); - -module.exports = router; diff --git a/print/methods/csv/invoice/download.js b/print/methods/csv/invoice/download.js deleted file mode 100644 index 9cca99f2d..000000000 --- a/print/methods/csv/invoice/download.js +++ /dev/null @@ -1,24 +0,0 @@ -const path = require('path'); -const db = require('vn-print/core/database'); - -const {toCSV} = require('../csv'); -const sqlPath = path.join(__dirname, 'sql'); - -module.exports = async function(request, response, next) { - try { - const reqArgs = request.query; - if (!reqArgs.refFk) - throw new Error('The argument refFk is required'); - - const refFk = reqArgs.refFk; - const sales = await db.rawSqlFromDef(`${sqlPath}/sales`, [refFk]); - const content = toCSV(sales); - const fileName = `invoice_${refFk}.csv`; - - response.setHeader('Content-type', 'text/csv'); - response.setHeader('Content-Disposition', `inline; filename="${fileName}"`); - response.end(content); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/csv/invoice/send.js b/print/methods/csv/invoice/send.js deleted file mode 100644 index 2729e4a2b..000000000 --- a/print/methods/csv/invoice/send.js +++ /dev/null @@ -1,40 +0,0 @@ -const path = require('path'); -const db = require('vn-print/core/database'); -const Email = require('vn-print/core/email'); - -const {toCSV} = require('../csv'); -const sqlPath = path.join(__dirname, 'sql'); - -module.exports = async function(request, response, next) { - try { - const reqArgs = request.query; - if (!reqArgs.refFk) - throw new Error('The argument refFk is required'); - - const refFk = reqArgs.refFk; - const invoice = await db.findOneFromDef(`${sqlPath}/invoice`, [refFk]); - const sales = await db.rawSqlFromDef(`${sqlPath}/sales`, [refFk]); - - const args = Object.assign({ - refFk: invoice.refFk, - recipientId: invoice.clientFk, - recipient: invoice.recipient, - replyTo: invoice.salesPersonEmail - }, response.locals); - - const content = toCSV(sales); - const fileName = `invoice_${refFk}.csv`; - const email = new Email('invoice', args); - await email.send({ - overrideAttachments: true, - attachments: [{ - filename: fileName, - content: content - }] - }); - - response.status(200).json({message: 'Success'}); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/csv/invoice/sql/invoice.sql b/print/methods/csv/invoice/sql/invoice.sql deleted file mode 100644 index d484766a0..000000000 --- a/print/methods/csv/invoice/sql/invoice.sql +++ /dev/null @@ -1,10 +0,0 @@ -SELECT - io.id, - io.clientFk, - c.email recipient, - eu.email salesPersonEmail -FROM invoiceOut io - JOIN client c ON c.id = io.clientFk - LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk - LEFT JOIN ticket t ON t.refFk = io.ref -WHERE t.refFk = ? \ No newline at end of file diff --git a/print/methods/csv/invoice/sql/sales.sql b/print/methods/csv/invoice/sql/sales.sql deleted file mode 100644 index 33fe62476..000000000 --- a/print/methods/csv/invoice/sql/sales.sql +++ /dev/null @@ -1,35 +0,0 @@ -SELECT io.ref Invoice, - io.issued InvoiceDate, - s.ticketFk Ticket, - s.itemFk Item, - s.concept Description, - i.size, - i.subName Producer, - s.quantity Quantity, - s.price Price, - s.discount Discount, - s.created Created, - tc.code Taxcode, - tc.description TaxDescription, - i.tag5, - i.value5, - i.tag6, - i.value6, - i.tag7, - i.value7, - i.tag8, - i.value8, - i.tag9, - i.value9, - i.tag10, - i.value10 -FROM sale s - JOIN ticket t ON t.id = s.ticketFk - JOIN item i ON i.id = s.itemFk - JOIN supplier s2 ON s2.id = t.companyFk - JOIN itemTaxCountry itc ON itc.itemFk = i.id - AND itc.countryFk = s2.countryFk - JOIN taxClass tc ON tc.id = itc.taxClassFk - JOIN invoiceOut io ON io.ref = t.refFk -WHERE t.refFk = ? -ORDER BY s.ticketFk, s.created \ No newline at end of file diff --git a/print/methods/email/email.js b/print/methods/email/email.js deleted file mode 100644 index 5d6882f7d..000000000 --- a/print/methods/email/email.js +++ /dev/null @@ -1,16 +0,0 @@ -const Email = require('vn-print/core/email'); - -module.exports = async function(request, response, next) { - try { - const templateName = request.params.name; - const args = response.locals; - const email = new Email(templateName, args); - await email.send(); - - response.status(200).json({ - message: 'Sent' - }); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/email/index.js b/print/methods/email/index.js deleted file mode 100644 index 10c2d2325..000000000 --- a/print/methods/email/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const express = require('express'); -const router = new express.Router(); - -router.get('/:name', require('./email')); -router.get('/:name/preview', require('./preview')); - -module.exports = router; diff --git a/print/methods/email/preview.js b/print/methods/email/preview.js deleted file mode 100644 index e6a1aaf35..000000000 --- a/print/methods/email/preview.js +++ /dev/null @@ -1,14 +0,0 @@ -const Email = require('vn-print/core/email'); - -module.exports = async function(request, response, next) { - try { - const templateName = request.params.name; - const args = Object.assign({isPreview: true}, response.locals); - const email = new Email(templateName, args); - const template = await email.render(); - - response.send(template); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/report/document.js b/print/methods/report/document.js deleted file mode 100644 index b24abf4ac..000000000 --- a/print/methods/report/document.js +++ /dev/null @@ -1,17 +0,0 @@ -const Report = require('vn-print/core/report'); - -module.exports = async function(request, response, next) { - try { - const reportName = request.params.name; - const args = response.locals; - const report = new Report(reportName, args); - const stream = await report.toPdfStream(); - const fileName = await report.getFileName(); - - response.setHeader('Content-type', 'application/pdf'); - response.setHeader('Content-Disposition', `inline; filename="${fileName}"`); - response.end(stream); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/report/index.js b/print/methods/report/index.js deleted file mode 100644 index c422c76df..000000000 --- a/print/methods/report/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const express = require('express'); -const router = new express.Router(); - -router.get('/:name', require('./document')); -router.get('/:name/preview', require('./preview')); - -module.exports = router; diff --git a/print/methods/report/preview.js b/print/methods/report/preview.js deleted file mode 100644 index 0d6ad6f43..000000000 --- a/print/methods/report/preview.js +++ /dev/null @@ -1,13 +0,0 @@ -const Report = require('vn-print/core/report'); - -module.exports = async function(request, response, next) { - try { - const reportName = request.params.name; - const report = new Report(reportName, request.query); - const template = await report.render(); - - response.send(template); - } catch (error) { - next(error); - } -}; diff --git a/print/methods/routes.js b/print/methods/routes.js deleted file mode 100644 index 28671b3da..000000000 --- a/print/methods/routes.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = [ - { - url: '/api/report', - cb: require('./report') - }, - { - url: '/api/email', - cb: require('./email') - }, - { - url: '/api/csv', - cb: require('./csv') - }, - { - url: '/api/closure', - cb: require('./closure') - }, - { - url: '/api/schedule', - cb: require('./schedule') - } -]; diff --git a/print/methods/schedule/consumption.js b/print/methods/schedule/consumption.js deleted file mode 100644 index 39d39105b..000000000 --- a/print/methods/schedule/consumption.js +++ /dev/null @@ -1,58 +0,0 @@ -const db = require('vn-print/core/database'); -const Email = require('vn-print/core/email'); - -module.exports = async function(request, response, next) { - try { - const reqArgs = request.body; - - if (!reqArgs.clientIds) - throw new Error('The argument clientIds is required'); - if (!reqArgs.from) - throw new Error('The argument from is required'); - if (!reqArgs.to) - throw new Error('The argument to is required'); - - response.status(200).json({ - message: 'Success' - }); - - const clientIds = reqArgs.clientIds; - - const clients = await db.rawSql(` - SELECT - c.id, - c.email, - eu.email salesPersonEmail - FROM client c - JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk - JOIN ticket t ON t.clientFk = c.id - JOIN sale s ON s.ticketFk = t.id - JOIN item i ON i.id = s.itemFk - JOIN itemType it ON it.id = i.typeFk - WHERE c.id IN(?) - AND it.isPackaging = FALSE - AND DATE(t.shipped) BETWEEN ? AND ? - GROUP BY c.id`, [clientIds, reqArgs.from, reqArgs.to]); - - const clientData = new Map(); - for (const client of clients) - clientData.set(client.id, client); - - for (const clientId of reqArgs.clientIds) { - const client = clientData.get(clientId); - - if (client) { - const args = Object.assign({ - recipientId: clientId, - recipient: client.email, - replyTo: client.salesPersonEmail - }, response.locals); - - const email = new Email('campaign-metrics', args); - await email.send(); - } - } - } catch (error) { - next(error); - } -}; diff --git a/print/methods/schedule/index.js b/print/methods/schedule/index.js deleted file mode 100644 index 05d54b2ed..000000000 --- a/print/methods/schedule/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const express = require('express'); -const router = new express.Router(); - -router.post('/consumption', require('./consumption')); -router.post('/invoice', require('./invoice')); - -module.exports = router; diff --git a/print/templates/email/buyer-week-waste/assets/css/import.js b/print/templates/email/buyer-week-waste/assets/css/import.js index c742fdf90..7360587f7 100644 --- a/print/templates/email/buyer-week-waste/assets/css/import.js +++ b/print/templates/email/buyer-week-waste/assets/css/import.js @@ -1,9 +1,13 @@ -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`, + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`, `${__dirname}/style.css`]) .mergeStyles(); + diff --git a/print/templates/email/buyer-week-waste/buyer-week-waste.js b/print/templates/email/buyer-week-waste/buyer-week-waste.js index 9af477e82..05a80ac6a 100755 --- a/print/templates/email/buyer-week-waste/buyer-week-waste.js +++ b/print/templates/email/buyer-week-waste/buyer-week-waste.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'); diff --git a/print/templates/email/campaign-metrics/assets/css/import.js b/print/templates/email/campaign-metrics/assets/css/import.js index b44d6bd37..4b4bb7086 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`]) + `${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/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/claim-pickup-order/assets/css/import.js b/print/templates/email/claim-pickup-order/assets/css/import.js index b44d6bd37..1582b82c5 100644 --- a/print/templates/email/claim-pickup-order/assets/css/import.js +++ b/print/templates/email/claim-pickup-order/assets/css/import.js @@ -1,8 +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/email.css`]) + `${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/claim-pickup-order/claim-pickup-order.js b/print/templates/email/claim-pickup-order/claim-pickup-order.js index cf4ba7d12..d3836db39 100755 --- a/print/templates/email/claim-pickup-order/claim-pickup-order.js +++ b/print/templates/email/claim-pickup-order/claim-pickup-order.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'); @@ -9,7 +9,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - claimId: { + id: { type: [Number, String], required: true } diff --git a/print/templates/email/client-debt-statement/assets/css/import.js b/print/templates/email/client-debt-statement/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/client-debt-statement/assets/css/import.js +++ b/print/templates/email/client-debt-statement/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`]) + `${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/client-debt-statement/attachments.json b/print/templates/email/client-debt-statement/attachments.json deleted file mode 100644 index 9cc4911e6..000000000 --- a/print/templates/email/client-debt-statement/attachments.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "filename": "client-debt-statement.pdf", - "component": "client-debt-statement" - } -] \ No newline at end of file diff --git a/print/templates/email/client-debt-statement/client-debt-statement.js b/print/templates/email/client-debt-statement/client-debt-statement.js index f32f9e239..85b3c5cc3 100755 --- a/print/templates/email/client-debt-statement/client-debt-statement.js +++ b/print/templates/email/client-debt-statement/client-debt-statement.js @@ -1,8 +1,7 @@ -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'); const attachment = new Component('attachment'); -const attachments = require('./attachments.json'); module.exports = { name: 'client-debt-statement', @@ -12,10 +11,18 @@ module.exports = { 'attachment': attachment.build() }, data() { - return {attachments}; + return { + attachments: [ + { + filename: 'client-debt-statement.pdf', + type: 'pdf', + path: `Clients/${this.id}/client-debt-statement-pdf` + } + ] + }; }, props: { - recipientId: { + id: { type: [Number, String], required: true }, diff --git a/print/templates/email/client-welcome/assets/css/import.js b/print/templates/email/client-welcome/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/client-welcome/assets/css/import.js +++ b/print/templates/email/client-welcome/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`]) + `${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/client-welcome/client-welcome.js b/print/templates/email/client-welcome/client-welcome.js index eeb11bb78..380837877 100755 --- a/print/templates/email/client-welcome/client-welcome.js +++ b/print/templates/email/client-welcome/client-welcome.js @@ -1,15 +1,15 @@ -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'); module.exports = { name: 'client-welcome', async serverPrefetch() { - this.client = await this.fetchClient(this.recipientId); + this.client = await this.fetchClient(this.id); }, methods: { - fetchClient(clientId) { - return this.findOneFromDef('client', [clientId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); }, }, components: { @@ -17,7 +17,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], required: true } diff --git a/print/templates/email/credit-request/assets/css/import.js b/print/templates/email/credit-request/assets/css/import.js index b44d6bd37..89b2afaa5 100644 --- a/print/templates/email/credit-request/assets/css/import.js +++ b/print/templates/email/credit-request/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/credit-request/credit-request.js b/print/templates/email/credit-request/credit-request.js index 69463f43a..8f68d56c0 100755 --- a/print/templates/email/credit-request/credit-request.js +++ b/print/templates/email/credit-request/credit-request.js @@ -1,8 +1,7 @@ -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'); const attachment = new Component('attachment'); -const attachments = require('./attachments.json'); module.exports = { name: 'credit-request', @@ -12,6 +11,20 @@ module.exports = { 'attachment': attachment.build() }, data() { - return {attachments}; + return { + attachments: [ + { + filename: 'credit-request.pdf', + type: 'pdf', + path: `Clients/${this.id}/credit-request-pdf` + } + ] + }; }, + props: { + id: { + type: Number, + required: true + } + } }; diff --git a/print/templates/email/delivery-note-link/assets/css/import.js b/print/templates/email/delivery-note-link/assets/css/import.js index c742fdf90..fec23d870 100644 --- a/print/templates/email/delivery-note-link/assets/css/import.js +++ b/print/templates/email/delivery-note-link/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/email.css`, + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`, `${__dirname}/style.css`]) .mergeStyles(); diff --git a/print/templates/email/delivery-note-link/delivery-note-link.html b/print/templates/email/delivery-note-link/delivery-note-link.html index ab58cbb24..1d4906261 100644 --- a/print/templates/email/delivery-note-link/delivery-note-link.html +++ b/print/templates/email/delivery-note-link/delivery-note-link.html @@ -30,7 +30,7 @@

{{ $t('title') }}

{{$t('dear')}}

-

+

@@ -38,7 +38,7 @@

{{$t('copyLink')}}

diff --git a/print/templates/email/delivery-note-link/delivery-note-link.js b/print/templates/email/delivery-note-link/delivery-note-link.js index 471b370d9..1804bf144 100755 --- a/print/templates/email/delivery-note-link/delivery-note-link.js +++ b/print/templates/email/delivery-note-link/delivery-note-link.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'); @@ -9,7 +9,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - ticketId: { + id: { type: [Number, String], required: true } diff --git a/print/templates/email/delivery-note/assets/css/import.js b/print/templates/email/delivery-note/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/delivery-note/assets/css/import.js +++ b/print/templates/email/delivery-note/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`]) + `${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/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 ffd2fe202..ba3d44001 100755 --- a/print/templates/email/delivery-note/delivery-note.js +++ b/print/templates/email/delivery-note/delivery-note.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'); @@ -9,7 +9,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - ticketId: { + id: { type: [Number, String], required: true } diff --git a/print/templates/email/driver-route/assets/css/import.js b/print/templates/email/driver-route/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/driver-route/assets/css/import.js +++ b/print/templates/email/driver-route/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`]) + `${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/driver-route/driver-route.js b/print/templates/email/driver-route/driver-route.js index 378cd82ce..0895ccc8c 100755 --- a/print/templates/email/driver-route/driver-route.js +++ b/print/templates/email/driver-route/driver-route.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'); @@ -9,7 +9,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - routeId: { + id: { type: [Number, String], required: true } diff --git a/print/templates/email/incoterms-authorization/assets/css/import.js b/print/templates/email/incoterms-authorization/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/incoterms-authorization/assets/css/import.js +++ b/print/templates/email/incoterms-authorization/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`]) + `${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/incoterms-authorization/attachments.json b/print/templates/email/incoterms-authorization/attachments.json deleted file mode 100644 index 9dfd945db..000000000 --- a/print/templates/email/incoterms-authorization/attachments.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "filename": "incoterms-authorization.pdf", - "component": "incoterms-authorization" - } -] \ No newline at end of file diff --git a/print/templates/email/incoterms-authorization/incoterms-authorization.js b/print/templates/email/incoterms-authorization/incoterms-authorization.js index bac40d331..b1c7286dd 100755 --- a/print/templates/email/incoterms-authorization/incoterms-authorization.js +++ b/print/templates/email/incoterms-authorization/incoterms-authorization.js @@ -1,13 +1,20 @@ -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'); const attachment = new Component('attachment'); -const attachments = require('./attachments.json'); module.exports = { name: 'incoterms-authorization', data() { - return {attachments}; + return { + attachments: [ + { + filename: 'incoterms-authorization.pdf', + type: 'pdf', + path: `Clients/${this.id}/incoterms-authorization-pdf` + } + ] + }; }, components: { 'email-header': emailHeader.build(), @@ -15,9 +22,10 @@ module.exports = { 'attachment': attachment.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The client id' }, companyId: { type: [Number, String], diff --git a/print/templates/email/invoice/assets/css/import.js b/print/templates/email/invoice/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/invoice/assets/css/import.js +++ b/print/templates/email/invoice/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`]) + `${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/invoice/invoice.js b/print/templates/email/invoice/invoice.js index 6f6ea8683..fe66062aa 100755 --- a/print/templates/email/invoice/invoice.js +++ b/print/templates/email/invoice/invoice.js @@ -1,15 +1,15 @@ -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'); module.exports = { name: 'invoice', async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.refFk); + this.invoice = await this.fetchInvoice(this.reference); }, methods: { - fetchInvoice(refFk) { - return this.findOneFromDef('invoice', [refFk]); + fetchInvoice(reference) { + return this.findOneFromDef('invoice', [reference]); }, }, components: { @@ -17,7 +17,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - refFk: { + reference: { type: [Number, String], required: true } diff --git a/print/templates/email/letter-debtor-nd/assets/css/import.js b/print/templates/email/letter-debtor-nd/assets/css/import.js index 624404a6c..1582b82c5 100644 --- a/print/templates/email/letter-debtor-nd/assets/css/import.js +++ b/print/templates/email/letter-debtor-nd/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/email.css`]) + `${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/letter-debtor-nd/attachments.json b/print/templates/email/letter-debtor-nd/attachments.json deleted file mode 100644 index 1e21ea343..000000000 --- a/print/templates/email/letter-debtor-nd/attachments.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "filename": "letter-debtor.pdf", - "component": "letter-debtor" - } -] \ No newline at end of file diff --git a/print/templates/email/letter-debtor-nd/letter-debtor-nd.js b/print/templates/email/letter-debtor-nd/letter-debtor-nd.js index 5e010d1ba..cf9cc7ddd 100755 --- a/print/templates/email/letter-debtor-nd/letter-debtor-nd.js +++ b/print/templates/email/letter-debtor-nd/letter-debtor-nd.js @@ -1,23 +1,30 @@ -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'); const attachment = new Component('attachment'); -const attachments = require('./attachments.json'); module.exports = { name: 'letter-debtor-nd', async serverPrefetch() { - this.debtor = await this.fetchDebtor(this.recipientId, this.companyId); + this.debtor = await this.fetchDebtor(this.id, this.companyId); if (!this.debtor) throw new Error('Something went wrong'); }, data() { - return {attachments}; + return { + attachments: [ + { + filename: 'letter-debtor.pdf', + type: 'pdf', + path: `Clients/${this.id}/letter-debtor-pdf` + } + ] + }; }, methods: { - fetchDebtor(clientId, companyId) { - return this.findOneFromDef('client', [clientId, companyId]); + fetchDebtor(id, companyId) { + return this.findOneFromDef('client', [id, companyId]); } }, components: { @@ -26,10 +33,7 @@ module.exports = { 'attachment': attachment.build() }, props: { - authorization: { - required: true - }, - recipientId: { + id: { type: [Number, String], required: true }, diff --git a/print/templates/email/letter-debtor-nd/sql/client.sql b/print/templates/email/letter-debtor-nd/sql/client.sql index 479bfac5e..d5da5d0d5 100644 --- a/print/templates/email/letter-debtor-nd/sql/client.sql +++ b/print/templates/email/letter-debtor-nd/sql/client.sql @@ -5,7 +5,6 @@ SELECT be.name AS bankName FROM client c JOIN company AS cny - JOIN supplierAccount AS sa ON - IF (ct.code = 'PT', sa.id = 907, sa.id = cny.supplierAccountFk) + JOIN supplierAccount AS sa ON sa.id = cny.supplierAccountFk JOIN bankEntity be ON be.id = sa.bankEntityFk WHERE c.id = ? AND cny.id = ? \ No newline at end of file diff --git a/print/templates/email/letter-debtor-st/assets/css/import.js b/print/templates/email/letter-debtor-st/assets/css/import.js index 624404a6c..1582b82c5 100644 --- a/print/templates/email/letter-debtor-st/assets/css/import.js +++ b/print/templates/email/letter-debtor-st/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/email.css`]) + `${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/letter-debtor-st/attachments.json b/print/templates/email/letter-debtor-st/attachments.json deleted file mode 100644 index 1e21ea343..000000000 --- a/print/templates/email/letter-debtor-st/attachments.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "filename": "letter-debtor.pdf", - "component": "letter-debtor" - } -] \ No newline at end of file diff --git a/print/templates/email/letter-debtor-st/letter-debtor-st.js b/print/templates/email/letter-debtor-st/letter-debtor-st.js index a514097cf..1a6555673 100755 --- a/print/templates/email/letter-debtor-st/letter-debtor-st.js +++ b/print/templates/email/letter-debtor-st/letter-debtor-st.js @@ -1,23 +1,30 @@ -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'); const attachment = new Component('attachment'); -const attachments = require('./attachments.json'); module.exports = { name: 'letter-debtor-st', async serverPrefetch() { - this.debtor = await this.fetchDebtor(this.recipientId, this.companyId); + this.debtor = await this.fetchDebtor(this.id, this.companyId); if (!this.debtor) throw new Error('Something went wrong'); }, data() { - return {attachments}; + return { + attachments: [ + { + filename: 'letter-debtor.pdf', + type: 'pdf', + path: `Clients/${this.id}/letter-debtor-pdf` + } + ] + }; }, methods: { - fetchDebtor(clientId, companyId) { - return this.findOneFromDef('client', [clientId, companyId]); + fetchDebtor(id, companyId) { + return this.findOneFromDef('client', [id, companyId]); } }, components: { @@ -26,7 +33,7 @@ module.exports = { 'attachment': attachment.build() }, props: { - recipientId: { + id: { type: [Number, String], required: true }, diff --git a/print/templates/email/letter-debtor-st/sql/client.sql b/print/templates/email/letter-debtor-st/sql/client.sql index 479bfac5e..d5da5d0d5 100644 --- a/print/templates/email/letter-debtor-st/sql/client.sql +++ b/print/templates/email/letter-debtor-st/sql/client.sql @@ -5,7 +5,6 @@ SELECT be.name AS bankName FROM client c JOIN company AS cny - JOIN supplierAccount AS sa ON - IF (ct.code = 'PT', sa.id = 907, sa.id = cny.supplierAccountFk) + JOIN supplierAccount AS sa ON sa.id = cny.supplierAccountFk JOIN bankEntity be ON be.id = sa.bankEntityFk WHERE c.id = ? AND cny.id = ? \ No newline at end of file diff --git a/print/templates/email/osticket-report/assets/css/import.js b/print/templates/email/osticket-report/assets/css/import.js index c742fdf90..7360587f7 100644 --- a/print/templates/email/osticket-report/assets/css/import.js +++ b/print/templates/email/osticket-report/assets/css/import.js @@ -1,9 +1,13 @@ -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`, + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`, `${__dirname}/style.css`]) .mergeStyles(); + diff --git a/print/templates/email/osticket-report/osticket-report.js b/print/templates/email/osticket-report/osticket-report.js index 45fadd4f1..48e2202f8 100755 --- a/print/templates/email/osticket-report/osticket-report.js +++ b/print/templates/email/osticket-report/osticket-report.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'); diff --git a/print/templates/email/payment-update/assets/css/import.js b/print/templates/email/payment-update/assets/css/import.js index b44d6bd37..1582b82c5 100644 --- a/print/templates/email/payment-update/assets/css/import.js +++ b/print/templates/email/payment-update/assets/css/import.js @@ -1,8 +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/email.css`]) + `${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/payment-update/payment-update.js b/print/templates/email/payment-update/payment-update.js index 2b92976a3..a9d99d4ef 100755 --- a/print/templates/email/payment-update/payment-update.js +++ b/print/templates/email/payment-update/payment-update.js @@ -1,11 +1,11 @@ -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'); module.exports = { name: 'payment-update', async serverPrefetch() { - this.payMethod = await this.fetchPayMethod(this.recipientId); + this.payMethod = await this.fetchPayMethod(this.id); if (!this.payMethod) throw new Error('Something went wrong'); @@ -16,8 +16,8 @@ module.exports = { }, }, methods: { - fetchPayMethod(clientId) { - return this.findOneFromDef('payMethod', [clientId]); + fetchPayMethod(id) { + return this.findOneFromDef('payMethod', [id]); } }, components: { @@ -25,9 +25,10 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The client id' } } }; diff --git a/print/templates/email/printer-setup/assets/css/import.js b/print/templates/email/printer-setup/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/printer-setup/assets/css/import.js +++ b/print/templates/email/printer-setup/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`]) + `${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/printer-setup/printer-setup.js b/print/templates/email/printer-setup/printer-setup.js index 95dff8ebb..a7d3c40bf 100755 --- a/print/templates/email/printer-setup/printer-setup.js +++ b/print/templates/email/printer-setup/printer-setup.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'); const attachment = new Component('attachment'); @@ -7,14 +7,14 @@ const attachments = require('./attachments.json'); module.exports = { name: 'printer-setup', async serverPrefetch() { - this.client = await this.fetchClient(this.recipientId); + this.client = await this.fetchClient(this.id); }, data() { return {attachments}; }, methods: { - fetchClient(clientId) { - return this.findOneFromDef('client', [clientId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); } }, components: { @@ -23,7 +23,7 @@ module.exports = { 'attachment': attachment.build() }, props: { - recipientId: { + id: { type: [Number, String], required: true } diff --git a/print/templates/email/sepa-core/assets/css/import.js b/print/templates/email/sepa-core/assets/css/import.js index b44d6bd37..1582b82c5 100644 --- a/print/templates/email/sepa-core/assets/css/import.js +++ b/print/templates/email/sepa-core/assets/css/import.js @@ -1,8 +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/email.css`]) + `${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/sepa-core/sepa-core.js b/print/templates/email/sepa-core/sepa-core.js index 743c6719c..00cc527dc 100755 --- a/print/templates/email/sepa-core/sepa-core.js +++ b/print/templates/email/sepa-core/sepa-core.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'); const attachment = new Component('attachment'); @@ -15,7 +15,7 @@ module.exports = { 'attachment': attachment.build() }, props: { - recipientId: { + id: { type: [Number, String], required: true }, diff --git a/print/templates/email/supplier-campaign-metrics/assets/css/import.js b/print/templates/email/supplier-campaign-metrics/assets/css/import.js index b44d6bd37..4b4bb7086 100644 --- a/print/templates/email/supplier-campaign-metrics/assets/css/import.js +++ b/print/templates/email/supplier-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`]) + `${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/supplier-campaign-metrics/supplier-campaign-metrics.js b/print/templates/email/supplier-campaign-metrics/supplier-campaign-metrics.js index 3cf290e4d..9cb9210ef 100755 --- a/print/templates/email/supplier-campaign-metrics/supplier-campaign-metrics.js +++ b/print/templates/email/supplier-campaign-metrics/supplier-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/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..b60a2b7eb 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,9 +24,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The client id' }, from: { required: true diff --git a/print/templates/reports/claim-pickup-order/assets/css/import.js b/print/templates/reports/claim-pickup-order/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/claim-pickup-order/assets/css/import.js +++ b/print/templates/reports/claim-pickup-order/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/claim-pickup-order/claim-pickup-order.html b/print/templates/reports/claim-pickup-order/claim-pickup-order.html index 1f6db4966..6764344b5 100644 --- a/print/templates/reports/claim-pickup-order/claim-pickup-order.html +++ b/print/templates/reports/claim-pickup-order/claim-pickup-order.html @@ -17,7 +17,7 @@ {{$t('claimId')}} - {{claimId}} + {{id}} {{$t('clientId')}} @@ -85,7 +85,7 @@
diff --git a/print/templates/reports/claim-pickup-order/claim-pickup-order.js b/print/templates/reports/claim-pickup-order/claim-pickup-order.js index bf975e9f2..f7d21a2d3 100755 --- a/print/templates/reports/claim-pickup-order/claim-pickup-order.js +++ b/print/templates/reports/claim-pickup-order/claim-pickup-order.js @@ -1,12 +1,12 @@ -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: 'claim-pickup-order', async serverPrefetch() { - this.client = await this.fetchClient(this.claimId); - this.sales = await this.fetchSales(this.claimId); + this.client = await this.fetchClient(this.id); + this.sales = await this.fetchSales(this.id); this.claimConfig = await this.fetchClaimConfig(); if (!this.client) @@ -20,11 +20,11 @@ module.exports = { } }, methods: { - fetchClient(claimId) { - return this.findOneFromDef('client', [claimId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); }, - fetchSales(claimId) { - return this.rawSqlFromDef('sales', [claimId]); + fetchSales(id) { + return this.rawSqlFromDef('sales', [id]); }, fetchClaimConfig() { return this.findOneFromDef('claimConfig'); @@ -35,9 +35,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - claimId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The claim id' } } }; diff --git a/print/templates/reports/client-debt-statement/assets/css/import.js b/print/templates/reports/client-debt-statement/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/client-debt-statement/assets/css/import.js +++ b/print/templates/reports/client-debt-statement/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/client-debt-statement/client-debt-statement.js b/print/templates/reports/client-debt-statement/client-debt-statement.js index f006b0a92..80c83b494 100755 --- a/print/templates/reports/client-debt-statement/client-debt-statement.js +++ b/print/templates/reports/client-debt-statement/client-debt-statement.js @@ -1,12 +1,12 @@ -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: 'client-debt-statement', async serverPrefetch() { - this.client = await this.fetchClient(this.recipientId); - this.sales = await this.fetchSales(this.recipientId, this.from); + this.client = await this.fetchClient(this.id); + this.sales = await this.fetchSales(this.id, this.from); if (!this.client) throw new Error('Something went wrong'); @@ -22,21 +22,21 @@ module.exports = { return {totalBalance: 0.00}; }, methods: { - fetchClient(clientId) { - return this.findOneFromDef('client', [clientId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); }, - fetchSales(clientId, from) { + fetchSales(id, from) { return this.rawSqlFromDef('sales', [ from, - clientId, + id, from, - clientId, + id, from, - clientId, + id, from, - clientId, + id, from, - clientId + id ]); }, getBalance(sale) { @@ -68,9 +68,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The client id' }, from: { required: true diff --git a/print/templates/reports/credit-request/assets/css/import.js b/print/templates/reports/credit-request/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/credit-request/assets/css/import.js +++ b/print/templates/reports/credit-request/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/credit-request/credit-request.js b/print/templates/reports/credit-request/credit-request.js index d04106493..7de1060ca 100755 --- a/print/templates/reports/credit-request/credit-request.js +++ b/print/templates/reports/credit-request/credit-request.js @@ -1,4 +1,4 @@ -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'); diff --git a/print/templates/reports/delivery-note/assets/css/import.js b/print/templates/reports/delivery-note/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/delivery-note/assets/css/import.js +++ b/print/templates/reports/delivery-note/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/delivery-note/delivery-note.html b/print/templates/reports/delivery-note/delivery-note.html index 35f9a2960..d166f3307 100644 --- a/print/templates/reports/delivery-note/delivery-note.html +++ b/print/templates/reports/delivery-note/delivery-note.html @@ -15,7 +15,7 @@
-

{{$t(type)}}

+

{{$t(deliverNoteType)}}

@@ -23,7 +23,7 @@ - + diff --git a/print/templates/reports/delivery-note/delivery-note.js b/print/templates/reports/delivery-note/delivery-note.js index f9dba0578..1037e5129 100755 --- a/print/templates/reports/delivery-note/delivery-note.js +++ b/print/templates/reports/delivery-note/delivery-note.js @@ -1,5 +1,5 @@ -const config = require(`${appPath}/core/config`); -const Component = require(`${appPath}/core/component`); +const config = require(`vn-print/core/config`); +const Component = require(`vn-print/core/component`); const reportHeader = new Component('report-header'); const reportFooter = new Component('report-footer'); const md5 = require('md5'); @@ -7,19 +7,15 @@ const fs = require('fs-extra'); module.exports = { name: 'delivery-note', - created() { - if (!this.type) - this.type = 'deliveryNote'; - }, 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'); @@ -41,6 +37,9 @@ module.exports = { return `data:image/png;base64, ${base64}`; }, + deliverNoteType() { + return this.type ? this.type : 'deliveryNote'; + }, serviceTotal() { let total = 0.00; this.services.forEach(service => { @@ -50,37 +49,37 @@ module.exports = { return total; }, showPrices() { - return this.type != 'withoutPrices'; + return this.deliverNoteType != 'withoutPrices'; }, footerType() { - const translatedType = this.$t(this.type); - return `${translatedType} ${this.ticketId}`; + const translatedType = this.$t(this.deliverNoteType); + 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() { @@ -127,9 +126,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - ticketId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The ticket id' }, type: { type: String, diff --git a/print/templates/reports/driver-route/assets/css/import.js b/print/templates/reports/driver-route/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/driver-route/assets/css/import.js +++ b/print/templates/reports/driver-route/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/driver-route/driver-route.html b/print/templates/reports/driver-route/driver-route.html index 600c49970..96fb6e957 100644 --- a/print/templates/reports/driver-route/driver-route.html +++ b/print/templates/reports/driver-route/driver-route.html @@ -141,7 +141,7 @@
{{client.id}}
{{$t(type)}}{{$t(deliverNoteType)}} {{ticket.id}}
-
+

{{ticket.description}}

@@ -150,7 +150,7 @@
diff --git a/print/templates/reports/driver-route/driver-route.js b/print/templates/reports/driver-route/driver-route.js index c34de37cc..2de3d5192 100755 --- a/print/templates/reports/driver-route/driver-route.js +++ b/print/templates/reports/driver-route/driver-route.js @@ -1,13 +1,18 @@ -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: 'driver-route', async serverPrefetch() { - const routesId = this.routeId.split(','); - const routes = await this.fetchRoutes(routesId); - const tickets = await this.fetchTickets(routesId); + let ids = this.id; + + const hasMultipleRoutes = String(this.id).includes(','); + if (hasMultipleRoutes) + ids = this.id.split(','); + + const routes = await this.fetchRoutes(ids); + const tickets = await this.fetchTickets(ids); const map = new Map(); @@ -26,11 +31,11 @@ module.exports = { throw new Error('Something went wrong'); }, methods: { - fetchRoutes(routesId) { - return this.rawSqlFromDef('routes', [routesId]); + fetchRoutes(ids) { + return this.rawSqlFromDef('routes', [ids]); }, - fetchTickets(routesId) { - return this.rawSqlFromDef('tickets', [routesId, routesId]); + fetchTickets(ids) { + return this.rawSqlFromDef('tickets', [ids, ids]); } }, components: { @@ -38,9 +43,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - routeId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The route id' } } }; diff --git a/print/templates/reports/entry-order/assets/css/import.js b/print/templates/reports/entry-order/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/entry-order/assets/css/import.js +++ b/print/templates/reports/entry-order/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/entry-order/entry-order.js b/print/templates/reports/entry-order/entry-order.js index 52a56bf03..ff4a65e0c 100755 --- a/print/templates/reports/entry-order/entry-order.js +++ b/print/templates/reports/entry-order/entry-order.js @@ -1,13 +1,13 @@ -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: 'entry-order', async serverPrefetch() { - this.supplier = await this.fetchSupplier(this.entryId); - this.entry = await this.fetchEntry(this.entryId); - this.buys = await this.fetchBuys(this.entryId); + this.supplier = await this.fetchSupplier(this.id); + this.entry = await this.fetchEntry(this.id); + this.buys = await this.fetchBuys(this.id); if (!this.entry) throw new Error('Something went wrong'); @@ -16,14 +16,14 @@ module.exports = { return {totalBalance: 0.00}; }, methods: { - fetchSupplier(entryId) { - return this.findOneFromDef('supplier', [entryId]); + fetchSupplier(id) { + return this.findOneFromDef('supplier', [id]); }, - fetchEntry(entryId) { - return this.findOneFromDef('entry', [entryId]); + fetchEntry(id) { + return this.findOneFromDef('entry', [id]); }, - fetchBuys(entryId) { - return this.rawSqlFromDef('buys', [entryId]); + fetchBuys(id) { + return this.rawSqlFromDef('buys', [id]); }, getTotal() { let total = 0.00; @@ -39,9 +39,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - entryId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The entry id' } } }; diff --git a/print/templates/reports/exportation/assets/css/import.js b/print/templates/reports/exportation/assets/css/import.js index a2a9334cb..37a98dfdd 100644 --- a/print/templates/reports/exportation/assets/css/import.js +++ b/print/templates/reports/exportation/assets/css/import.js @@ -1,8 +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/layout.css`, - `${appPath}/common/css/report.css`, - `${appPath}/common/css/misc.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/exportation/exportation.html b/print/templates/reports/exportation/exportation.html index f08af2cdb..252999467 100644 --- a/print/templates/reports/exportation/exportation.html +++ b/print/templates/reports/exportation/exportation.html @@ -31,9 +31,9 @@

({{$t('signature')}})

-

{{$t('signer.name')}}: JUAN VICENTE FERRER ROIG
-
{{$t('signer.ID')}}: 73943586N
-
{{$t('signer.position')}}: ADMINISTRADOR
+
{{$t('signer.name')}}: {{company.manager}}
+
{{$t('signer.ID')}}: {{company.managerFi}}
+
{{$t('signer.position')}}: {{$t('manager')}}

diff --git a/print/templates/reports/exportation/exportation.js b/print/templates/reports/exportation/exportation.js index a7e018c48..630baf421 100755 --- a/print/templates/reports/exportation/exportation.js +++ b/print/templates/reports/exportation/exportation.js @@ -1,18 +1,20 @@ -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: 'exportation', async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.refFk); + this.invoice = await this.fetchInvoice(this.reference); if (!this.invoice) throw new Error('Something went wrong'); + + this.company = await this.findOneFromDef('company', [this.invoice.companyFk]); }, methods: { - fetchInvoice(refFk) { - return this.findOneFromDef('invoice', [refFk]); + fetchInvoice(reference) { + return this.findOneFromDef('invoice', [reference]); } }, computed: { @@ -27,9 +29,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - refFk: { + reference: { type: [Number, String], - required: true + required: true, + description: 'The invoice ref' } } }; diff --git a/print/templates/reports/exportation/locale/es.yml b/print/templates/reports/exportation/locale/es.yml index a689e245b..230263cb9 100644 --- a/print/templates/reports/exportation/locale/es.yml +++ b/print/templates/reports/exportation/locale/es.yml @@ -36,6 +36,7 @@ signer: name: Nombre del firmante ID: DNI del firmante position: Cargo del firmante +manager: Gerente months: - 'Enero' - 'Febrero' diff --git a/print/templates/reports/exportation/sql/company.sql b/print/templates/reports/exportation/sql/company.sql new file mode 100644 index 000000000..3ecef2071 --- /dev/null +++ b/print/templates/reports/exportation/sql/company.sql @@ -0,0 +1,9 @@ +SELECT + s.name, + s.city, + cl.name AS manager, + cl.fi AS managerFi +FROM company c + JOIN supplier s ON s.id = c.id + JOIN client cl ON cl.id = c.workerManagerFk +WHERE c.id = ? \ No newline at end of file diff --git a/print/templates/reports/exportation/sql/invoice.sql b/print/templates/reports/exportation/sql/invoice.sql index 7ea55e481..14e1568e2 100644 --- a/print/templates/reports/exportation/sql/invoice.sql +++ b/print/templates/reports/exportation/sql/invoice.sql @@ -1,7 +1,8 @@ SELECT io.id, io.ref, - io.issued + io.issued, + io.companyFk FROM invoiceOut io LEFT JOIN ticket t ON t.refFk = io.ref WHERE t.refFk = ? \ No newline at end of file diff --git a/print/templates/reports/extra-community/assets/css/import.js b/print/templates/reports/extra-community/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/extra-community/assets/css/import.js +++ b/print/templates/reports/extra-community/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/extra-community/extra-community.js b/print/templates/reports/extra-community/extra-community.js index 4dad5dfff..dec89648a 100755 --- a/print/templates/reports/extra-community/extra-community.js +++ b/print/templates/reports/extra-community/extra-community.js @@ -1,7 +1,7 @@ -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'); -const db = require(`${appPath}/core/database`); +const db = require(`vn-print/core/database`); module.exports = { name: 'extra-community', @@ -82,7 +82,15 @@ module.exports = { let query = this.getSqlFromDef('travels'); query = db.merge(query, where); query = db.merge(query, 'GROUP BY t.id'); - query = db.merge(query, 'ORDER BY `shipped` ASC, `landed` ASC, `travelFk`, `loadPriority`, `agencyModeFk`, `evaNotes`'); + query = db.merge(query, ` + ORDER BY + shipped ASC, + landed ASC, + travelFk, + loadPriority, + agencyModeFk, + evaNotes + `); return this.rawSql(query); }, @@ -99,7 +107,7 @@ module.exports = { 'landedTo', 'shippedFrom', 'continent', - 'ref', + 'reference', 'id', 'agencyModeFk', 'warehouseOutFk', diff --git a/print/templates/reports/incoterms-authorization/assets/css/import.js b/print/templates/reports/incoterms-authorization/assets/css/import.js index a2a9334cb..37a98dfdd 100644 --- a/print/templates/reports/incoterms-authorization/assets/css/import.js +++ b/print/templates/reports/incoterms-authorization/assets/css/import.js @@ -1,8 +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/layout.css`, - `${appPath}/common/css/report.css`, - `${appPath}/common/css/misc.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/incoterms-authorization/incoterms-authorization.js b/print/templates/reports/incoterms-authorization/incoterms-authorization.js index 656a9d7b0..26637b8c2 100755 --- a/print/templates/reports/incoterms-authorization/incoterms-authorization.js +++ b/print/templates/reports/incoterms-authorization/incoterms-authorization.js @@ -1,11 +1,11 @@ -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: 'incoterms-authorization', async serverPrefetch() { - this.client = await this.findOneFromDef('client', [this.recipientId]); + this.client = await this.findOneFromDef('client', [this.id]); this.company = await this.findOneFromDef('company', [this.companyId]); if (!this.client) throw new Error('Something went wrong'); @@ -20,9 +20,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The client id' }, companyId: { type: [Number, String], diff --git a/print/templates/reports/invoice-incoterms/assets/css/import.js b/print/templates/reports/invoice-incoterms/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/invoice-incoterms/assets/css/import.js +++ b/print/templates/reports/invoice-incoterms/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/invoice-incoterms/invoice-incoterms.js b/print/templates/reports/invoice-incoterms/invoice-incoterms.js index 99a4e2e73..3dbe76ac3 100755 --- a/print/templates/reports/invoice-incoterms/invoice-incoterms.js +++ b/print/templates/reports/invoice-incoterms/invoice-incoterms.js @@ -1,13 +1,13 @@ -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: 'invoice-incoterms', async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.refFk); - this.client = await this.fetchClient(this.refFk); - this.incoterms = await this.fetchIncoterms(this.refFk); + this.invoice = await this.fetchInvoice(this.reference); + this.client = await this.fetchClient(this.reference); + this.incoterms = await this.fetchIncoterms(this.reference); if (!this.invoice) throw new Error('Something went wrong'); @@ -16,14 +16,14 @@ module.exports = { }, methods: { - fetchInvoice(refFk) { - return this.findOneFromDef('invoice', [refFk]); + fetchInvoice(reference) { + return this.findOneFromDef('invoice', [reference]); }, - fetchClient(refFk) { - return this.findOneFromDef('client', [refFk]); + fetchClient(reference) { + return this.findOneFromDef('client', [reference]); }, - fetchIncoterms(refFk) { - return this.findOneFromDef('incoterms', [refFk, refFk, refFk]); + fetchIncoterms(reference) { + return this.findOneFromDef('incoterms', [reference, reference, reference]); } }, components: { @@ -31,9 +31,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - refFk: { + reference: { type: [Number, String], - required: true + required: true, + description: 'The invoice ref' } } }; diff --git a/print/templates/reports/invoice/assets/css/import.js b/print/templates/reports/invoice/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/invoice/assets/css/import.js +++ b/print/templates/reports/invoice/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/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index fd4acd4b5..db94a7a12 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -1,5 +1,5 @@ -const Component = require(`${appPath}/core/component`); -const Report = require(`${appPath}/core/report`); +const Component = require(`vn-print/core/component`); +const Report = require(`vn-print/core/report`); const reportHeader = new Component('report-header'); const reportFooter = new Component('report-footer'); const invoiceIncoterms = new Report('invoice-incoterms'); @@ -7,15 +7,15 @@ const invoiceIncoterms = new Report('invoice-incoterms'); module.exports = { name: 'invoice', async serverPrefetch() { - this.invoice = await this.fetchInvoice(this.refFk); - this.client = await this.fetchClient(this.refFk); - this.taxes = await this.fetchTaxes(this.refFk); - this.intrastat = await this.fetchIntrastat(this.refFk); - this.rectified = await this.fetchRectified(this.refFk); - this.hasIncoterms = await this.fetchHasIncoterms(this.refFk); + this.invoice = await this.fetchInvoice(this.reference); + this.client = await this.fetchClient(this.reference); + this.taxes = await this.fetchTaxes(this.reference); + this.intrastat = await this.fetchIntrastat(this.reference); + this.rectified = await this.fetchRectified(this.reference); + this.hasIncoterms = await this.fetchHasIncoterms(this.reference); - const tickets = await this.fetchTickets(this.refFk); - const sales = await this.fetchSales(this.refFk); + const tickets = await this.fetchTickets(this.reference); + const sales = await this.fetchSales(this.reference); const map = new Map(); @@ -65,29 +65,29 @@ module.exports = { } }, methods: { - fetchInvoice(refFk) { - return this.findOneFromDef('invoice', [refFk]); + fetchInvoice(reference) { + return this.findOneFromDef('invoice', [reference]); }, - fetchClient(refFk) { - return this.findOneFromDef('client', [refFk]); + fetchClient(reference) { + return this.findOneFromDef('client', [reference]); }, - fetchTickets(refFk) { - return this.rawSqlFromDef('tickets', [refFk]); + fetchTickets(reference) { + return this.rawSqlFromDef('tickets', [reference]); }, - fetchSales(refFk) { - return this.rawSqlFromDef('sales', [refFk, refFk]); + fetchSales(reference) { + return this.rawSqlFromDef('sales', [reference, reference]); }, - fetchTaxes(refFk) { - return this.rawSqlFromDef(`taxes`, [refFk]); + fetchTaxes(reference) { + return this.rawSqlFromDef(`taxes`, [reference]); }, - fetchIntrastat(refFk) { - return this.rawSqlFromDef(`intrastat`, [refFk, refFk, refFk]); + fetchIntrastat(reference) { + return this.rawSqlFromDef(`intrastat`, [reference, reference, reference]); }, - fetchRectified(refFk) { - return this.rawSqlFromDef(`rectified`, [refFk]); + fetchRectified(reference) { + return this.rawSqlFromDef(`rectified`, [reference]); }, - fetchHasIncoterms(refFk) { - return this.findValueFromDef(`hasIncoterms`, [refFk]); + fetchHasIncoterms(reference) { + return this.findValueFromDef(`hasIncoterms`, [reference]); }, saleImport(sale) { const price = sale.quantity * sale.price; @@ -115,8 +115,9 @@ module.exports = { 'invoice-incoterms': invoiceIncoterms.build() }, props: { - refFk: { - type: String + reference: { + type: String, + description: 'The invoice ref' } } }; diff --git a/print/templates/reports/item-label/assets/css/import.js b/print/templates/reports/item-label/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/item-label/assets/css/import.js +++ b/print/templates/reports/item-label/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/item-label/item-label.js b/print/templates/reports/item-label/item-label.js index 730d8ad99..d03d03cfa 100755 --- a/print/templates/reports/item-label/item-label.js +++ b/print/templates/reports/item-label/item-label.js @@ -1,4 +1,4 @@ -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'); const qrcode = require('qrcode'); @@ -6,9 +6,9 @@ const qrcode = require('qrcode'); module.exports = { name: 'item-label', async serverPrefetch() { - this.item = await this.fetchItem(this.itemId, this.warehouseId); - this.tags = await this.fetchItemTags(this.itemId); - this.barcode = await this.getBarcodeBase64(this.itemId); + this.item = await this.fetchItem(this.id, this.warehouseId); + this.tags = await this.fetchItemTags(this.id); + this.barcode = await this.getBarcodeBase64(this.id); if (!this.item) throw new Error('Something went wrong'); @@ -31,16 +31,18 @@ module.exports = { fetchItem(id, warehouseId) { return this.findOneFromDef('item', [id, warehouseId]); }, - fetchItemTags(itemId) { - return this.rawSqlFromDef('itemTags', [itemId]).then(rows => { + fetchItemTags(id) { + return this.rawSqlFromDef('itemTags', [id]).then(rows => { const tags = {}; rows.forEach(row => tags[row.code] = row.value); return tags; }); }, - getBarcodeBase64(itemId) { - return qrcode.toDataURL(itemId, {margin: 0}); + getBarcodeBase64(id) { + const data = String(id); + + return qrcode.toDataURL(data, {margin: 0}); }, packing() { const stems = this.item.stems ? this.item.stems : 1; @@ -52,17 +54,20 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - itemId: { - required: true + id: { + type: Number, + required: true, + description: 'The item id' }, warehouseId: { + type: Number, required: true }, labelNumber: { - type: String + type: Number }, totalLabels: { - type: String + type: Number } } }; diff --git a/print/templates/reports/letter-debtor/assets/css/import.js b/print/templates/reports/letter-debtor/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/letter-debtor/assets/css/import.js +++ b/print/templates/reports/letter-debtor/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/letter-debtor/letter-debtor.js b/print/templates/reports/letter-debtor/letter-debtor.js index 354b1d8d8..80d4cba9b 100755 --- a/print/templates/reports/letter-debtor/letter-debtor.js +++ b/print/templates/reports/letter-debtor/letter-debtor.js @@ -1,12 +1,12 @@ -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: 'letter-debtor', async serverPrefetch() { - this.client = await this.fetchClient(this.recipientId); - this.sales = await this.fetchSales(this.recipientId, this.companyId); + this.client = await this.fetchClient(this.id); + this.sales = await this.fetchSales(this.id, this.companyId); if (!this.client) throw new Error('Something went wrong'); @@ -22,12 +22,12 @@ module.exports = { return {totalBalance: 0.00}; }, methods: { - fetchClient(clientId) { - return this.findOneFromDef('client', [clientId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); }, - fetchSales(clientId, companyId) { + fetchSales(id, companyId) { return this.findOneFromDef('sales', [ - clientId, + id, companyId ]); }, @@ -62,9 +62,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The client id' }, companyId: { type: [Number, String], diff --git a/print/templates/reports/receipt/assets/css/import.js b/print/templates/reports/receipt/assets/css/import.js index a2a9334cb..37a98dfdd 100644 --- a/print/templates/reports/receipt/assets/css/import.js +++ b/print/templates/reports/receipt/assets/css/import.js @@ -1,8 +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/layout.css`, - `${appPath}/common/css/report.css`, - `${appPath}/common/css/misc.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/receipt/receipt.js b/print/templates/reports/receipt/receipt.js index d7f4dd6da..401aa1ef3 100755 --- a/print/templates/reports/receipt/receipt.js +++ b/print/templates/reports/receipt/receipt.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: 'receipt', async serverPrefetch() { - this.client = await this.fetchClient(this.receiptId); - this.receipt = await this.fetchReceipt(this.receiptId); + this.client = await this.fetchClient(this.id); + this.receipt = await this.fetchReceipt(this.id); if (!this.receipt) throw new Error('Something went wrong'); }, methods: { - fetchClient(receiptId) { - return this.findOneFromDef('client', [receiptId]); + fetchClient(id) { + return this.findOneFromDef('client', [id]); }, - fetchReceipt(receiptId) { - return this.findOneFromDef('receipt', [receiptId]); + fetchReceipt(id) { + return this.findOneFromDef('receipt', [id]); } }, components: { @@ -24,9 +24,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - receiptId: { + id: { type: [Number, String], - required: true + required: true, + description: 'Receipt id' } } }; diff --git a/print/templates/reports/sepa-core/assets/css/import.js b/print/templates/reports/sepa-core/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/sepa-core/assets/css/import.js +++ b/print/templates/reports/sepa-core/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/sepa-core/sepa-core.js b/print/templates/reports/sepa-core/sepa-core.js index 7e3dd3566..73e0beaaa 100755 --- a/print/templates/reports/sepa-core/sepa-core.js +++ b/print/templates/reports/sepa-core/sepa-core.js @@ -1,12 +1,12 @@ -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'); const rptSepaCore = { name: 'sepa-core', async serverPrefetch() { - this.client = await this.fetchClient(this.recipientId, this.companyId); - this.supplier = await this.fetchSupplier(this.recipientId, this.companyId); + this.client = await this.fetchClient(this.id, this.companyId); + this.supplier = await this.fetchSupplier(this.id, this.companyId); if (!this.client) throw new Error('Something went wrong'); @@ -19,18 +19,18 @@ const rptSepaCore = { } }, methods: { - fetchClient(clientId, companyId) { + fetchClient(id, companyId) { return this.findOneFromDef('client', [ companyId, companyId, - clientId + id ]); }, - fetchSupplier(clientId, companyId) { + fetchSupplier(id, companyId) { return this.findOneFromDef('supplier', [ companyId, companyId, - clientId + id ]); } }, @@ -39,9 +39,10 @@ const rptSepaCore = { 'report-footer': reportFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The client id' }, companyId: { type: [Number, String], diff --git a/print/templates/reports/supplier-campaign-metrics/assets/css/import.js b/print/templates/reports/supplier-campaign-metrics/assets/css/import.js index fd8796c2b..37a98dfdd 100644 --- a/print/templates/reports/supplier-campaign-metrics/assets/css/import.js +++ b/print/templates/reports/supplier-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/supplier-campaign-metrics/supplier-campaign-metrics.js b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.js index 1a460daa9..6a58cbd0e 100755 --- a/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.js +++ b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.js @@ -1,12 +1,12 @@ -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: 'supplier-campaign-metrics', async serverPrefetch() { - this.supplier = await this.fetchSupplier(this.recipientId); - let entries = await this.fetchEntries(this.recipientId, this.from, this.to); + this.supplier = await this.fetchSupplier(this.id); + let entries = await this.fetchEntries(this.id, this.from, this.to); const entriesId = []; @@ -48,9 +48,10 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - recipientId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The supplier id' }, from: { required: true diff --git a/print/templates/reports/zone/assets/css/import.js b/print/templates/reports/zone/assets/css/import.js index a2a9334cb..37a98dfdd 100644 --- a/print/templates/reports/zone/assets/css/import.js +++ b/print/templates/reports/zone/assets/css/import.js @@ -1,8 +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/layout.css`, - `${appPath}/common/css/report.css`, - `${appPath}/common/css/misc.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/zone/zone.js b/print/templates/reports/zone/zone.js index d611e1e53..bbce9df36 100755 --- a/print/templates/reports/zone/zone.js +++ b/print/templates/reports/zone/zone.js @@ -1,20 +1,21 @@ module.exports = { name: 'zone', async serverPrefetch() { - this.zone = await this.fetchZone(this.routeId); + this.zone = await this.fetchZone(this.id); if (!this.zone) throw new Error('Something went wrong'); }, methods: { - fetchZone(routeId) { - return this.findOneFromDef('zone', [routeId]); + fetchZone(id) { + return this.findOneFromDef('zone', [id]); } }, props: { - routeId: { + id: { type: [Number, String], - required: true + required: true, + description: 'The zone id' } } };