diff --git a/modules/ticket/back/methods/services/refund.js b/modules/ticket/back/methods/services/refund.js new file mode 100644 index 000000000..ae58e0924 --- /dev/null +++ b/modules/ticket/back/methods/services/refund.js @@ -0,0 +1,189 @@ +module.exports = Self => { + Self.remoteMethod('refund', { + description: 'Create refund tickets with sales and services if provided', + accessType: 'WRITE', + accepts: [ + { + arg: 'salesIds', + type: ['number'], + required: true + }, + { + arg: 'servicesIds', + type: ['number'] + }, + { + arg: 'createSingleTicket', + type: 'boolean', + required: false + } + ], + returns: { + type: ['number'], + root: true + }, + http: { + path: `/refund`, + verb: 'POST' + } + }); + + Self.refund = async(salesIds, servicesIds, createSingleTicket = false, options) => { + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const refundAgencyMode = await models.AgencyMode.findOne({ + include: { + relation: 'zones', + scope: { + limit: 1, + field: ['id', 'name'] + } + }, + where: {code: 'refund'} + }, myOptions); + + const refoundZoneId = refundAgencyMode.zones()[0].id; + + const salesFilter = { + where: {id: {inq: salesIds}}, + include: { + relation: 'components', + scope: { + fields: ['saleFk', 'componentFk', 'value'] + } + } + }; + const sales = await models.Sale.find(salesFilter, myOptions); + const ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))]; + + const refundTickets = []; + const mappedTickets = new Map(); + const now = Date.vnNew(); + + const [firstTicketId] = ticketsIds; + if (createSingleTicket) { + await createTicketRefund( + firstTicketId, + refundTickets, + mappedTickets, + now, + refundAgencyMode, + refoundZoneId, + myOptions + ); + } else { + for (let ticketId of ticketsIds) { + await createTicketRefund( + ticketId, + refundTickets, + mappedTickets, + now, + refundAgencyMode, + refoundZoneId, + myOptions + ); + } + } + + for (const sale of sales) { + const refundTicketId = await getTicketRefundId(createSingleTicket, sale.ticketFk, refundTickets, mappedTickets); + + const createdSale = await models.Sale.create({ + ticketFk: refundTicketId, + itemFk: sale.itemFk, + quantity: - sale.quantity, + concept: sale.concept, + price: sale.price, + discount: sale.discount, + }, myOptions); + + const components = sale.components(); + for (const component of components) + component.saleFk = createdSale.id; + + await models.SaleComponent.create(components, myOptions); + } + + if (servicesIds && servicesIds.length > 0) { + const servicesFilter = { + where: {id: {inq: servicesIds}} + }; + const services = await models.TicketService.find(servicesFilter, myOptions); + + for (const service of services) { + const refundTicketId = await getTicketRefundId(createSingleTicket, service.ticketFk, refundTickets, mappedTickets); + + await models.TicketService.create({ + description: service.description, + quantity: - service.quantity, + price: service.price, + taxClassFk: service.taxClassFk, + ticketFk: refundTicketId, + ticketServiceTypeFk: service.ticketServiceTypeFk, + }, myOptions); + } + } + + if (tx) await tx.commit(); + + return refundTickets; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; + + async function createTicketRefund( + ticketId, + refundTickets, + mappedTickets, + now, + refundAgencyMode, + refoundZoneId, + myOptions + ) { + const models = Self.app.models; + + const filter = {include: {relation: 'address'}}; + const ticket = await models.Ticket.findById(ticketId, filter, myOptions); + + const refundTicket = await models.Ticket.create({ + clientFk: ticket.clientFk, + shipped: now, + addressFk: ticket.address().id, + agencyModeFk: refundAgencyMode.id, + nickname: ticket.address().nickname, + warehouseFk: ticket.warehouseFk, + companyFk: ticket.companyFk, + landed: now, + zoneFk: refoundZoneId + }, myOptions); + + refundTickets.push(refundTicket); + + mappedTickets.set(ticketId, refundTicket.id); + + await models.TicketRefund.create({ + refundTicketFk: refundTicket.id, + originalTicketFk: ticket.id, + }, myOptions); + } + + async function getTicketRefundId(createSingleTicket, ticketId, refundTickets, mappedTickets) { + if (createSingleTicket) { + const [firstRefundTicket] = refundTickets; + return firstRefundTicket.id; + } else return mappedTickets.get(ticketId); + } +}; diff --git a/modules/ticket/front/services/index.html b/modules/ticket/front/services/index.html index 3aba0e08d..9ab4f3270 100644 --- a/modules/ticket/front/services/index.html +++ b/modules/ticket/front/services/index.html @@ -24,12 +24,13 @@