Client consumption queue
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
parent
7a7ad6ac5f
commit
3601881026
|
@ -1,5 +1,6 @@
|
||||||
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
VALUES
|
VALUES
|
||||||
|
('ClientConsumptionQueue', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
|
||||||
('Ticket', 'deliveryNotePdf', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
('Ticket', 'deliveryNotePdf', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
('Ticket', 'deliveryNoteEmail', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
('Ticket', 'deliveryNoteEmail', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
('Client', 'campaignMetricsPdf', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
('Client', 'campaignMetricsPdf', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
@ -17,6 +18,7 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalTyp
|
||||||
('Client', 'clientDebtStatementEmail', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
('Client', 'clientDebtStatementEmail', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
('Client', 'incotermsAuthorizationHtml', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
('Client', 'incotermsAuthorizationHtml', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
('Client', 'incotermsAuthorizationEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
|
('Client', 'incotermsAuthorizationEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Client', 'consumptionSendQueued', 'WRITE', 'ALLOW', 'ROLE', 'system'),
|
||||||
('InvoiceOut', 'invoiceEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
|
('InvoiceOut', 'invoiceEmail', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
|
||||||
('InvoiceOut', 'exportationPdf', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
('InvoiceOut', 'exportationPdf', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
('InvoiceOut', 'sendQueued', 'WRITE', 'ALLOW', 'ROLE', 'system'),
|
('InvoiceOut', 'sendQueued', 'WRITE', 'ALLOW', 'ROLE', 'system'),
|
||||||
|
|
|
@ -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';
|
|
@ -0,0 +1 @@
|
||||||
|
rename table `vn`.`invoiceOut_queue` to `vn`.`invoiceOutQueue`;
|
|
@ -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'
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -26,6 +26,9 @@
|
||||||
"ClientCreditLimit": {
|
"ClientCreditLimit": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"ClientConsumptionQueue": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"ClientLog": {
|
"ClientLog": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "ClientConsumptionQueue",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "clientConsumptionQueue"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"params": {
|
||||||
|
"type": "json"
|
||||||
|
},
|
||||||
|
"queued": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"printed": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"client": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Client",
|
||||||
|
"foreignKey": "clientFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,4 +42,5 @@ module.exports = Self => {
|
||||||
require('../methods/client/creditRequestEmail')(Self);
|
require('../methods/client/creditRequestEmail')(Self);
|
||||||
require('../methods/client/incotermsAuthorizationHtml')(Self);
|
require('../methods/client/incotermsAuthorizationHtml')(Self);
|
||||||
require('../methods/client/incotermsAuthorizationEmail')(Self);
|
require('../methods/client/incotermsAuthorizationEmail')(Self);
|
||||||
|
require('../methods/client/consumptionSendQueued')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,13 +77,15 @@ export default class Controller extends Section {
|
||||||
|
|
||||||
onSendClientConsumption() {
|
onSendClientConsumption() {
|
||||||
const clientIds = this.checked.map(client => client.id);
|
const clientIds = this.checked.map(client => client.id);
|
||||||
const params = Object.assign({
|
const params = {
|
||||||
clientIds: clientIds
|
clients: clientIds,
|
||||||
}, this.campaign);
|
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.$.filters.hide())
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Notifications sent!')));
|
.then(() => this.vnApp.showSuccess(this.$t('Notifications queued')));
|
||||||
}
|
}
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
exprBuilder(param, value) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ module.exports = Self => {
|
||||||
c.hasToInvoice,
|
c.hasToInvoice,
|
||||||
co.hasDailyInvoice,
|
co.hasDailyInvoice,
|
||||||
eu.email salesPersonEmail
|
eu.email salesPersonEmail
|
||||||
FROM invoiceOut_queue ioq
|
FROM invoiceOutQueue ioq
|
||||||
JOIN invoiceOut io ON io.id = ioq.invoiceFk
|
JOIN invoiceOut io ON io.id = ioq.invoiceFk
|
||||||
JOIN client c ON c.id = io.clientFk
|
JOIN client c ON c.id = io.clientFk
|
||||||
JOIN province p ON p.id = c.provinceFk
|
JOIN province p ON p.id = c.provinceFk
|
||||||
|
|
|
@ -1,72 +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;
|
|
||||||
|
|
||||||
let toDate = new Date();
|
|
||||||
toDate.setDate(toDate.getDate() - 1);
|
|
||||||
|
|
||||||
if (reqArgs.to) toDate = reqArgs.to;
|
|
||||||
|
|
||||||
const todayMinDate = new Date();
|
|
||||||
minDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const todayMaxDate = new Date();
|
|
||||||
maxDate.setHours(23, 59, 59, 59);
|
|
||||||
|
|
||||||
// Prevent closure for current day
|
|
||||||
if (toDate >= todayMinDate && toDate <= todayMaxDate)
|
|
||||||
throw new Error('You cannot close tickets for today');
|
|
||||||
|
|
||||||
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 ticket t
|
|
||||||
JOIN agencyMode am ON am.id = t.agencyModeFk
|
|
||||||
JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission
|
|
||||||
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 DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY)
|
|
||||||
AND util.dayEnd(?)
|
|
||||||
AND t.refFk IS NULL
|
|
||||||
GROUP BY t.id`, [toDate, toDate]);
|
|
||||||
|
|
||||||
await closure.start(tickets, response.locals);
|
|
||||||
|
|
||||||
await db.rawSql(`
|
|
||||||
UPDATE ticket t
|
|
||||||
JOIN ticketState ts ON t.id = ts.ticketFk
|
|
||||||
JOIN alertLevel al ON al.id = ts.alertLevel
|
|
||||||
JOIN agencyMode am ON am.id = t.agencyModeFk
|
|
||||||
JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
|
|
||||||
JOIN zone z ON z.id = t.zoneFk
|
|
||||||
SET t.routeFk = NULL
|
|
||||||
WHERE DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY)
|
|
||||||
AND util.dayEnd(?)
|
|
||||||
AND al.code NOT IN('DELIVERED','PACKED')
|
|
||||||
AND t.routeFk
|
|
||||||
AND z.name LIKE '%MADRID%'`, [toDate, toDate]);
|
|
||||||
|
|
||||||
response.status(200).json({
|
|
||||||
message: 'Success'
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,62 +0,0 @@
|
||||||
const db = require('vn-print/core/database');
|
|
||||||
const Email = require('vn-print/core/email');
|
|
||||||
const closure = require('./closure');
|
|
||||||
|
|
||||||
module.exports = async function(request, response, next) {
|
|
||||||
try {
|
|
||||||
const reqArgs = request.body;
|
|
||||||
|
|
||||||
if (!reqArgs.routeId)
|
|
||||||
throw new Error('The argument routeId is required');
|
|
||||||
|
|
||||||
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.routeFk = ?
|
|
||||||
AND t.refFk IS NULL
|
|
||||||
GROUP BY e.ticketFk`, [reqArgs.routeId]);
|
|
||||||
|
|
||||||
await closure.start(tickets, response.locals);
|
|
||||||
|
|
||||||
// Send route report to the agency
|
|
||||||
const agencyMail = await db.findValue(`
|
|
||||||
SELECT am.reportMail
|
|
||||||
FROM route r
|
|
||||||
JOIN agencyMode am ON am.id = r.agencyModeFk
|
|
||||||
WHERE r.id = ?`, [reqArgs.routeId]);
|
|
||||||
|
|
||||||
if (agencyMail) {
|
|
||||||
const args = Object.assign({
|
|
||||||
routeId: Number.parseInt(reqArgs.routeId),
|
|
||||||
recipient: agencyMail
|
|
||||||
}, response.locals);
|
|
||||||
|
|
||||||
const email = new Email('driver-route', args);
|
|
||||||
await email.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
response.status(200).json({
|
|
||||||
message: 'Success'
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,44 +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.ticketId)
|
|
||||||
throw new Error('The argument ticketId is required');
|
|
||||||
|
|
||||||
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.id = ?
|
|
||||||
AND t.refFk IS NULL
|
|
||||||
GROUP BY e.ticketFk`, [reqArgs.ticketId]);
|
|
||||||
|
|
||||||
await closure.start(tickets, response.locals);
|
|
||||||
|
|
||||||
response.status(200).json({
|
|
||||||
message: 'Success'
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,181 +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) {
|
|
||||||
if (tickets.length == 0) return;
|
|
||||||
|
|
||||||
const failedtickets = [];
|
|
||||||
for (const ticket of tickets) {
|
|
||||||
try {
|
|
||||||
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:<br/><br/>';
|
|
||||||
|
|
||||||
for (const ticket of failedtickets) {
|
|
||||||
body += `Ticket: <strong>${ticket.id}</strong>
|
|
||||||
<br/> <strong>${ticket.stacktrace}</strong><br/><br/>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 <strong>${ticket.id}</strong>
|
|
||||||
al cliente <strong>${ticket.clientFk} - ${ticket.clientName}</strong>
|
|
||||||
porque la dirección de email <strong>"${ticket.recipient}"</strong> no es correcta
|
|
||||||
o no está disponible.<br/><br/>
|
|
||||||
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
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -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;
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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;
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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;
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,22 +1,6 @@
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
|
||||||
url: '/api/report',
|
|
||||||
cb: require('./report')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: '/api/email',
|
|
||||||
cb: require('./email')
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
url: '/api/csv',
|
url: '/api/csv',
|
||||||
cb: require('./csv')
|
cb: require('./csv')
|
||||||
},
|
|
||||||
{
|
|
||||||
url: '/api/closure',
|
|
||||||
cb: require('./closure')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: '/api/schedule',
|
|
||||||
cb: require('./schedule')
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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;
|
|
|
@ -1,115 +0,0 @@
|
||||||
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');
|
|
||||||
|
|
||||||
module.exports = async function(request, response, next) {
|
|
||||||
try {
|
|
||||||
response.status(200).json({
|
|
||||||
message: 'Success'
|
|
||||||
});
|
|
||||||
|
|
||||||
const invoices = await db.rawSql(`
|
|
||||||
SELECT
|
|
||||||
io.id,
|
|
||||||
io.clientFk,
|
|
||||||
io.issued,
|
|
||||||
io.ref,
|
|
||||||
c.email recipient,
|
|
||||||
c.salesPersonFk,
|
|
||||||
c.isToBeMailed,
|
|
||||||
c.hasToInvoice,
|
|
||||||
co.hasDailyInvoice,
|
|
||||||
eu.email salesPersonEmail
|
|
||||||
FROM invoiceOut_queue 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
|
|
||||||
JOIN country co ON co.id = p.countryFk
|
|
||||||
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 args = Object.assign({
|
|
||||||
refFk: invoiceOut.ref,
|
|
||||||
recipientId: invoiceOut.clientFk,
|
|
||||||
recipient: invoiceOut.recipient,
|
|
||||||
replyTo: invoiceOut.salesPersonEmail
|
|
||||||
}, response.locals);
|
|
||||||
|
|
||||||
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
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.query('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id]);
|
|
||||||
|
|
||||||
const isToBeMailed = invoiceOut.recipient && invoiceOut.salesPersonFk && invoiceOut.isToBeMailed;
|
|
||||||
|
|
||||||
if (isToBeMailed) {
|
|
||||||
const mailOptions = {
|
|
||||||
overrideAttachments: true,
|
|
||||||
attachments: []
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
// Update queue status
|
|
||||||
const date = new Date();
|
|
||||||
sql = `UPDATE invoiceOut_queue
|
|
||||||
SET status = "printed",
|
|
||||||
printed = ?
|
|
||||||
WHERE invoiceFk = ?`;
|
|
||||||
connection.query(sql, [date, invoiceOut.id]);
|
|
||||||
connection.query('COMMIT');
|
|
||||||
} catch (error) {
|
|
||||||
connection.query('ROLLBACK');
|
|
||||||
connection.release();
|
|
||||||
sql = `UPDATE invoiceOut_queue
|
|
||||||
SET status = ?
|
|
||||||
WHERE invoiceFk = ?`;
|
|
||||||
await db.rawSql(sql, [error.message, invoiceId]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
};
|
|
Loading…
Reference in New Issue