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

194 lines
6.3 KiB
JavaScript

let UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('transferSales', {
description: 'Transfer sales to a new or a given ticket',
accepts: [{
arg: 'id',
type: 'Number',
required: true,
description: 'Origin ticket id',
http: {source: 'path'}
},
{
arg: 'ticketId',
type: 'Number',
description: 'Destination ticket id',
required: false
},
{
arg: 'sales',
type: ['Object'],
description: 'The sales to transfer',
required: true
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/:id/transferSales`,
verb: 'POST'
}
});
Self.transferSales = async(ctx, id, ticketId, sales) => {
let userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const isEditable = await models.Ticket.isEditable(ctx, id);
if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`);
if (ticketId) {
const isReceiverEditable = await models.Ticket.isEditable(ctx, ticketId);
if (!isReceiverEditable)
throw new UserError(`The sales of the receiver ticket can't be modified`);
}
let tx = await Self.beginTransaction({});
try {
const options = {transaction: tx};
const originalTicket = await models.Ticket.findById(id, null, options);
const originalSales = await models.Sale.find({
where: {ticketFk: id}
}, options);
if (!ticketId)
ticketId = await cloneTicket(ctx, originalTicket, options);
const map = new Map();
for (const sale of originalSales)
map.set(sale.id, sale);
for (const sale of sales) {
const originalSale = map.get(sale.id);
let originalSaleQuantity = originalSale.quantity;
if (sale.quantity == originalSale.quantity) {
await models.Sale.updateAll({
id: sale.id
}, {ticketFk: ticketId}, options);
} else if (sale.quantity < originalSale.quantity) {
await transferPartialSale(
ticketId, originalSale, sale, options);
}
let logTicketOrigin = {
originFk: id,
userFk: userId,
action: 'update',
changedModel: 'Ticket',
changedModelId: ticketId,
oldInstance: {item: sale.itemFk,
quantity: 0,
concept: sale.concept,
ticket: ticketId},
newInstance: {item: sale.itemFk,
quantity: sale.quantity,
concept: sale.concept,
ticket: ticketId}
};
await models.TicketLog.create(logTicketOrigin, options);
let logTicketDestination = {
originFk: ticketId,
userFk: userId,
action: 'update',
changedModel: 'Ticket',
changedModelId: ticketId,
oldInstance: {item: sale.itemFk,
quantity: originalSaleQuantity,
concept: sale.concept,
ticket: id},
newInstance: {item: sale.itemFk,
quantity: originalSaleQuantity - sale.quantity,
concept: sale.concept,
ticket: id}
};
await models.TicketLog.create(logTicketDestination, options);
}
const isTicketEmpty = await models.Ticket.isEmpty(id, options);
if (isTicketEmpty) {
await originalTicket.updateAttributes({
isDeleted: true
}, options);
}
await tx.commit();
return {id: ticketId};
} catch (error) {
await tx.rollback();
throw error;
}
};
async function cloneTicket(ctx, ticket, options) {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const travelDates = await models.Agency.getFirstShipped({
agencyModeFk: ticket.agencyModeFk,
addressFk: ticket.addressFk,
warehouseFk: ticket.warehouseFk
});
if (!travelDates)
throw new UserError(`Invalid parameters to create a new ticket`);
let shipped = new Date(travelDates.shipped);
let landed = new Date(travelDates.landed);
const newTicket = await models.Ticket.new(ctx, {
clientFk: ticket.clientFk,
addressFk: ticket.addressFk,
agencyModeFk: ticket.agencyModeFk,
warehouseFk: ticket.warehouseFk,
shipped: shipped,
landed: landed,
userId: userId
}, options);
return newTicket.id;
}
async function transferPartialSale(ticketId, originalSale, sale, options) {
const models = Self.app.models;
if (sale.quantity > originalSale.quantity)
throw new UserError('Invalid quantity');
// Update original sale
const rest = originalSale.quantity - sale.quantity;
const updatedSale = await models.Sale.updateAll({
id: sale.id
}, {quantity: rest}, options);
// Clone sale with new quantity
const newSale = originalSale;
newSale.id = undefined;
newSale.ticketFk = ticketId;
newSale.quantity = sale.quantity;
const createdSale = await models.Sale.create(newSale, options);
// Clone sale components
const saleComponents = await models.SaleComponent.find({
where: {saleFk: sale.id}
}, options);
const newComponents = saleComponents.map(component => {
component.saleFk = createdSale.id;
return component;
});
await models.SaleComponent.create(newComponents, options);
return updatedSale;
}
};