salix/modules/ticket/back/methods/ticket/makeInvoice.js

105 lines
3.5 KiB
JavaScript

const UserError = require('vn-loopback/util/user-error');
module.exports = function(Self) {
Self.remoteMethodCtx('makeInvoice', {
description: 'Make out an invoice from one or more tickets',
accessType: 'WRITE',
accepts: [
{
arg: 'invoiceType',
description: 'The invoice type',
type: 'string',
required: true
},
{
arg: 'companyFk',
description: 'The company id',
type: 'number',
required: true
},
{
arg: 'invoiceDate',
description: 'The invoice date',
type: 'date',
required: true
}
],
returns: {
type: ['object'],
root: true
},
http: {
path: `/makeInvoice`,
verb: 'POST'
}
});
Self.makeInvoice = async(ctx, invoiceType, companyFk, invoiceDate, options) => {
const models = Self.app.models;
invoiceDate.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;
}
try {
const ticketToInvoice = await Self.rawSql(`
SELECT id
FROM tmp.ticketToInvoice`, null, myOptions);
const ticketsIds = ticketToInvoice.map(ticket => ticket.id);
const tickets = await models.Ticket.find({
where: {
id: {inq: ticketsIds}
},
fields: ['id', 'clientFk', 'addressFk']
}, myOptions);
await models.Ticket.canBeInvoiced(ctx, ticketsIds, myOptions);
const [firstTicket] = tickets;
const clientId = firstTicket.clientFk;
const clientCanBeInvoiced = await models.Client.canBeInvoiced(clientId, companyFk, myOptions);
if (!clientCanBeInvoiced)
throw new UserError(`This client can't be invoiced`);
const query = `SELECT vn.invoiceSerial(?, ?, ?) AS serial`;
const [{serial}] = await Self.rawSql(query, [
clientId,
companyFk,
invoiceType,
], myOptions);
const invoiceOutSerial = await models.InvoiceOutSerial.findById(serial);
if (invoiceOutSerial?.taxAreaFk == 'WORLD') {
const address = await models.Address.findById(firstTicket.addressFk);
if (!address || !address.customsAgentFk || !address.incotermsFk)
throw new UserError('Incoterms data for consignee is missing');
}
await Self.rawSql('CALL invoiceOut_new(?, ?, null, @invoiceId)', [serial, invoiceDate], myOptions);
const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions);
if (!resultInvoice)
throw new UserError('No tickets to invoice', 'notInvoiced');
if (serial != 'R' && resultInvoice.id)
await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions);
if (tx) await tx.commit();
return resultInvoice.id;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};