Closure refactor

This commit is contained in:
Joan Sanchez 2022-01-17 12:33:11 +01:00
parent 63ea0902d1
commit 7d16d7aaf2
14 changed files with 244 additions and 27 deletions

View File

@ -104,17 +104,17 @@ INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`)
(3, 'GBP', 'Libra', 1), (3, 'GBP', 'Libra', 1),
(4, 'JPY', 'Yen Japones', 1); (4, 'JPY', 'Yen Japones', 1);
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`) INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`, `hasDailyInvoice`, `CEE`)
VALUES VALUES
(1, 'España', 1, 'ES', 1, 24, 4), (1, 'España', 1, 'ES', 1, 24, 4, 0, 1),
(2, 'Italia', 1, 'IT', 1, 27, 4), (2, 'Italia', 1, 'IT', 1, 27, 4, 0, 1),
(3, 'Alemania', 1, 'DE', 1, 22, 4), (3, 'Alemania', 1, 'DE', 1, 22, 4, 0, 1),
(4, 'Rumania', 1, 'RO', 1, 24, 4), (4, 'Rumania', 1, 'RO', 1, 24, 4, 0, 1),
(5, 'Holanda', 1, 'NL', 1, 18, 4), (5, 'Holanda', 1, 'NL', 1, 18, 4, 0, 1),
(8, 'Portugal', 1, 'PT', 1, 27, 4), (8, 'Portugal', 1, 'PT', 1, 27, 4, 0, 1),
(13,'Ecuador', 0, 'EC', 1, 24, 2), (13,'Ecuador', 0, 'EC', 1, 24, 2, 1, 2),
(19,'Francia', 1, 'FR', 1, 27, 4), (19,'Francia', 1, 'FR', 1, 27, 4, 0, 1),
(30,'Canarias', 1, 'IC', 1, 24, 4); (30,'Canarias', 1, 'IC', 1, 24, 4, 1, 2);
INSERT INTO `hedera`.`language` (`code`, `name`, `orgName`, `isActive`) INSERT INTO `hedera`.`language` (`code`, `name`, `orgName`, `isActive`)
VALUES VALUES
@ -243,7 +243,7 @@ INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `autonomyFk`, `warehouseF
VALUES VALUES
(1, 'Province one', 1, 1, NULL), (1, 'Province one', 1, 1, NULL),
(2, 'Province two', 1, 1, NULL), (2, 'Province two', 1, 1, NULL),
(3, 'Province three', 1, 2, NULL), (3, 'Province three', 30, 2, NULL),
(4, 'Province four', 2, 3, NULL), (4, 'Province four', 2, 3, NULL),
(5, 'Province five', 13, 4, NULL); (5, 'Province five', 13, 4, NULL);
@ -486,7 +486,9 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF
('A', 'Global nacional', 1, 'NATIONAL', 0), ('A', 'Global nacional', 1, 'NATIONAL', 0),
('T', 'Española rapida', 1, 'NATIONAL', 0), ('T', 'Española rapida', 1, 'NATIONAL', 0),
('V', 'Intracomunitaria global', 0, 'CEE', 1), ('V', 'Intracomunitaria global', 0, 'CEE', 1),
('M', 'Múltiple nacional', 1, 'NATIONAL', 0); ('M', 'Múltiple nacional', 1, 'NATIONAL', 0),
('E', 'Exportación rápida', 0, 'WORLD', 0);
;
INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`)
VALUES VALUES

View File

@ -1,5 +1,6 @@
const db = require('vn-print/core/database'); const db = require('vn-print/core/database');
const closure = require('./closure'); const closure = require('./closure');
module.exports = async function(request, response, next) { module.exports = async function(request, response, next) {
try { try {
const reqArgs = request.query; const reqArgs = request.query;
@ -40,9 +41,8 @@ module.exports = async function(request, response, next) {
AND t.refFk IS NULL AND t.refFk IS NULL
GROUP BY t.id`, [reqArgs.to, reqArgs.to]); GROUP BY t.id`, [reqArgs.to, reqArgs.to]);
await closure.start(tickets); await closure.start(tickets, response.locals);
// await closeAll(ticketIds, req.args);
await db.rawSql(` await db.rawSql(`
UPDATE ticket t UPDATE ticket t
JOIN ticketState ts ON t.id = ts.ticketFk JOIN ticketState ts ON t.id = ts.ticketFk

View File

@ -0,0 +1,46 @@
const db = require('vn-print/core/database');
const closure = require('./closure');
module.exports = async function(request, response, next) {
try {
const reqArgs = request.query;
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');
response.status(200).json({
message: 'Success'
});
const agencyIds = reqArgs.agencyModeId.split(',');
const tickets = await db.rawSql(`
SELECT
t.id
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
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);
} catch (error) {
next(error);
}
};

