159 lines
5.0 KiB
JavaScript
159 lines
5.0 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) => {
|
||
|
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);
|
||
|
|
||
|
const promises = [];
|
||
|
for (const sale of sales) {
|
||
|
const originalSale = map.get(sale.id);
|
||
|
|
||
|
if (sale.quantity == originalSale.quantity) {
|
||
|
const updatedSale = models.Sale.updateAll({
|
||
|
id: sale.id
|
||
|
}, {ticketFk: ticketId}, options);
|
||
|
|
||
|
promises.push(updatedSale);
|
||
|
} else if (sale.quantity < originalSale.quantity) {
|
||
|
const transferedSale = await transferPartialSale(
|
||
|
ticketId, originalSale, sale, options);
|
||
|
|
||
|
promises.push(transferedSale);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const isTicketEmpty = await models.Ticket.isEmpty(id, options);
|
||
|
if (isTicketEmpty) {
|
||
|
originalTicket.updateAttributes({
|
||
|
isDeleted: true
|
||
|
}, options);
|
||
|
}
|
||
|
|
||
|
await Promise.all(promises);
|
||
|
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;
|
||
|
// Update original sale
|
||
|
const rest = originalSale.quantity - sale.quantity;
|
||
|
const updatedSale = 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;
|
||
|
});
|
||
|
const createdComponents = models.SaleComponent
|
||
|
.create(newComponents, options);
|
||
|
|
||
|
return [updatedSale, createdComponents];
|
||
|
}
|
||
|
};
|