let UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('updateDiscount', { description: 'Changes the discount of a sale', accessType: 'WRITE', accepts: [ { arg: 'id', description: 'The ticket id', type: 'number', required: true, http: {source: 'path'} }, { arg: 'salesIds', description: 'The sales id', type: ['number'], required: true, }, { arg: 'newDiscount', description: 'The new discount', type: 'number', required: true }, { arg: 'manaCode', description: 'The type of mana', type: 'string', required: false } ], returns: { type: 'string', root: true }, http: { path: `/:id/updateDiscount`, verb: 'post' } }); Self.updateDiscount = async(ctx, id, salesIds, newDiscount, manaCode, options) => { const $t = ctx.req.__; // $translate const models = Self.app.models; 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 filter = { where: { id: {inq: salesIds} }, include: { relation: 'ticket', scope: { include: { relation: 'client', scope: { fields: ['salesPersonFk'] } }, fields: ['id', 'clientFk'] } } }; const sales = await models.Sale.find(filter, myOptions); if (sales.length === 0) throw new UserError('Please select at least one sale'); const allFromSameTicket = sales.every(sale => sale.ticketFk === id); if (!allFromSameTicket) throw new UserError('All sales must belong to the same ticket'); const userId = ctx.req.accessToken.userId; const isLocked = await models.Ticket.isLocked(id, myOptions); const canEditDiscount = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editDiscount'); const state = await Self.app.models.TicketState.findOne({ where: {ticketFk: id} }, myOptions); const alertLevel = state ? state.alertLevel : null; if (isLocked || (!canEditDiscount && alertLevel > 0)) throw new UserError(`The sales of this ticket can't be modified`); const usesMana = await models.Sale.usesMana(ctx, myOptions); const componentCode = usesMana ? manaCode : 'buyerDiscount'; const discountComponent = await models.Component.findOne({ where: {code: componentCode}}, myOptions); const componentId = discountComponent.id; const promises = []; let changesMade = ''; for (let sale of sales) { const oldDiscount = sale.discount; const value = ((-sale.price * newDiscount) / 100); const manaComponent = await models.Component.findOne({ where: {code: 'mana'} }, myOptions); const manaClaimComponent = await models.Component.findOne({ where: {code: 'manaClaim'} }, myOptions); const [oldComponent] = await models.SaleComponent.find({ where: { and: [ {saleFk: sale.id}, {componentFk: {inq: [manaComponent.id, manaClaimComponent.id]}} ] } }, myOptions); let deletedComponent; if (oldComponent) { const filter = { saleFk: sale.id, componentFk: oldComponent.componentFk }; deletedComponent = await models.SaleComponent.destroyAll(filter, myOptions); } const newComponent = await createSaleComponent(sale.id, value, componentId, myOptions); const updatedSale = sale.updateAttribute('discount', newDiscount, myOptions); promises.push(newComponent, updatedSale, deletedComponent); const change = `${oldDiscount}% ➔ *${newDiscount}%*`; changesMade += `\r\n-${sale.itemFk}: ${sale.concept} (${sale.quantity}) ${change}`; } await Promise.all(promises); await Self.rawSql('CALL vn.manaSpellersRequery(?)', [userId], myOptions); await Self.rawSql('CALL vn.ticket_recalc(?, NULL)', [id], myOptions); const ticket = await models.Ticket.findById(id, { include: { relation: 'client', scope: { include: { relation: 'salesPersonUser', scope: { fields: ['id', 'name'] } } } } }, myOptions); const salesPerson = ticket.client().salesPersonUser(); if (salesPerson) { const url = await Self.app.models.Url.getUrl(); const message = $t('Changed sale discount', { ticketId: id, ticketUrl: `${url}ticket/${id}/sale`, changes: changesMade }); await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message, myOptions); } if (tx) await tx.commit(); } catch (e) { if (tx) await tx.rollback(); throw e; } }; async function createSaleComponent(saleId, value, componentId, myOptions) { const models = Self.app.models; return models.SaleComponent.upsert({ saleFk: saleId, value: value, componentFk: componentId }, myOptions); } };