194 lines
6.3 KiB
JavaScript
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;
|
|
}
|
|
};
|