From e5d466b697e33513ea98b74b855f4c17877a8ba8 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 26 Jan 2024 08:30:43 +0100 Subject: [PATCH 1/4] fix: refs #6703 drop & replace sale refund by clone --- modules/ticket/back/methods/sale/clone.js | 28 +++++ modules/ticket/back/methods/sale/refund.js | 61 ----------- .../back/methods/sale/specs/refund.spec.js | 101 ------------------ modules/ticket/back/methods/ticket/refund.js | 2 +- modules/ticket/back/models/sale.js | 1 - 5 files changed, 29 insertions(+), 164 deletions(-) delete mode 100644 modules/ticket/back/methods/sale/refund.js delete mode 100644 modules/ticket/back/methods/sale/specs/refund.spec.js diff --git a/modules/ticket/back/methods/sale/clone.js b/modules/ticket/back/methods/sale/clone.js index f8eb4d143..8397499f7 100644 --- a/modules/ticket/back/methods/sale/clone.js +++ b/modules/ticket/back/methods/sale/clone.js @@ -1,4 +1,32 @@ module.exports = Self => { + Self.remoteMethodCtx('clone', { + description: 'Clone sales and services provided', + accessType: 'WRITE', + accepts: [ + { + arg: 'salesIds', + type: ['number'], + }, { + arg: 'servicesIds', + type: ['number'] + }, { + arg: 'withWarehouse', + type: 'boolean', + required: true + }, { + arg: 'negative', + type: 'boolean' + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/refund`, + verb: 'post' + } + }); Self.clone = async(ctx, salesIds, servicesIds, withWarehouse, negative, options) => { const models = Self.app.models; const myOptions = {}; diff --git a/modules/ticket/back/methods/sale/refund.js b/modules/ticket/back/methods/sale/refund.js deleted file mode 100644 index 19a8dfbb0..000000000 --- a/modules/ticket/back/methods/sale/refund.js +++ /dev/null @@ -1,61 +0,0 @@ -module.exports = Self => { - Self.remoteMethodCtx('refund', { - description: 'Create refund tickets with sales and services if provided', - accessType: 'WRITE', - accepts: [ - { - arg: 'salesIds', - type: ['number'], - }, - { - arg: 'servicesIds', - type: ['number'] - }, - { - arg: 'withWarehouse', - type: 'boolean', - required: true - } - ], - returns: { - type: ['object'], - root: true - }, - http: { - path: `/refund`, - verb: 'post' - } - }); - - Self.refund = async(ctx, salesIds, servicesIds, withWarehouse, options) => { - 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 refundsTicket = await models.Sale.clone( - ctx, - salesIds, - servicesIds, - withWarehouse, - true, - myOptions - ); - - if (tx) await tx.commit(); - - return refundsTicket; - } catch (e) { - if (tx) await tx.rollback(); - throw e; - } - }; -}; diff --git a/modules/ticket/back/methods/sale/specs/refund.spec.js b/modules/ticket/back/methods/sale/specs/refund.spec.js deleted file mode 100644 index ab5e1e281..000000000 --- a/modules/ticket/back/methods/sale/specs/refund.spec.js +++ /dev/null @@ -1,101 +0,0 @@ -const models = require('vn-loopback/server/server').models; -const LoopBackContext = require('loopback-context'); - -describe('Sale refund()', () => { - const userId = 5; - const ctx = {req: {accessToken: userId}, args: {}}; - const activeCtx = { - accessToken: {userId}, - }; - const servicesIds = [3]; - const withWarehouse = true; - - beforeEach(() => { - spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ - active: activeCtx - }); - }); - - it('should create ticket with the selected lines', async() => { - const tx = await models.Sale.beginTransaction({}); - const salesIds = [7, 8]; - - try { - const options = {transaction: tx}; - - const refundedTickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); - - expect(refundedTickets).toBeDefined(); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should create one ticket for each unique ticketFk in the sales', async() => { - const tx = await models.Sale.beginTransaction({}); - const salesIds = [6, 7]; - - try { - const options = {transaction: tx}; - const ticketsBefore = await models.Ticket.find({}, options); - - const tickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); - - const refundedTicket = await getTicketRefund(tickets[0].id, options); - const ticketsAfter = await models.Ticket.find({}, options); - const salesLength = refundedTicket.ticketSales().length; - const componentsLength = refundedTicket.ticketSales()[0].components().length; - - expect(refundedTicket).toBeDefined(); - expect(salesLength).toEqual(1); - expect(ticketsBefore.length).toEqual(ticketsAfter.length - 2); - expect(componentsLength).toEqual(4); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should create a ticket without sales', async() => { - const servicesIds = [4]; - const tx = await models.Sale.beginTransaction({}); - const options = {transaction: tx}; - try { - const tickets = await models.Sale.refund(ctx, null, servicesIds, withWarehouse, options); - const refundedTicket = await getTicketRefund(tickets[0].id, options); - - expect(refundedTicket).toBeDefined(); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); - -async function getTicketRefund(id, options) { - return models.Ticket.findOne({ - where: { - id - }, - include: [ - { - relation: 'ticketSales', - scope: { - include: { - relation: 'components' - } - } - }, - { - relation: 'ticketServices', - } - ] - }, options); -} diff --git a/modules/ticket/back/methods/ticket/refund.js b/modules/ticket/back/methods/ticket/refund.js index 4fed02260..b07995453 100644 --- a/modules/ticket/back/methods/ticket/refund.js +++ b/modules/ticket/back/methods/ticket/refund.js @@ -45,7 +45,7 @@ module.exports = Self => { const services = await models.TicketService.find(filter, myOptions); const servicesIds = services.map(service => service.id); - const refundedTickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, myOptions); + const refundedTickets = await models.Sale.clone(ctx, salesIds, servicesIds, withWarehouse, true, myOptions); if (tx) await tx.commit(); diff --git a/modules/ticket/back/models/sale.js b/modules/ticket/back/models/sale.js index dd092573d..30fb74b75 100644 --- a/modules/ticket/back/models/sale.js +++ b/modules/ticket/back/models/sale.js @@ -9,7 +9,6 @@ module.exports = 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); require('../methods/sale/clone')(Self); From 4fc780967f17256d49ea0cf5724219bb4dfc7f08 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 26 Jan 2024 15:32:50 +0100 Subject: [PATCH 2/4] fix: refs #6703 tests --- db/changes/240601/00-cloneAcl.sql | 4 ++++ modules/ticket/back/methods/sale/clone.js | 4 ++-- modules/ticket/back/methods/ticket/refund.js | 2 +- modules/ticket/front/sale/index.js | 2 +- modules/ticket/front/sale/index.spec.js | 2 +- modules/ticket/front/services/index.js | 2 +- 6 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 db/changes/240601/00-cloneAcl.sql diff --git a/db/changes/240601/00-cloneAcl.sql b/db/changes/240601/00-cloneAcl.sql new file mode 100644 index 000000000..bc6e22ee0 --- /dev/null +++ b/db/changes/240601/00-cloneAcl.sql @@ -0,0 +1,4 @@ +UPDATE salix.ACL + SET property='clone' + WHERE model = 'Sale' + AND property = 'refund' \ No newline at end of file diff --git a/modules/ticket/back/methods/sale/clone.js b/modules/ticket/back/methods/sale/clone.js index 8397499f7..77c40d8a0 100644 --- a/modules/ticket/back/methods/sale/clone.js +++ b/modules/ticket/back/methods/sale/clone.js @@ -23,8 +23,8 @@ module.exports = Self => { root: true }, http: { - path: `/refund`, - verb: 'post' + path: `/clone`, + verb: 'POST' } }); Self.clone = async(ctx, salesIds, servicesIds, withWarehouse, negative, options) => { diff --git a/modules/ticket/back/methods/ticket/refund.js b/modules/ticket/back/methods/ticket/refund.js index b07995453..7365f34df 100644 --- a/modules/ticket/back/methods/ticket/refund.js +++ b/modules/ticket/back/methods/ticket/refund.js @@ -20,7 +20,7 @@ module.exports = Self => { }, http: { path: `/refund`, - verb: 'post' + verb: 'POST' } }); diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index ed6d9b10a..ce6aad5ed 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -524,7 +524,7 @@ class Controller extends Section { const salesIds = sales.map(sale => sale.id); const params = {salesIds: salesIds, withWarehouse: withWarehouse}; - const query = 'Sales/refund'; + const query = 'Sales/clone'; this.$http.post(query, params).then(res => { const [refundTicket] = res.data; this.vnApp.showSuccess(this.$t('The following refund ticket have been created', { diff --git a/modules/ticket/front/sale/index.spec.js b/modules/ticket/front/sale/index.spec.js index 36be32f52..6b1da108e 100644 --- a/modules/ticket/front/sale/index.spec.js +++ b/modules/ticket/front/sale/index.spec.js @@ -729,7 +729,7 @@ describe('Ticket', () => { salesIds: [1, 4], }; const refundTicket = {id: 99}; - $httpBackend.expect('POST', 'Sales/refund', params).respond(200, [refundTicket]); + $httpBackend.expect('POST', 'Sales/clone', params).respond(200, [refundTicket]); controller.createRefund(); $httpBackend.flush(); diff --git a/modules/ticket/front/services/index.js b/modules/ticket/front/services/index.js index d8c209ea4..08a76f9ba 100644 --- a/modules/ticket/front/services/index.js +++ b/modules/ticket/front/services/index.js @@ -56,7 +56,7 @@ class Controller extends Section { if (!this.checkeds.length) return; const params = {servicesIds: this.checkeds, withWarehouse: false}; - const query = 'Sales/refund'; + const query = 'Sales/clone'; this.$http.post(query, params).then(res => { const refundTicket = res.data; this.vnApp.showSuccess(this.$t('The following refund ticket have been created', { From c136395d1e65edf1bd81c5cff5e570c961e539da Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 31 Jan 2024 09:16:38 +0100 Subject: [PATCH 3/4] fix: refs #6703 fix conflicts --- .../{10832-purpleAralia => 10856-greenAralia}/00-cloneAcl.sql | 0 modules/ticket/front/sale/index.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename db/versions/{10832-purpleAralia => 10856-greenAralia}/00-cloneAcl.sql (100%) diff --git a/db/versions/10832-purpleAralia/00-cloneAcl.sql b/db/versions/10856-greenAralia/00-cloneAcl.sql similarity index 100% rename from db/versions/10832-purpleAralia/00-cloneAcl.sql rename to db/versions/10856-greenAralia/00-cloneAcl.sql diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index ce6aad5ed..f295efae9 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -523,7 +523,7 @@ class Controller extends Section { if (!sales) return; const salesIds = sales.map(sale => sale.id); - const params = {salesIds: salesIds, withWarehouse: withWarehouse}; + const params = {salesIds: salesIds, withWarehouse: withWarehouse,}; const query = 'Sales/clone'; this.$http.post(query, params).then(res => { const [refundTicket] = res.data; From e6eac5470934f90ee7ba2055e1969a33336db98d Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 31 Jan 2024 09:59:32 +0100 Subject: [PATCH 4/4] fix: refs #6703 tests & front --- .../back/methods/sale/specs/clone.spec.js | 38 +++++++++++++++++++ modules/ticket/front/sale/index.js | 2 +- modules/ticket/front/sale/index.spec.js | 1 + modules/ticket/front/services/index.js | 4 +- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/modules/ticket/back/methods/sale/specs/clone.spec.js b/modules/ticket/back/methods/sale/specs/clone.spec.js index 26506485a..f52f7ba38 100644 --- a/modules/ticket/back/methods/sale/specs/clone.spec.js +++ b/modules/ticket/back/methods/sale/specs/clone.spec.js @@ -67,4 +67,42 @@ describe('Ticket cloning - clone function', () => { expect(services.length).toBeGreaterThan(0); } }); + + it('should create a ticket without sales', async() => { + const servicesIds = [4]; + const tx = await models.Sale.beginTransaction({}); + const options = {transaction: tx}; + try { + const tickets = await models.Sale.clone(ctx, null, servicesIds, false, options); + const refundedTicket = await getTicketRefund(tickets[0].id, options); + + expect(refundedTicket).toBeDefined(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); + +async function getTicketRefund(id, options) { + return models.Ticket.findOne({ + where: { + id + }, + include: [ + { + relation: 'ticketSales', + scope: { + include: { + relation: 'components' + } + } + }, + { + relation: 'ticketServices', + } + ] + }, options); +} diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index f295efae9..1cd5560a4 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -523,7 +523,7 @@ class Controller extends Section { if (!sales) return; const salesIds = sales.map(sale => sale.id); - const params = {salesIds: salesIds, withWarehouse: withWarehouse,}; + const params = {salesIds: salesIds, withWarehouse: withWarehouse, negative: true}; const query = 'Sales/clone'; this.$http.post(query, params).then(res => { const [refundTicket] = res.data; diff --git a/modules/ticket/front/sale/index.spec.js b/modules/ticket/front/sale/index.spec.js index 6b1da108e..fb1c925d4 100644 --- a/modules/ticket/front/sale/index.spec.js +++ b/modules/ticket/front/sale/index.spec.js @@ -727,6 +727,7 @@ describe('Ticket', () => { jest.spyOn(controller.$state, 'go'); const params = { salesIds: [1, 4], + negative: true }; const refundTicket = {id: 99}; $httpBackend.expect('POST', 'Sales/clone', params).respond(200, [refundTicket]); diff --git a/modules/ticket/front/services/index.js b/modules/ticket/front/services/index.js index 08a76f9ba..fadf2ad4f 100644 --- a/modules/ticket/front/services/index.js +++ b/modules/ticket/front/services/index.js @@ -55,10 +55,10 @@ class Controller extends Section { createRefund() { if (!this.checkeds.length) return; - const params = {servicesIds: this.checkeds, withWarehouse: false}; + const params = {servicesIds: this.checkeds, withWarehouse: false, negative: true}; const query = 'Sales/clone'; this.$http.post(query, params).then(res => { - const refundTicket = res.data; + const [refundTicket] = res.data; this.vnApp.showSuccess(this.$t('The following refund ticket have been created', { ticketId: refundTicket.id }));