From b2e7ea3089b24acfbc1dfbde612cbe7ee36940b5 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 30 Nov 2023 15:16:41 +0100 Subject: [PATCH] refs #5914 feat: make invoice support rectificative --- loopback/locale/es.json | 3 ++- .../back/methods/client/canBeInvoiced.js | 2 +- .../back/methods/invoiceOut/invoiceClient.js | 1 + .../invoiceOut/specs/transferinvoice.spec.js | 23 +++++++++++----- .../methods/invoiceOut/transferInvoice.js | 8 +++--- .../invoiceOut/front/descriptor-menu/index.js | 2 +- .../back/methods/sale/specs/refund.spec.js | 8 +++--- .../back/methods/ticket/canBeInvoiced.js | 16 ++++++++---- .../back/methods/ticket/invoiceTickets.js | 1 - .../ticket/back/methods/ticket/makeInvoice.js | 26 +++++++++++-------- .../ticket/specs/canBeInvoiced.spec.js | 8 +++--- .../ticket/specs/invoiceTickets.spec.js | 10 +++---- .../methods/ticket/specs/makeInvoice.spec.js | 4 +-- modules/ticket/front/descriptor-menu/index.js | 2 +- .../front/descriptor-menu/index.spec.js | 5 ++-- modules/ticket/front/sale/index.js | 2 +- modules/ticket/front/sale/index.spec.js | 2 +- 17 files changed, 72 insertions(+), 51 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 41acc36c3..71e0dc6af 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -328,5 +328,6 @@ "User disabled": "Usuario desactivado", "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima", - "Cannot past travels with entries": "No se pueden pasar envíos con entradas" + "Cannot past travels with entries": "No se pueden pasar envíos con entradas", + "No tickets to invoice": "No hay tickets para facturar" } diff --git a/modules/client/back/methods/client/canBeInvoiced.js b/modules/client/back/methods/client/canBeInvoiced.js index 843e9549f..cdb865500 100644 --- a/modules/client/back/methods/client/canBeInvoiced.js +++ b/modules/client/back/methods/client/canBeInvoiced.js @@ -1,7 +1,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self) { - Self.remoteMethodCtx('canBeInvoiced', { + Self.remoteMethod('canBeInvoiced', { description: 'Change property isEqualizated in all client addresses', accessType: 'READ', accepts: [ diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index fa22dab1e..530b02353 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -80,6 +80,7 @@ module.exports = Self => { invoiceType, args.companyFk, args.invoiceDate, + null, options ); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js index dea4b6d00..b3bd17826 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js @@ -23,20 +23,29 @@ describe('InvoiceOut tranferInvoice()', () => { const tx = await models.InvoiceOut.beginTransaction({}); const options = {transaction: tx}; const args = { - id: '1', + id: '4', refFk: 'T4444444', newClientFk: 1, - cplusRectificationId: 1, - siiTypeInvoiceOutId: 1, - invoiceCorrectionTypeId: 1 + cplusRectificationTypeFk: 1, + siiTypeInvoiceOutFk: 1, + invoiceCorrectionTypeFk: 1 }; ctx.args = args; try { + const {clientFk: oldClient} = await models.InvoiceOut.findById(args.id, {fields: ['clientFk']}); + const invoicesBefore = await models.InvoiceOut.find({}, options); const result = await models.InvoiceOut.transferInvoice( ctx, options); + const invoicesAfter = await models.InvoiceOut.find({}, options); + const rectificativeInvoice = invoicesAfter[invoicesAfter.length - 2]; + const newInvoice = invoicesAfter[invoicesAfter.length - 1]; expect(result).toBeDefined(); + expect(invoicesAfter.length - invoicesBefore.length).toEqual(2); + expect(rectificativeInvoice.clientFk).toEqual(oldClient); + expect(newInvoice.clientFk).toEqual(args.newClientFk); + await tx.rollback(); } catch (e) { await tx.rollback(); @@ -51,9 +60,9 @@ describe('InvoiceOut tranferInvoice()', () => { id: '1', refFk: 'T1111111', newClientFk: 1101, - cplusRectificationId: 1, - siiTypeInvoiceOutId: 1, - invoiceCorrectionTypeId: 1 + cplusRectificationTypeFk: 1, + siiTypeInvoiceOutFk: 1, + invoiceCorrectionTypeFk: 1 }; ctx.args = args; try { diff --git a/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js index dcdd9b9b1..5f2428539 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js @@ -22,7 +22,7 @@ module.exports = Self => { required: true }, { - arg: 'cplusRectificationFk', + arg: 'cplusRectificationTypeFk', type: 'number', required: true }, @@ -50,7 +50,7 @@ module.exports = Self => { Self.transferInvoice = async(ctx, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; - const {id, refFk, newClientFk, cplusRectificationFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk} = ctx.args; + const {id, refFk, newClientFk, cplusRectificationTypeFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk} = ctx.args; let tx; if (typeof options == 'object') Object.assign(myOptions, options); @@ -87,11 +87,11 @@ module.exports = Self => { } const invoiceCorrection = - {correctedFk: id, cplusRectificationFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk}; + {correctedFk: id, cplusRectificationTypeFk, siiTypeInvoiceOutFk, invoiceCorrectionTypeFk}; const refundTicketIds = refundTickets.map(ticket => ticket.id); await models.Ticket.invoiceTickets(ctx, refundTicketIds, invoiceCorrection, myOptions); - const [[invoiceId]] = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions); + const [invoiceId] = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, null, myOptions); if (tx) { await tx.commit(); diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js index f9d436092..aee323e39 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.js +++ b/modules/invoiceOut/front/descriptor-menu/index.js @@ -131,7 +131,7 @@ class Controller extends Section { id: this.invoiceOut.id, refFk: this.invoiceOut.ref, newClientFk: this.clientId, - cplusRectificationFk: this.cplusRectificationType, + cplusRectificationTypeFk: this.cplusRectificationType, siiTypeInvoiceOutFk: this.siiTypeInvoiceOut, invoiceCorrectionTypeFk: this.invoiceCorrectionType }; diff --git a/modules/ticket/back/methods/sale/specs/refund.spec.js b/modules/ticket/back/methods/sale/specs/refund.spec.js index 08eb1fabd..60f77e90c 100644 --- a/modules/ticket/back/methods/sale/specs/refund.spec.js +++ b/modules/ticket/back/methods/sale/specs/refund.spec.js @@ -23,9 +23,9 @@ describe('Sale refund()', () => { try { const options = {transaction: tx}; - const refundedTicket = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); + const refundedTickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); - expect(refundedTicket).toBeDefined(); + expect(refundedTickets).toBeDefined(); await tx.rollback(); } catch (e) { @@ -42,11 +42,11 @@ describe('Sale refund()', () => { const options = {transaction: tx}; const ticketsBefore = await models.Ticket.find({}, options); - const ticket = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); + const tickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); const refundedTicket = await models.Ticket.findOne({ where: { - id: ticket.id + id: tickets[0].id }, include: [ { diff --git a/modules/ticket/back/methods/ticket/canBeInvoiced.js b/modules/ticket/back/methods/ticket/canBeInvoiced.js index 348f02348..fe7223c17 100644 --- a/modules/ticket/back/methods/ticket/canBeInvoiced.js +++ b/modules/ticket/back/methods/ticket/canBeInvoiced.js @@ -10,6 +10,11 @@ module.exports = function(Self) { description: 'The tickets id', type: ['number'], required: true + }, + { + arg: 'isRectificative', + description: 'If it is rectificative', + type: 'boolean' } ], returns: { @@ -23,7 +28,7 @@ module.exports = function(Self) { } }); - Self.canBeInvoiced = async(ctx, ticketsIds, options) => { + Self.canBeInvoiced = async(ctx, ticketsIds, isRectificative, options) => { const myOptions = {}; const $t = ctx.req.__; // $translate @@ -48,10 +53,11 @@ module.exports = function(Self) { const [supplierCompany] = await Self.rawSql(query, [companyFk], options); const isSpanishCompany = supplierCompany?.isSpanishCompany; - - const [result] = await Self.rawSql('SELECT hasAnyNegativeBase() AS base', null, options); - const hasAnyNegativeBase = result?.base && isSpanishCompany; - if (hasAnyNegativeBase) + const taxBaseFunction = isRectificative ? 'hasAnyPositiveBase' : 'hasAnyNegativeBase'; + const [result] = + await Self.rawSql(`SELECT ?() AS hasBasesProblem`, [taxBaseFunction], options); + const hasAnyIncorrectBase = result?.hasBasesProblem && isSpanishCompany; + if (hasAnyIncorrectBase) throw new UserError($t('Negative basis of tickets', {ticketsIds: ticketsIds})); const today = Date.vnNew(); diff --git a/modules/ticket/back/methods/ticket/invoiceTickets.js b/modules/ticket/back/methods/ticket/invoiceTickets.js index 29fb1769b..212f6556a 100644 --- a/modules/ticket/back/methods/ticket/invoiceTickets.js +++ b/modules/ticket/back/methods/ticket/invoiceTickets.js @@ -93,7 +93,6 @@ module.exports = function(Self) { async function createInvoice(ctx, companyId, ticketsIds, address, invoicesIds, invoiceCorrection, myOptions) { const models = Self.app.models; - console.log(ticketsIds, address); await models.Ticket.rawSql(` CREATE OR REPLACE TEMPORARY TABLE tmp.ticketToInvoice (PRIMARY KEY (id)) diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index 6f1586c2b..fe7e527c8 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -67,20 +67,24 @@ module.exports = function(Self) { fields: ['id', 'clientFk', 'addressFk'] }, myOptions); - await models.Ticket.canBeInvoiced(ctx, ticketsIds, myOptions); + await models.Ticket.canBeInvoiced(ctx, ticketsIds, !!invoiceCorrection, myOptions); const [firstTicket] = tickets; const clientId = firstTicket.clientFk; - const clientCanBeInvoiced = await models.Client.canBeInvoiced(clientId, companyFk, invoiceCorrection, myOptions); - if (!clientCanBeInvoiced && !invoiceCorrection) + const clientCanBeInvoiced = + await models.Client.canBeInvoiced(clientId, companyFk, myOptions); + + if (!clientCanBeInvoiced) throw new UserError(`This client can't be invoiced`); - const query = `SELECT vn.invoiceSerial(?, ?, ?) AS serial`; - const [{serial}] = await Self.rawSql(query, [ - clientId, - companyFk, - invoiceType, - ], myOptions); + const [{serial}] = invoiceCorrection ? [{serial: 'R'}] : await Self.rawSql( + `SELECT vn.invoiceSerial(?, ?, ?) AS serial`, + [ + clientId, + companyFk, + invoiceType + ], + myOptions); const invoiceOutSerial = await models.InvoiceOutSerial.findById(serial); if (invoiceOutSerial?.taxAreaFk == 'WORLD') { @@ -92,7 +96,7 @@ module.exports = function(Self) { await Self.rawSql('CALL invoiceOut_new(?, ?, null, @invoiceId)', [serial, invoiceDate], myOptions); const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions); - if (!resultInvoice) + if (!resultInvoice?.id) throw new UserError('No tickets to invoice', 'notInvoiced'); if (invoiceCorrection) { @@ -102,7 +106,7 @@ module.exports = function(Self) { ); } - if (serial != 'R' && resultInvoice.id) + if (resultInvoice.id) // serial != 'R' && await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions); if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js index 538dbc49f..e443ed6d3 100644 --- a/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js +++ b/modules/ticket/back/methods/ticket/specs/canBeInvoiced.spec.js @@ -27,7 +27,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(false); @@ -59,7 +59,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(false); @@ -95,7 +95,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(false); @@ -123,7 +123,7 @@ describe('ticket canBeInvoiced()', () => { WHERE id IN (?) `, [ticketId], options); - const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], options); + const canBeInvoiced = await models.Ticket.canBeInvoiced(ctx, [ticketId], false, options); expect(canBeInvoiced).toEqual(true); diff --git a/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js b/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js index 8971fb24a..162dc066a 100644 --- a/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js +++ b/modules/ticket/back/methods/ticket/specs/invoiceTickets.spec.js @@ -31,7 +31,7 @@ describe('ticket invoiceTickets()', () => { const options = {transaction: tx}; const ticketsIds = [11, 16]; - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); await tx.rollback(); } catch (e) { @@ -57,7 +57,7 @@ describe('ticket invoiceTickets()', () => { await client.updateAttribute('isTaxDataChecked', false, options); const ticketsIds = [11]; - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); await tx.rollback(); } catch (e) { @@ -80,8 +80,8 @@ describe('ticket invoiceTickets()', () => { const options = {transaction: tx}; const ticketsIds = [11]; - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); - await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); + await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); await tx.rollback(); } catch (e) { @@ -102,7 +102,7 @@ describe('ticket invoiceTickets()', () => { const options = {transaction: tx}; const ticketsIds = [11]; - const invoicesIds = await models.Ticket.invoiceTickets(ctx, ticketsIds, options); + const invoicesIds = await models.Ticket.invoiceTickets(ctx, ticketsIds, null, options); expect(invoicesIds.length).toBeGreaterThan(0); diff --git a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js index 9b1fd8f6f..456303602 100644 --- a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js +++ b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js @@ -42,7 +42,7 @@ describe('ticket makeInvoice()', () => { WHERE id IN (?) `, [ticketsIds], options); - const invoiceId = await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, options); + const invoiceId = await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, null, options); expect(invoiceId).toBeDefined(); @@ -70,7 +70,7 @@ describe('ticket makeInvoice()', () => { WHERE id IN (?) `, [ticketsId], options); - await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, options); + await models.Ticket.makeInvoice(ctx, invoiceType, companyFk, invoiceDate, null, options); await tx.rollback(); } catch (e) { error = e; diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 18db8c147..cd819e623 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -292,7 +292,7 @@ class Controller extends Section { const query = 'Tickets/refund'; return 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 })); diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index 1bb270165..c755b14c3 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -262,11 +262,12 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { const params = { ticketsIds: [16] }; - $httpBackend.expectPOST('Tickets/refund', params).respond({id: 99}); + const response = {id: 99}; + $httpBackend.expectPOST('Tickets/refund', params).respond([response]); controller.refund(); $httpBackend.flush(); - expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', {id: 99}); + expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.sale', response); }); }); diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index 4f6a9e757..ed6d9b10a 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -526,7 +526,7 @@ class Controller extends Section { const params = {salesIds: salesIds, withWarehouse: withWarehouse}; const query = 'Sales/refund'; 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 })); diff --git a/modules/ticket/front/sale/index.spec.js b/modules/ticket/front/sale/index.spec.js index 70781eb58..36be32f52 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/refund', params).respond(200, [refundTicket]); controller.createRefund(); $httpBackend.flush();