View File

@ -0,0 +1,49 @@
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.query;
if (!reqArgs.routeId)
throw new Error('The argument routeId is required');
response.status(200).json({
message: 'Success'
});
const tickets = await db.rawSql(`
SELECT
t.id
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
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();
}
} catch (error) {
next(error);
}
};

View File

@ -0,0 +1,31 @@
const db = require('vn-print/core/database');
const closure = require('./closure');
module.exports = async function(request, response, next) {
try {
const reqArgs = request.query;
if (!reqArgs.ticketId)
throw new Error('The argument ticketId is required');
response.status(200).json({
message: 'Success'
});
const tickets = await db.rawSql(`
SELECT
t.id
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
WHERE al.code = 'PACKED'
AND t.id = ?
AND t.refFk IS NULL
GROUP BY e.ticketFk`, [reqArgs.ticketId]);
await closure.start(tickets, response.locals);
} catch (error) {
next(error);
}
};

View File

@ -1,7 +1,12 @@
const db = require('vn-print/core/database');
const Report = require('vn-print/core/report'); // Put inside block to avoid circular dependency const Report = require('vn-print/core/report'); // Put inside block to avoid circular dependency
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 = { module.exports = {
async start(tickets) { async start(tickets, reqArgs) {
if (tickets.length == 0) return; if (tickets.length == 0) return;
const failedtickets = []; const failedtickets = [];
@ -17,14 +22,21 @@ module.exports = {
WHERE t.id = ? WHERE t.id = ?
`, [ticket.id]); `, [ticket.id]);
const mailOptions = { const mailOptions = {
overrideAttachments: true, overrideAttachments: true,
attachments: [] attachments: []
}; };
// Store invoice const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed;
if (invoiceOut) { if (invoiceOut) {
const args = Object.assign({
invoiceId: invoiceOut.id,
recipientId: ticket.clientFk,
recipient: ticket.recipient,
replyTo: ticket.salesPersonEmail
}, reqArgs);
const invoiceReport = new Report('invoice', args); const invoiceReport = new Report('invoice', args);
const stream = await invoiceReport.toPdfStream(); const stream = await invoiceReport.toPdfStream();
@ -35,19 +47,46 @@ module.exports = {
const fileName = `${year}${invoiceOut.ref}.pdf`; const fileName = `${year}${invoiceOut.ref}.pdf`;
// Store invoice
storage.write(stream, { storage.write(stream, {
type: 'invoice', type: 'invoice',
path: `${year}/${month}/${day}`, path: `${year}/${month}/${day}`,
fileName: fileName fileName: fileName
}); });
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({ mailOptions.attachments.push({
filename: fileName, filename: fileName,
content: stream 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();
}
} catch (error) { } catch (error) {
// Domain not found // Domain not found
if (error.responseCode == 450) if (error.responseCode == 450)
@ -60,4 +99,49 @@ module.exports = {
}); });
} }
} }
// 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 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
});
}
}; };

View File

@ -2,6 +2,8 @@ const express = require('express');
const router = new express.Router(); const router = new express.Router();
router.get('/all', require('./closeAll')); router.get('/all', require('./closeAll'));
// router.get('/byTicket', require('./preview')); router.get('/by-ticket', require('./closeByTicket'));
router.get('/by-agency', require('./closeByAgency'));
router.get('/by-route', require('./closeByRoute'));
module.exports = router; module.exports = router;

View File

@ -18,7 +18,7 @@ module.exports = {
}, },
props: { props: {
invoiceId: { invoiceId: {
type: String, type: Number,
required: true required: true
} }
} }

View File

@ -39,6 +39,7 @@ module.exports = {
}, },
props: { props: {
routeId: { routeId: {
type: Number,
required: true required: true
} }
} }

View File

@ -1,3 +1,4 @@
reportName: 'hoja_de_ruta'
title: Hoja de ruta title: Hoja de ruta
information: Información information: Información
date: Fecha date: Fecha

View File

@ -28,6 +28,7 @@ module.exports = {
}, },
props: { props: {
invoiceId: { invoiceId: {
type: Number,
required: true required: true
} }
} }

View File

@ -32,7 +32,7 @@ module.exports = {
}, },
props: { props: {
invoiceId: { invoiceId: {
type: String, type: Number,
required: true required: true
} }
} }

View File

@ -115,7 +115,7 @@ module.exports = {
}, },
props: { props: {
invoiceId: { invoiceId: {
type: String, type: Number,
required: true required: true
} }
} }