salix/modules/ticket/back/models/sale.js

113 lines
4.1 KiB
JavaScript

const UserError = require('vn-loopback/util/user-error');
const LoopBackContext = require('loopback-context');
module.exports = Self => {
require('../methods/sale/getClaimableFromTicket')(Self);
require('../methods/sale/reserve')(Self);
require('../methods/sale/deleteSales')(Self);
require('../methods/sale/updatePrice')(Self);
require('../methods/sale/updateQuantity')(Self);
require('../methods/sale/updateConcept')(Self);
require('../methods/sale/recalculatePrice')(Self);
require('../methods/sale/refund')(Self);
require('../methods/sale/canEdit')(Self);
require('../methods/sale/usesMana')(Self);
Self.validatesPresenceOf('concept', {
message: `Concept cannot be blank`
});
Self.observe('before save', async ctx => {
const models = Self.app.models;
const changes = ctx.data || ctx.instance;
const instance = ctx.currentInstance;
const newQuantity = changes?.quantity;
if (newQuantity == null) return;
const loopBackContext = LoopBackContext.getCurrentContext();
ctx.req = loopBackContext.active;
if (await models.ACL.checkAccessAcl(ctx, 'Sale', 'canForceQuantity', 'WRITE')) return;
const ticketId = changes?.ticketFk || instance?.ticketFk;
const itemId = changes?.itemFk || instance?.itemFk;
const oldQuantity = instance?.quantity ?? null;
const quantityAdded = newQuantity - oldQuantity;
const ticket = await models.Ticket.findById(
ticketId,
{
fields: ['id', 'clientFk', 'warehouseFk', 'addressFk', 'agencyModeFk', 'shipped', 'landed'],
include: {
relation: 'client',
scope: {
fields: ['id', 'clientTypeFk'],
include: {
relation: 'type',
scope: {
fields: ['code', 'description']
}
}
}
}
},
ctx.options);
if (ticket?.client()?.type()?.code === 'loses') return;
const isRefund = await models.TicketRefund.findOne({
fields: ['id'],
where: {refundTicketFk: ticketId}
}, ctx.options);
if (isRefund) return;
if (newQuantity < 0)
throw new UserError('You can only add negative amounts in refund tickets');
const item = await models.Item.findOne({
fields: ['family', 'minQuantity'],
where: {id: itemId},
}, ctx.options);
if (item.family == 'EMB') return;
await models.Sale.rawSql(`CALL catalog_calcFromItem(?,?,?,?)`, [
ticket.landed,
ticket.addressFk,
ticket.agencyModeFk,
itemId
],
ctx.options);
const [itemInfo] = await models.Sale.rawSql(`SELECT available FROM tmp.ticketCalculateItem`, null, ctx.options);
if (!itemInfo?.available || itemInfo.available < quantityAdded)
throw new UserError(`This item is not available`);
if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return;
if (newQuantity < item.minQuantity && newQuantity != itemInfo?.available)
throw new UserError('The amount cannot be less than the minimum');
if (ctx.isNewInstance || newQuantity <= oldQuantity) return;
const [saleGrouping] = await models.Sale.rawSql(`
SELECT MAX(t.grouping), t.price newPrice
FROM tmp.ticketComponentPrice t
WHERE t.grouping <= ?`,
[quantityAdded],
ctx.options);
await models.Sale.rawSql(`
DROP TEMPORARY TABLE IF EXISTS
tmp.ticketCalculateItem,
tmp.ticketComponentPrice,
tmp.ticketComponent,
tmp.ticketLot,
tmp.zoneGetShipped;
`, null, ctx.options);
if (!saleGrouping?.newPrice || saleGrouping.newPrice < instance.price)
throw new UserError('The price of the item changed');
});
};