const db = require('../core/database'); const Email = require('../core/email'); const Report = require('../core/report'); const smtp = require('../core/smtp'); const config = require('../core/config'); module.exports = app => { app.get('/api/closure/all', async function(req, res, next) { try { const reqArgs = req.args; if (!reqArgs.to) throw new Error('The argument to is required'); res.status(200).json({ message: 'Task executed successfully' }); const tickets = await db.rawSql(` SELECT t.id FROM expedition e JOIN ticket t ON t.id = e.ticketFk 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 WHERE al.code = 'PACKED' AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) AND util.dayEnd(?) AND t.refFk IS NULL GROUP BY e.ticketFk`, [reqArgs.to, reqArgs.to]); const ticketIds = tickets.map(ticket => ticket.id); await closeAll(ticketIds, req.args); 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%'`, [reqArgs.to, reqArgs.to]); } catch (error) { next(error); } }); app.get('/api/closure/by-ticket', async function(req, res, next) { try { const reqArgs = req.args; if (!reqArgs.ticketId) throw new Error('The argument ticketId is required'); res.status(200).json({ message: 'Task executed successfully' }); 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]); const ticketIds = tickets.map(ticket => ticket.id); await closeAll(ticketIds, reqArgs); } catch (error) { next(error); } }); app.get('/api/closure/by-agency', async function(req, res, next) { try { const reqArgs = req.args; 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'); res.status(200).json({ message: 'Task executed successfully' }); const agenciesId = 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(:to, INTERVAL -2 DAY) AND util.dayEnd(?) AND t.refFk IS NULL GROUP BY e.ticketFk`, [ agenciesId, reqArgs.warehouseId, reqArgs.to, reqArgs.to ]); const ticketIds = tickets.map(ticket => ticket.id); await closeAll(ticketIds, reqArgs); } catch (error) { next(error); } }); app.get('/api/closure/by-route', async function(req, res, next) { try { const reqArgs = req.args; if (!reqArgs.routeId) throw new Error('The argument routeId is required'); res.status(200).json({ message: 'Task executed successfully' }); 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]); const ticketIds = tickets.map(ticket => ticket.id); await closeAll(ticketIds, reqArgs); // 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: reqArgs.routeId, recipient: agencyMail }, reqArgs); const email = new Email('driver-route', args); await email.send(); } } catch (error) { next(error); } }); async function closeAll(ticketIds, reqArgs) { const failedtickets = []; const tickets = await db.rawSql(` SELECT t.id, t.clientFk, c.name clientName, c.email recipient, c.salesPersonFk, c.isToBeMailed, c.hasToInvoice, co.hasDailyInvoice, eu.email salesPersonEmail FROM ticket t 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 t.id IN(?)`, [ticketIds]); for (const ticket of tickets) { try { await db.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id]); if (!ticket.salesPersonFk || !ticket.isToBeMailed) continue; if (!ticket.recipient) { const body = `No se ha podido enviar el albarán ${ticket.id} al cliente ${ticket.clientFk} porque no tiene un email especificado.

Para dejar de recibir esta notificación, asígnale un email o desactiva la notificación por email para este cliente.`; smtp.send({ to: ticket.salesPersonEmail, subject: 'No se ha podido enviar el albarán', html: body }); continue; } const hasToInvoice = ticket.hasToInvoice && ticket.hasDailyInvoice; if (hasToInvoice) { const invoice = await db.findOne(` SELECT io.id, io.ref, io.serial, cny.code companyCode 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 args = Object.assign({ invoiceId: invoice.id, recipientId: ticket.clientFk, recipient: ticket.recipient, replyTo: ticket.salesPersonEmail }, reqArgs); let mailOptions = {}; if (invoice.serial == 'E' && invoice.companyCode == 'VNL') { const exportation = new Report('exportation', args); const stream = await exportation.toPdfStream(); const fileName = `exportation-${invoice.ref}.pdf`; mailOptions = { overrideAttachments: false, attachments: [{ filename: fileName, content: stream }] }; } const email = new Email('invoice', args); await email.send(mailOptions); } else { 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) { // 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 (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 }); } };