const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self) { Self.remoteMethodCtx('invoiceTickets', { description: 'Make out an invoice from one or more tickets', accessType: 'WRITE', accepts: [ { arg: 'ticketsIds', description: 'The tickets id', type: ['number'], required: true }, { arg: 'invoiceCorrection', description: 'The invoice correction', type: 'object', } ], returns: { type: ['object'], root: true }, http: { path: `/invoiceTickets`, verb: 'POST' } }); Self.invoiceTickets = async(ctx, ticketsIds, invoiceCorrection, options) => { const models = Self.app.models; const date = Date.vnNew(); date.setHours(0, 0, 0, 0); const myOptions = {userId: ctx.req.accessToken.userId}; let tx; if (typeof options === 'object') Object.assign(myOptions, options); if (!myOptions.transaction) { tx = await Self.beginTransaction({}); myOptions.transaction = tx; } let invoicesIds = []; try { const tickets = await models.Ticket.find({ fields: ['id', 'clientFk', 'companyFk', 'addressFk'], where: { id: {inq: ticketsIds} } }, myOptions); const [firstTicket] = tickets; const clientId = firstTicket.clientFk; const companyId = firstTicket.companyFk; const isSameClient = tickets.every(ticket => ticket.clientFk === clientId); if (!isSameClient) throw new UserError(`You can't invoice tickets from multiple clients`); const {hasToInvoiceByAddress} = await models.Client.findById(clientId, { fields: ['hasToInvoiceByAddress'] }, myOptions); let ticketsByAddress = hasToInvoiceByAddress ? Object.values(tickets.reduce((group, {id, addressFk}) => { group[addressFk] = group[addressFk] ?? []; group[addressFk].push(id); return group; }, {})) : [ticketsIds]; for (const ticketIds of ticketsByAddress) invoicesIds.push(await createInvoice(ctx, companyId, ticketIds, invoiceCorrection, myOptions)); tx && await tx.commit(); } catch (e) { if (tx) await tx.rollback(); throw e; } return invoicesIds; }; async function createInvoice(ctx, companyId, ticketsIds, invoiceCorrection, myOptions) { const models = Self.app.models; await models.Ticket.rawSql(` CREATE OR REPLACE TEMPORARY TABLE tmp.ticketToInvoice (PRIMARY KEY (id)) ENGINE = MEMORY SELECT id FROM vn.ticket WHERE id IN (?) `, [ticketsIds], myOptions); return models.Ticket.makeInvoice(ctx, 'quick', companyId, Date.vnNew(), invoiceCorrection, myOptions); } };