From ca3ac64072f0480650b7f9dd623e99b1d75172a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Tue, 1 Oct 2024 16:37:12 +0200 Subject: [PATCH 01/22] feat: refs #4460 invoiceIn refund --- db/routines/sage/procedures/invoiceIn_add.sql | 18 +++---- .../sage/procedures/invoiceOut_add.sql | 5 +- .../00-firstScript.sql | 47 +++++++++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 db/versions/11266-goldenChrysanthemum/00-firstScript.sql diff --git a/db/routines/sage/procedures/invoiceIn_add.sql b/db/routines/sage/procedures/invoiceIn_add.sql index 0898d6810..ba7a0c6c0 100644 --- a/db/routines/sage/procedures/invoiceIn_add.sql +++ b/db/routines/sage/procedures/invoiceIn_add.sql @@ -4,10 +4,10 @@ BEGIN /** * Traslada la info de contabilidad relacionada con las facturas recibidas * - * @vInvoiceInFk Factura recibida - * @vXDiarioFk Id tabla XDiario + * @param vInvoiceInFk Factura recibida + * @param vXDiarioFk Id tabla XDiario */ - DECLARE vInvoiceInOriginalFk INT; + DECLARE vInvoiceInOriginalFk INT; DECLARE vDone BOOL DEFAULT FALSE; DECLARE vBase DOUBLE; DECLARE vVat DOUBLE; @@ -204,9 +204,9 @@ BEGIN WHERE correctingFk = vInvoiceInFk; IF vInvoiceInOriginalFk THEN - UPDATE movContaIVA mci - JOIN vn.invoiceInRefund iir ON iir.invoiceInRefundFk = vInvoiceInFk + JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk + JOIN vn.siiTypeInvoiceOut st ON st.id = iic.siiTypeInvoiceOutFk JOIN (SELECT issued, SUM(sub.taxableBase) taxableBase, SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat @@ -215,20 +215,20 @@ BEGIN ti.PorcentajeIva FROM vn.invoiceIn i JOIN vn.invoiceInTax iit ON iit.invoiceInFk = i.id - JOIN sage.TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk + JOIN TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk WHERE i.id = vInvoiceInOriginalFk GROUP BY ti.CodigoIva)sub )invoiceInOriginal JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa' - SET mci.TipoRectificativa = iir.refundCategoryFk, - mci.ClaseAbonoRectificativas = iir.refundType, + SET mci.TipoRectificativa = iic.cplusRectificationTypeFk, + mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''), mci.FechaFacturaOriginal = invoiceInOriginal.issued, mci.FechaOperacion = invoiceInOriginal.issued, mci.BaseImponibleOriginal = invoiceInOriginal.taxableBase, mci.CuotaIvaOriginal = invoiceInOriginal.vat, mci.ClaveOperacionFactura = co.ClaveOperacionFactura_ WHERE mci.id = vXDiarioFk; - END IF; END$$ +$$ DELIMITER ; \ No newline at end of file diff --git a/db/routines/sage/procedures/invoiceOut_add.sql b/db/routines/sage/procedures/invoiceOut_add.sql index 95d6a56dd..f9c6f6b87 100644 --- a/db/routines/sage/procedures/invoiceOut_add.sql +++ b/db/routines/sage/procedures/invoiceOut_add.sql @@ -169,6 +169,7 @@ BEGIN UPDATE movContaIVA mci JOIN vn.invoiceOut i ON i.id = vInvoiceOutCorrectedFk JOIN vn.invoiceCorrection ic ON ic.correctedFk = vInvoiceOutCorrectedFk + JOIN vn.siiTypeInvoiceOut st ON st.id = ic.siiTypeInvoiceOutFk JOIN (SELECT SUM(IF(IFNULL(e.vatFk, TRUE), iot.taxableBase, 0)) taxableBase, SUM(IF(IFNULL(e.vatFk, TRUE), iot.vat, 0)) vat, SUM(IF(IFNULL(e.vatFk, TRUE), 0, iot.vat)) equ @@ -177,8 +178,8 @@ BEGIN WHERE iot.invoiceOutFk = vInvoiceOutCorrectedFk ) tax JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa' - SET mci.TipoRectificativa = 2, - mci.ClaseAbonoRectificativas = 1, + SET mci.TipoRectificativa = ic.cplusRectificationTypeFk, + mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''), mci.FechaFacturaOriginal = i.issued, mci.FechaOperacion = i.issued, mci.BaseImponibleOriginal = tax.taxableBase, diff --git a/db/versions/11266-goldenChrysanthemum/00-firstScript.sql b/db/versions/11266-goldenChrysanthemum/00-firstScript.sql new file mode 100644 index 000000000..37143c99b --- /dev/null +++ b/db/versions/11266-goldenChrysanthemum/00-firstScript.sql @@ -0,0 +1,47 @@ + USE vn; + + DROP TRIGGER IF EXISTS invoiceIn_beforeUpdate; + + UPDATE vn.invoiceIn + SET cplusRectificationTypeFk = NULL + WHERE cplusRectificationTypeFk = 1; + + DELETE IGNORE FROM vn.cplusRectificationType WHERE id = 1; + + UPDATE vn.cplusRectificationType + SET id = 1 + WHERE id = 3; + +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_beforeUpdate` + BEFORE UPDATE ON `invoiceIn` + FOR EACH ROW +BEGIN + DECLARE vWithholdingSageFk INT; + + IF NOT (NEW.supplierRef <=> OLD.supplierRef) AND NOT util.checkPrintableChars(NEW.supplierRef) THEN + CALL util.throw('The invoiceIn reference contains invalid characters'); + END IF; + + SET NEW.editorFk = account.myUser_getId(); + + IF (SELECT COUNT(*) FROM vn.invoiceIn + WHERE supplierRef = NEW.supplierRef + AND supplierFk = NEW.supplierFk + AND YEAR(issued) = YEAR(NEW.issued) + AND id <> NEW.id + ) THEN + CALL util.throw('reference duplicated'); + END IF; + + IF NEW.supplierFk != OLD.supplierFk THEN + CALL supplier_checkIsActive(NEW.supplierFk); + SELECT withholdingSageFk INTO vWithholdingSageFk + FROM vn.supplier + WHERE id = NEW.supplierFk; + SET NEW.withholdingSageFk = vWithholdingSageFk; + END IF; + +END$$ +DELIMITER ; + From 2a1fa8ca68d34e67767c954fa808c1f51d5e728b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Tue, 1 Oct 2024 18:55:29 +0200 Subject: [PATCH 02/22] feat: refs #4466 invoiceIn refund --- db/routines/vn/procedures/invoiceIn_booking.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/routines/vn/procedures/invoiceIn_booking.sql b/db/routines/vn/procedures/invoiceIn_booking.sql index 36189afcc..3d1ca402a 100644 --- a/db/routines/vn/procedures/invoiceIn_booking.sql +++ b/db/routines/vn/procedures/invoiceIn_booking.sql @@ -43,7 +43,7 @@ BEGIN ii.cplusTaxBreakFk, ii.cplusSubjectOpFk, ii.siiTypeInvoiceInFk, - ii.cplusRectificationTypeFk, + ic.cplusRectificationTypeFk, ii.booked, IFNULL(a.isUeeMember, c.isUeeMember) isUeeMember, (c.id = cc.id) isSameCountry, @@ -66,6 +66,7 @@ BEGIN e.name expenseName FROM invoiceIn ii JOIN supplier s ON s.id = ii.supplierFk + LEFT JOIN invoiceInCorrection ic ON ic.correctingFk = ii.id LEFT JOIN province p ON p.id = s.provinceFk LEFT JOIN autonomy a ON a.id = p.autonomyFk JOIN country c ON c.id = s.countryFk From 9a645c3288bb2db2bcb5604c0500d4c2a283a422 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 26 Nov 2024 16:56:39 +0100 Subject: [PATCH 03/22] fix: refs #7936 add IF NOT EXISTS to isRaid column in travel table --- db/versions/11332-tealErica/00-firstScript.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/versions/11332-tealErica/00-firstScript.sql b/db/versions/11332-tealErica/00-firstScript.sql index 6358695b2..957aa57e2 100644 --- a/db/versions/11332-tealErica/00-firstScript.sql +++ b/db/versions/11332-tealErica/00-firstScript.sql @@ -1,4 +1,4 @@ -ALTER TABLE vn.travel ADD isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; +ALTER TABLE vn.travel ADD IF NOT EXISTS isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; ALTER TABLE vn.travel MODIFY COLUMN daysInForward int(10) unsigned DEFAULT NULL COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada'; From a68e287b23cfc568574a215562a629562e2d0465 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 26 Nov 2024 17:01:50 +0100 Subject: [PATCH 04/22] refactor: refs #7936 remove old trigger and add isRaid column to travel table --- db/versions/11332-tealErica/00-firstScript.sql | 2 +- .../00-firstScript.sql | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename db/versions/{11266-goldenChrysanthemum => 11368-whiteAspidistra}/00-firstScript.sql (99%) diff --git a/db/versions/11332-tealErica/00-firstScript.sql b/db/versions/11332-tealErica/00-firstScript.sql index 957aa57e2..6358695b2 100644 --- a/db/versions/11332-tealErica/00-firstScript.sql +++ b/db/versions/11332-tealErica/00-firstScript.sql @@ -1,4 +1,4 @@ -ALTER TABLE vn.travel ADD IF NOT EXISTS isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; +ALTER TABLE vn.travel ADD isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; ALTER TABLE vn.travel MODIFY COLUMN daysInForward int(10) unsigned DEFAULT NULL COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada'; diff --git a/db/versions/11266-goldenChrysanthemum/00-firstScript.sql b/db/versions/11368-whiteAspidistra/00-firstScript.sql similarity index 99% rename from db/versions/11266-goldenChrysanthemum/00-firstScript.sql rename to db/versions/11368-whiteAspidistra/00-firstScript.sql index 37143c99b..333fa1315 100644 --- a/db/versions/11266-goldenChrysanthemum/00-firstScript.sql +++ b/db/versions/11368-whiteAspidistra/00-firstScript.sql @@ -45,3 +45,4 @@ BEGIN END$$ DELIMITER ; + From 6ab25c2ff588c82db06cde389ccdc4fd73efff58 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 26 Nov 2024 17:06:45 +0100 Subject: [PATCH 05/22] fix: refs #7936 add IF NOT EXISTS to isRaid column in travel table --- db/versions/11332-tealErica/00-firstScript.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/versions/11332-tealErica/00-firstScript.sql b/db/versions/11332-tealErica/00-firstScript.sql index 6358695b2..a7870632f 100644 --- a/db/versions/11332-tealErica/00-firstScript.sql +++ b/db/versions/11332-tealErica/00-firstScript.sql @@ -1,4 +1,4 @@ -ALTER TABLE vn.travel ADD isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; +ALTER TABLE vn.travel ADD IF NOT EXISTS isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; ALTER TABLE vn.travel MODIFY COLUMN daysInForward int(10) unsigned DEFAULT NULL - COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada'; + COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada'; \ No newline at end of file From 5db1262e082d52d2f5333f7c452aa30a5d69d723 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 27 Nov 2024 10:24:13 +0100 Subject: [PATCH 06/22] feat: refs #7936 add company filter --- .../invoiceIn/back/methods/invoice-in/filter.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/filter.js b/modules/invoiceIn/back/methods/invoice-in/filter.js index 936f7bb6c..c549769ab 100644 --- a/modules/invoiceIn/back/methods/invoice-in/filter.js +++ b/modules/invoiceIn/back/methods/invoice-in/filter.js @@ -91,6 +91,10 @@ module.exports = Self => { { arg: 'supplierActivityFk', type: 'string', + }, + { + arg: 'companyFk', + type: 'number', } ], returns: { @@ -161,8 +165,8 @@ module.exports = Self => { : {'ii.id': {nin: correcteds.map(x => x.correctingFk)}}; case 'correctedFk': return {'ii.id': {inq: correctings.map(x => x.correctingFk)}}; - case 'supplierActivityFk': - return {'s.supplierActivityFk': value}; + case 'companyFk': + return {'ii.companyFk': value}; } }); @@ -184,7 +188,8 @@ module.exports = Self => { s.name supplierName, s.account, SUM(iid.amount) amount, - sub.code awbCode + sub.code awbCode, + c.code FROM invoiceIn ii JOIN supplier s ON s.id = ii.supplierFk LEFT JOIN invoiceInDueDay iid ON iid.invoiceInFk = ii.id @@ -199,7 +204,8 @@ module.exports = Self => { GROUP BY de.duaFk ) sub ON sub.duaFk = d.id LEFT JOIN company co ON co.id = ii.companyFk - LEFT JOIN dms dm ON dm.id = ii.docFk` + LEFT JOIN dms dm ON dm.id = ii.docFk + JOIN company c ON c.id = ii.companyFk`, ); const sqlWhere = conn.makeWhere(filter.where); From ba51052d8836ab43df51f36baa21bc62392329fd Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 27 Nov 2024 17:52:45 +0100 Subject: [PATCH 07/22] feat: refs #7936 add SiiTypeInvoiceIn model and update invoice correction logic --- db/routines/sage/procedures/invoiceIn_add.sql | 2 +- db/versions/11368-whiteAspidistra/01-acls.sql | 23 +++++++++++++++++++ .../back/methods/invoice-in/corrective.js | 2 +- .../invoice-in/specs/corrective.spec.js | 2 +- .../back/models/invoice-in-correction.json | 7 +++--- modules/invoiceOut/back/model-config.json | 5 +++- .../back/models/sii-type-invoice-in.json | 22 ++++++++++++++++++ .../back/models/sii-type-invoice-out.json | 5 +--- 8 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 db/versions/11368-whiteAspidistra/01-acls.sql create mode 100644 modules/invoiceOut/back/models/sii-type-invoice-in.json diff --git a/db/routines/sage/procedures/invoiceIn_add.sql b/db/routines/sage/procedures/invoiceIn_add.sql index a3de50d6a..eeeb28143 100644 --- a/db/routines/sage/procedures/invoiceIn_add.sql +++ b/db/routines/sage/procedures/invoiceIn_add.sql @@ -207,7 +207,7 @@ BEGIN IF vInvoiceInOriginalFk THEN UPDATE movContaIVA mci JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk - JOIN vn.siiTypeInvoiceOut st ON st.id = iic.siiTypeInvoiceOutFk + JOIN vn.siiTypeInvoiceIn st ON st.id = iic.siiTypeInvoiceInFk JOIN (SELECT issued, SUM(sub.taxableBase) taxableBase, SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat diff --git a/db/versions/11368-whiteAspidistra/01-acls.sql b/db/versions/11368-whiteAspidistra/01-acls.sql new file mode 100644 index 000000000..6ac98db43 --- /dev/null +++ b/db/versions/11368-whiteAspidistra/01-acls.sql @@ -0,0 +1,23 @@ +INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) + VALUES('SiiTypeInvoiceIn', 'find', 'READ', 'ALLOW', 'ROLE', 'salesPerson'); + +DROP TABLE IF EXISTS vn.invoiceInCorrection; + +CREATE TABLE `invoiceInCorrection` ( + `correctingFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificativa', + `correctedFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificada', + `cplusRectificationTypeFk` int(10) unsigned NOT NULL, + `siiTypeInvoiceInFk` int(10) unsigned NOT NULL, + `invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3, + PRIMARY KEY (`correctingFk`), + KEY `invoiceInCorrection_correctedFk` (`correctedFk`), + KEY `invoiceInCorrection_cplusRectificationTypeFk` (`cplusRectificationTypeFk`), + KEY `invoiceInCorrection_siiTypeInvoiceIn` (`siiTypeInvoiceInFk`), + KEY `invoiceInCorrection_invoiceCorrectionTypeFk` (`invoiceCorrectionTypeFk`), + CONSTRAINT `invoiceInCorrection_correctedFk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_correctingFk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_cplusRectificationTypeFk` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_invoiceCorrectionTypeFk` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_siiTypeInvoiceIn` FOREIGN KEY (`siiTypeInvoiceInFk`) REFERENCES `siiTypeInvoiceIn` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + diff --git a/modules/invoiceIn/back/methods/invoice-in/corrective.js b/modules/invoiceIn/back/methods/invoice-in/corrective.js index 05f632bcd..e7088d201 100644 --- a/modules/invoiceIn/back/methods/invoice-in/corrective.js +++ b/modules/invoiceIn/back/methods/invoice-in/corrective.js @@ -44,7 +44,7 @@ module.exports = Self => { correctingFk: clone.id, correctedFk: id, cplusRectificationTypeFk: invoiceType, - siiTypeInvoiceOutFk: invoiceClass, + siiTypeInvoiceInFk: invoiceClass, invoiceCorrectionTypeFk: invoiceReason }, myOptions); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js index c63f02439..9f085694b 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js @@ -30,7 +30,7 @@ describe('invoiceIn corrective()', () => { }, options); expect(correction.cplusRectificationTypeFk).toEqual(invoiceType); - expect(correction.siiTypeInvoiceOutFk).toEqual(invoiceClass); + expect(correction.siiTypeInvoiceInFk).toEqual(invoiceClass); expect(correction.invoiceCorrectionTypeFk).toEqual(invoiceReason); }); }); diff --git a/modules/invoiceIn/back/models/invoice-in-correction.json b/modules/invoiceIn/back/models/invoice-in-correction.json index 52e16d420..d353f9e98 100644 --- a/modules/invoiceIn/back/models/invoice-in-correction.json +++ b/modules/invoiceIn/back/models/invoice-in-correction.json @@ -28,11 +28,10 @@ "model": "InvoiceCorrectionType", "foreignKey": "invoiceCorrectionTypeFk" }, - "siiTypeInvoiceOut": { + "siiTypeInvoiceIn": { "type": "belongsTo", - "model": "SiiTypeInvoiceOut", - "foreignKey": "siiTypeInvoiceOutFk" + "model": "SiiTypeInvoiceIn", + "foreignKey": "siiTypeInvoiceInFk" } - } } \ No newline at end of file diff --git a/modules/invoiceOut/back/model-config.json b/modules/invoiceOut/back/model-config.json index 9c7512429..710d824c3 100644 --- a/modules/invoiceOut/back/model-config.json +++ b/modules/invoiceOut/back/model-config.json @@ -43,5 +43,8 @@ }, "SiiTypeInvoiceOut": { "dataSource": "vn" + }, + "SiiTypeInvoiceIn": { + "dataSource": "vn" } -} +} \ No newline at end of file diff --git a/modules/invoiceOut/back/models/sii-type-invoice-in.json b/modules/invoiceOut/back/models/sii-type-invoice-in.json new file mode 100644 index 000000000..a191febb9 --- /dev/null +++ b/modules/invoiceOut/back/models/sii-type-invoice-in.json @@ -0,0 +1,22 @@ +{ + "name": "SiiTypeInvoiceIn", + "base": "VnModel", + "options": { + "mysql": { + "table": "siiTypeInvoiceIn" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/modules/invoiceOut/back/models/sii-type-invoice-out.json b/modules/invoiceOut/back/models/sii-type-invoice-out.json index 37fd39c38..89f01bd74 100644 --- a/modules/invoiceOut/back/models/sii-type-invoice-out.json +++ b/modules/invoiceOut/back/models/sii-type-invoice-out.json @@ -17,9 +17,6 @@ }, "description": { "type": "string" - }, - "code": { - "type": "string" } } -} +} \ No newline at end of file From 7d5ae9dfbd4a0ba3a6ec4b34a46473ab475f4e1b Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 28 Nov 2024 14:52:41 +0100 Subject: [PATCH 08/22] feat: refs #7936 add reference rates for currency in fixtures --- db/dump/fixtures.before.sql | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index e5d5f53dc..542d3dfe9 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -4033,3 +4033,8 @@ INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel) INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate) VALUES (1106,'26493101E','2019-09-20'); + +INSERT INTO vn.referenceRate (currencyFk, dated, value) + VALUES (2, '2000-12-01', 1.0495), + (2, '2001-01-01', 1.0531), + (2, '2001-02-01', 7.6347); \ No newline at end of file From 1f6e401e39c45fbb404b8c9434b0f9cb3d052169 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 11:53:07 +0100 Subject: [PATCH 09/22] feat: refs #7936 add save validation --- .../invoiceIn/back/methods/invoice-in/toUnbook.js | 3 ++- .../back/methods/invoice-in/updateInvoiceIn.js | 3 ++- modules/invoiceIn/back/models/invoice-in.js | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/toUnbook.js b/modules/invoiceIn/back/methods/invoice-in/toUnbook.js index a697e9ddc..c27354d73 100644 --- a/modules/invoiceIn/back/methods/invoice-in/toUnbook.js +++ b/modules/invoiceIn/back/methods/invoice-in/toUnbook.js @@ -52,7 +52,8 @@ module.exports = Self => { accountingEntries = await models.Xdiario.count({ASIEN: asien}, myOptions); await models.Xdiario.destroyAll({ASIEN: asien}, myOptions); - await Self.updateAll({id: invoiceInId}, {isBooked: false}, myOptions); + const invoiceIn = await Self.findById(invoiceInId, myOptions); + await invoiceIn.updateAttribute('isBooked', false, myOptions); } else { const linkedBookEntry = await models.Xdiario.findOne({ fields: ['ASIEN'], diff --git a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js index 92a1ba8ee..2f1b4caca 100644 --- a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js +++ b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js @@ -82,7 +82,7 @@ module.exports = Self => { try { const invoiceIn = await Self.findById(id, null, myOptions); - invoiceIn.updateAttributes({supplierFk, + await invoiceIn.updateAttributes({supplierFk, supplierRef, issued, operated, @@ -94,6 +94,7 @@ module.exports = Self => { companyFk, withholdingSageFk }, myOptions); + if (tx) await tx.commit(); return invoiceIn; } catch (e) { diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 1e69c0ef8..21aa230c5 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -19,4 +19,19 @@ module.exports = Self => { return new UserError(`This invoice has a linked vehicle.`); return err; }); + + Self.observe('before save', async function(ctx) { + if (ctx.newInstance) return; + + const changes = ctx.data || ctx.instance; + const orgData = ctx.currentInstance; + let isNotEditable = orgData.isBooked || (!orgData.isBooked && changes.isBooked); + + if (isNotEditable) { + for (const [key, value] of Object.entries(changes)) { + if (key !== 'isBooked' && value !== orgData[key]) + throw new UserError('InvoiceIn is already booked'); + } + } + }); }; From 332e1c62d9e1361df960d2a0e99033c4b5263e74 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 12:22:01 +0100 Subject: [PATCH 10/22] feat: refs #7936 add validation to InvoiceIn & InvoiceInTax --- .../invoiceIn/back/models/invoice-in-tax.js | 18 ++++++++++++++++++ modules/invoiceIn/back/models/invoice-in.js | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 modules/invoiceIn/back/models/invoice-in-tax.js diff --git a/modules/invoiceIn/back/models/invoice-in-tax.js b/modules/invoiceIn/back/models/invoice-in-tax.js new file mode 100644 index 000000000..a9d16ec42 --- /dev/null +++ b/modules/invoiceIn/back/models/invoice-in-tax.js @@ -0,0 +1,18 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.observe('before save', async function(ctx) { + if (ctx.newInstance) return; + + const models = Self.app.models; + const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk); + if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); + }); + + Self.observe('before delete', async function(ctx) { + const models = Self.app.models; + const invoiceInTax = await models.InvoiceInTax.findById(ctx.where.id); + const invoiceIn = await models.InvoiceIn.findById(invoiceInTax.invoiceInFk); + if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); + }); +}; diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 21aa230c5..ff5d1ba86 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -34,4 +34,10 @@ module.exports = Self => { } } }); + + Self.observe('before delete', async function(ctx) { + const invoiceIn = await Self.findById(ctx.where.id); + if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); + }); }; + From 9ece52c5cecf15fa6d7350999f27cc3dd68d1b71 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 12:42:15 +0100 Subject: [PATCH 11/22] feat: refs #7936 add currency check to updateInvoiceIn --- .../back/methods/invoice-in/updateInvoiceIn.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js index 2f1b4caca..2b059f07b 100644 --- a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js +++ b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js @@ -72,6 +72,7 @@ module.exports = Self => { ) => { let tx; const myOptions = {userId: ctx.req.accessToken.userId}; + const models = Self.app.models; if (typeof options == 'object') Object.assign(myOptions, options); @@ -95,6 +96,17 @@ module.exports = Self => { withholdingSageFk }, myOptions); + if (currencyFk) { + const currency = await models.Currency.findById(currencyFk, null, myOptions); + if (currency.code === 'EUR') { + const invoiceInTaxes = await models.InvoiceInTax.find( + {where: {invoiceInFk: id}}, myOptions); + + for (const invoiceInTax of invoiceInTaxes) + await invoiceInTax.updateAttribute('foreignValue', null, myOptions); + } + } + if (tx) await tx.commit(); return invoiceIn; } catch (e) { From 163c6ddd20b2846cff8a01d2415aa0fb317facf0 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 13:44:42 +0100 Subject: [PATCH 12/22] feat: refs #7936 add currency handling in invoiceIn trigger --- .../vn/triggers/invoiceIn_afterUpdate.sql | 18 ++++++++++++------ .../back/methods/invoice-in/updateInvoiceIn.js | 11 ----------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql index 95b1d98a9..8f0a63465 100644 --- a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql +++ b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql @@ -3,24 +3,30 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_afterUpdate` AFTER UPDATE ON `invoiceIn` FOR EACH ROW BEGIN - IF NEW.issued != OLD.issued - OR NEW.currencyFk != OLD.currencyFk THEN + DECLARE vIsEuro BOOL; + + SELECT if(`code` = 'EUR', TRUE, FALSE) INTO vIsEuro + FROM currency + WHERE id = NEW.currencyFk; + + IF (NOT NEW.issued <=> OLD.issued + OR NEW.currencyFk <> OLD.currencyFk) THEN UPDATE invoiceInTax iit JOIN invoiceIn ii ON ii.id = iit.invoiceInFk LEFT JOIN referenceRate rr ON rr.dated = ii.issued AND rr.currencyFk = ii.currencyFk - SET iit.taxableBase = IF(iit.foreignValue IS NULL, iit.taxableBase, iit.foreignValue / rr.value) + SET iit.taxableBase = IF(vIsEuro, iit.taxableBase, iit.foreignValue / rr.value), + iit.foreignValue = IF(vIsEuro, NULL, iit.foreignValue) WHERE ii.id = NEW.id; UPDATE invoiceInDueDay iidd JOIN invoiceIn ii ON ii.id = iidd.invoiceInFk LEFT JOIN referenceRate rr ON rr.dated = ii.issued AND rr.currencyFk = ii.currencyFk - SET iidd.amount = IF(iidd.foreignValue IS NULL, iidd.amount, iidd.foreignValue / rr.value) + SET iidd.amount = IF(vIsEuro, iidd.amount, iidd.foreignValue / rr.value), + iidd.foreignValue = IF(vIsEuro, NULL, iidd.foreignValue) WHERE ii.id = NEW.id; - END IF; - END$$ DELIMITER ; diff --git a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js index 2b059f07b..6006b1b14 100644 --- a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js +++ b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js @@ -96,17 +96,6 @@ module.exports = Self => { withholdingSageFk }, myOptions); - if (currencyFk) { - const currency = await models.Currency.findById(currencyFk, null, myOptions); - if (currency.code === 'EUR') { - const invoiceInTaxes = await models.InvoiceInTax.find( - {where: {invoiceInFk: id}}, myOptions); - - for (const invoiceInTax of invoiceInTaxes) - await invoiceInTax.updateAttribute('foreignValue', null, myOptions); - } - } - if (tx) await tx.commit(); return invoiceIn; } catch (e) { From c9cf96676b15f0d2d45469a3fbda417422008b8d Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 14:32:12 +0100 Subject: [PATCH 13/22] fix: refs #7936 check if insert in hook & change test description --- .../back/methods/invoice-in/specs/corrective.spec.js | 4 ++-- modules/invoiceIn/back/models/invoice-in-tax.js | 2 +- modules/invoiceIn/back/models/invoice-in.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js index 9f085694b..aee8d3f2c 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js @@ -15,11 +15,11 @@ describe('invoiceIn corrective()', () => { await tx.rollback(); }); - it('La función corrective debería devolver un id cuando se ejecuta correctamente', async() => { + it('should return an id when executed correctly', async() => { const originalId = 1; const invoiceReason = 3; const invoiceType = 2; - const invoiceClass = 1; + const invoiceClass = 8; const cloneId = await models.InvoiceIn.corrective(ctx, originalId, invoiceReason, invoiceType, invoiceClass, options); diff --git a/modules/invoiceIn/back/models/invoice-in-tax.js b/modules/invoiceIn/back/models/invoice-in-tax.js index a9d16ec42..0449d7719 100644 --- a/modules/invoiceIn/back/models/invoice-in-tax.js +++ b/modules/invoiceIn/back/models/invoice-in-tax.js @@ -2,7 +2,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.observe('before save', async function(ctx) { - if (ctx.newInstance) return; + if (ctx.isNewInstance) return; const models = Self.app.models; const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk); diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index ff5d1ba86..ac197e904 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -21,7 +21,7 @@ module.exports = Self => { }); Self.observe('before save', async function(ctx) { - if (ctx.newInstance) return; + if (ctx.isNewInstance) return; const changes = ctx.data || ctx.instance; const orgData = ctx.currentInstance; From ac87905351ef6dbebaaee042f3c78132c44706d8 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 15:49:14 +0100 Subject: [PATCH 14/22] feat: refs #7936 add back test for updateInvoiceIn --- .../invoice-in/specs/updateInvoiceIn.spec.js | 59 +++++++++++++++++++ .../methods/invoice-in/updateInvoiceIn.js | 1 - 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js new file mode 100644 index 000000000..4e856ec71 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js @@ -0,0 +1,59 @@ +const models = require('vn-loopback/server/server').models; + +const invoiceInId = 1; +const supplierId = 791; +fdescribe('invoiceIn updateInvoiceIn()', () => { + const ctx = beforeAll.getCtx(); + let options; + let tx; + + beforeEach(async() => { + options = {transaction: tx}; + tx = await models.Sale.beginTransaction({}); + options.transaction = tx; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should update the invoice', async() => { + const invoiceBefore = await models.InvoiceIn.findById(invoiceInId, null, options); + await update(ctx, options); + const invoiceAfter = await models.InvoiceIn.findById(invoiceInId, null, options); + + expect(invoiceAfter.supplierFk).not.toBe(invoiceBefore.supplierFk); + expect(invoiceAfter.supplierFk).toBe(supplierId); + }); + + it('should not update the invoice if is booked', async() => { + let error; + try { + await models.InvoiceIn.toBook(ctx, invoiceInId, options); + await update(ctx, options); + } catch (e) { + error = e; + } + + expect(error.message).toBe('InvoiceIn is already booked'); + }); +}); + +async function update(ctx, opts) { + const supplierRef = 'mockRef'; + const currencyId = 1; + await models.InvoiceIn.updateInvoiceIn(ctx, + invoiceInId, + supplierId, + supplierRef, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + currencyId, + undefined, + undefined, + opts); +} diff --git a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js index 6006b1b14..2f1b4caca 100644 --- a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js +++ b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js @@ -72,7 +72,6 @@ module.exports = Self => { ) => { let tx; const myOptions = {userId: ctx.req.accessToken.userId}; - const models = Self.app.models; if (typeof options == 'object') Object.assign(myOptions, options); From 59b5dd5a3627c08c8e1a5d0be468d00833cf68af Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 16:25:47 +0100 Subject: [PATCH 15/22] feat: refs #7936 add tests for invoiceIn --- .../invoice-in/specs/invoiceIn.spec.js | 66 +++++++++++++++++++ .../invoice-in/specs/updateInvoiceIn.spec.js | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js new file mode 100644 index 000000000..4e2ee36d5 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js @@ -0,0 +1,66 @@ +const models = require('vn-loopback/server/server').models; + +fdescribe('invoiceIn', () => { + let options; + let tx; + const invoiceId = 1; + const supplierId = 791; + const currencyId = 1; + const companyId = 442; + + beforeEach(async() => { + options = {transaction: tx}; + tx = await models.InvoiceIn.beginTransaction({}); + options.transaction = tx; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should allow insert for new instance', async() => { + const newInvoice = { + supplierFk: supplierId, + issued: Date.vnNew(), + operated: Date.vnNew(), + currencyFk: currencyId, + companyFk: companyId, + isBooked: false + }; + + const createdInvoice = await models.InvoiceIn.create(newInvoice, options); + + expect(createdInvoice).toBeDefined(); + expect(createdInvoice.id).toBeDefined(); + }); + + it('should throw an error if trying to update a booked invoice', async() => { + const invoice = await models.InvoiceIn.findById(invoiceId, null, options); + await invoice.updateAttribute('isBooked', true, options); + + let error; + try { + await invoice.updateAttribute('supplierFk', supplierId, options); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.message).toBe('InvoiceIn is already booked'); + }); + + it('should throw an error if trying to delete a booked invoice', async() => { + const invoice = await models.InvoiceIn.findById(invoiceId, null, options); + await invoice.updateAttribute('isBooked', true, options); + + let error; + try { + await models.InvoiceIn.deleteById(invoiceId, options); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.sqlMessage).toBe('InvoiceIn is already booked'); + }); +}); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js index 4e856ec71..773e2ac2f 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js @@ -2,7 +2,7 @@ const models = require('vn-loopback/server/server').models; const invoiceInId = 1; const supplierId = 791; -fdescribe('invoiceIn updateInvoiceIn()', () => { +describe('invoiceIn updateInvoiceIn()', () => { const ctx = beforeAll.getCtx(); let options; let tx; From 00085f2b99d61086908ee29975cd731cbcf5b2c9 Mon Sep 17 00:00:00 2001 From: jorgep Date: Fri, 29 Nov 2024 17:05:13 +0100 Subject: [PATCH 16/22] feat: refs #7936 add tests for invoiceIn filter --- .../methods/invoice-in/specs/filter.spec.js | 17 +++++++++++++++++ .../methods/invoice-in/specs/invoiceIn.spec.js | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js index 48310b32a..beaa608e6 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js @@ -166,4 +166,21 @@ describe('InvoiceIn filter()', () => { throw e; } }); + + it('should return the invoice in matching companyFk', async() => { + const tx = await models.InvoiceIn.beginTransaction({}); + const options = {transaction: tx}; + + try { + const company = await models.Company.findOne({}, options); + const invoicesByCompany = await models.InvoiceIn.find({where: {companyFk: company.id}}, options); + const filteredInvoices = await models.InvoiceIn.filter({args: {companyFk: company.id}}, {}, options); + + expect(filteredInvoices.length).toEqual(invoicesByCompany.length); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js index 4e2ee36d5..69038d9fd 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js @@ -1,6 +1,6 @@ const models = require('vn-loopback/server/server').models; -fdescribe('invoiceIn', () => { +describe('invoiceIn', () => { let options; let tx; const invoiceId = 1; From 5b04debfb157b6240e4e1ba2f6bf32814930b91b Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 2 Dec 2024 17:48:40 +0100 Subject: [PATCH 17/22] refactor: refs #7936 add transaction & tests --- .../invoice-in/specs/invoiceIn.spec.js | 7 +- .../invoice-in/specs/invoiceInTax.spec.js | 74 +++++++++++++++++++ .../invoiceIn/back/models/invoice-in-tax.js | 6 +- modules/invoiceIn/back/models/invoice-in.js | 2 +- 4 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js index 69038d9fd..a83aad3b2 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js @@ -9,9 +9,8 @@ describe('invoiceIn', () => { const companyId = 442; beforeEach(async() => { - options = {transaction: tx}; tx = await models.InvoiceIn.beginTransaction({}); - options.transaction = tx; + options = {transaction: tx}; }); afterEach(async() => { @@ -45,7 +44,6 @@ describe('invoiceIn', () => { error = err; } - expect(error).toBeDefined(); expect(error.message).toBe('InvoiceIn is already booked'); }); @@ -60,7 +58,6 @@ describe('invoiceIn', () => { error = err; } - expect(error).toBeDefined(); - expect(error.sqlMessage).toBe('InvoiceIn is already booked'); + expect(error.message).toBe('InvoiceIn is already booked'); }); }); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js new file mode 100644 index 000000000..e822189bd --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js @@ -0,0 +1,74 @@ +const models = require('vn-loopback/server/server').models; + +describe('invoiceInTax', () => { + let options; + let tx; + const invoiceInId = 1; + const invoiceInTaxId = 1; + beforeEach(async() => { + tx = await models.InvoiceInTax.beginTransaction({}); + options = {transaction: tx}; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should throw an error if trying to save a tax from a booked invoice', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttributes({isBooked: true}, options); + const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + let error; + try { + await invoiceInTax.updateAttribute('taxableBase', 100, options); + } catch (err) { + error = err; + } + + expect(error.message).toBe('InvoiceIn is already booked'); + }); + + it('should allow save if the invoice is not booked', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttribute('isBooked', false, options); + + const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + await invoiceInTax.updateAttribute('taxableBase', 100, options); + + const updatedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + + expect(updatedInvoiceInTax.taxableBase).toBe(100); + }); + + it('should throw an error if trying to delete a tax from a booked invoice', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttribute('isBooked', true, options); + + let error; + try { + await models.InvoiceInTax.destroyById(invoiceInTaxId, options); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.message).toBe('InvoiceIn is already booked'); + }); + + it('should allow delete if the invoice is not booked', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttribute('isBooked', false, options); + + let error; + try { + await models.InvoiceInTax.destroyById(invoiceInTaxId, options); + } catch (err) { + error = err; + } + + const deletedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + + expect(error).toBeUndefined(); + expect(deletedInvoiceInTax).toBeNull(); + }); +}); diff --git a/modules/invoiceIn/back/models/invoice-in-tax.js b/modules/invoiceIn/back/models/invoice-in-tax.js index 0449d7719..ce33fe18f 100644 --- a/modules/invoiceIn/back/models/invoice-in-tax.js +++ b/modules/invoiceIn/back/models/invoice-in-tax.js @@ -5,14 +5,14 @@ module.exports = Self => { if (ctx.isNewInstance) return; const models = Self.app.models; - const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk); + const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk, null, ctx.options); if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); }); Self.observe('before delete', async function(ctx) { const models = Self.app.models; - const invoiceInTax = await models.InvoiceInTax.findById(ctx.where.id); - const invoiceIn = await models.InvoiceIn.findById(invoiceInTax.invoiceInFk); + const invoiceInTax = await Self.findById(ctx.where.id, null, ctx.options); + const invoiceIn = await models.InvoiceIn.findById(invoiceInTax.invoiceInFk, null, ctx.options); if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); }); }; diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index ac197e904..ca506b54d 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -36,7 +36,7 @@ module.exports = Self => { }); Self.observe('before delete', async function(ctx) { - const invoiceIn = await Self.findById(ctx.where.id); + const invoiceIn = await Self.findById(ctx.where.id, null, ctx.options); if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); }); }; From f69dfbd5aa89463c52e315f9a6c35e8c863524d3 Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 9 Dec 2024 14:03:45 +0100 Subject: [PATCH 18/22] refactor: refs #7936 remove schema --- db/routines/vn/triggers/invoiceIn_afterUpdate.sql | 2 +- db/versions/11368-whiteAspidistra/00-firstScript.sql | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql index 8f0a63465..8c2785e38 100644 --- a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql +++ b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql @@ -5,7 +5,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_afterUpdate` BEGIN DECLARE vIsEuro BOOL; - SELECT if(`code` = 'EUR', TRUE, FALSE) INTO vIsEuro + SELECT `code` = 'EUR' INTO vIsEuro FROM currency WHERE id = NEW.currencyFk; diff --git a/db/versions/11368-whiteAspidistra/00-firstScript.sql b/db/versions/11368-whiteAspidistra/00-firstScript.sql index 333fa1315..f36832805 100644 --- a/db/versions/11368-whiteAspidistra/00-firstScript.sql +++ b/db/versions/11368-whiteAspidistra/00-firstScript.sql @@ -2,13 +2,13 @@ DROP TRIGGER IF EXISTS invoiceIn_beforeUpdate; - UPDATE vn.invoiceIn + UPDATE invoiceIn SET cplusRectificationTypeFk = NULL WHERE cplusRectificationTypeFk = 1; - DELETE IGNORE FROM vn.cplusRectificationType WHERE id = 1; + DELETE IGNORE FROM cplusRectificationType WHERE id = 1; - UPDATE vn.cplusRectificationType + UPDATE cplusRectificationType SET id = 1 WHERE id = 3; @@ -25,7 +25,7 @@ BEGIN SET NEW.editorFk = account.myUser_getId(); - IF (SELECT COUNT(*) FROM vn.invoiceIn + IF (SELECT COUNT(*) FROM invoiceIn WHERE supplierRef = NEW.supplierRef AND supplierFk = NEW.supplierFk AND YEAR(issued) = YEAR(NEW.issued) @@ -37,7 +37,7 @@ BEGIN IF NEW.supplierFk != OLD.supplierFk THEN CALL supplier_checkIsActive(NEW.supplierFk); SELECT withholdingSageFk INTO vWithholdingSageFk - FROM vn.supplier + FROM supplier WHERE id = NEW.supplierFk; SET NEW.withholdingSageFk = vWithholdingSageFk; END IF; From 46448d5fc20d5346c1cd0a70888b00f91f5d3172 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 10 Dec 2024 10:27:35 +0100 Subject: [PATCH 19/22] fix: refs #7936 change type --- modules/invoiceIn/back/models/invoice-in-tax.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/invoiceIn/back/models/invoice-in-tax.json b/modules/invoiceIn/back/models/invoice-in-tax.json index 53b5548b6..256ee0553 100644 --- a/modules/invoiceIn/back/models/invoice-in-tax.json +++ b/modules/invoiceIn/back/models/invoice-in-tax.json @@ -22,12 +22,11 @@ "type": "number" }, "expenseFk": { - "type": "number" + "type": "string" }, "created": { "type": "date" } - }, "relations": { "invoiceIn": { @@ -51,4 +50,4 @@ "foreignKey": "transactionTypeSageFk" } } -} +} \ No newline at end of file From addb093b6b37a76c19bce6b299cd0eb25c65b589 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 11 Dec 2024 17:42:03 +0100 Subject: [PATCH 20/22] feat: refs #7936 add minimum due date --- modules/invoiceIn/back/methods/invoice-in/filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/filter.js b/modules/invoiceIn/back/methods/invoice-in/filter.js index c549769ab..f081368e4 100644 --- a/modules/invoiceIn/back/methods/invoice-in/filter.js +++ b/modules/invoiceIn/back/methods/invoice-in/filter.js @@ -189,7 +189,8 @@ module.exports = Self => { s.account, SUM(iid.amount) amount, sub.code awbCode, - c.code + c.code, + MIN(iid.dueDated) dueDated FROM invoiceIn ii JOIN supplier s ON s.id = ii.supplierFk LEFT JOIN invoiceInDueDay iid ON iid.invoiceInFk = ii.id From c83f34859a02228e273b267e0e8717c5cc87df9e Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 12 Dec 2024 11:20:23 +0100 Subject: [PATCH 21/22] feat: refs #7936 return country code & is vies fields --- modules/invoiceIn/back/methods/invoice-in/summary.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/summary.js b/modules/invoiceIn/back/methods/invoice-in/summary.js index fe198b2b4..b3fd9ee97 100644 --- a/modules/invoiceIn/back/methods/invoice-in/summary.js +++ b/modules/invoiceIn/back/methods/invoice-in/summary.js @@ -37,7 +37,13 @@ module.exports = Self => { { relation: 'supplier', scope: { - fields: ['id', 'name'] + fields: ['id', 'name', 'isVies', 'countryFk'], + include: [{ + relation: 'country', + scope: { + fields: ['id', 'code'] + } + }] } }, { From d9eab361600ab1eddcd1f02576bebef0932146b3 Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 16 Dec 2024 09:35:41 +0100 Subject: [PATCH 22/22] fix: refs #7936 conflicts --- db/routines/sage/procedures/invoiceIn_add.sql | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/db/routines/sage/procedures/invoiceIn_add.sql b/db/routines/sage/procedures/invoiceIn_add.sql index eeeb28143..8fdbb9ce3 100644 --- a/db/routines/sage/procedures/invoiceIn_add.sql +++ b/db/routines/sage/procedures/invoiceIn_add.sql @@ -25,7 +25,7 @@ BEGIN DECLARE vIsInformativeExportation BOOL DEFAULT FALSE; DECLARE vCursor CURSOR FOR - SELECT it.taxableBase, + SELECT SUM(it.taxableBase), CAST(SUM((( it.taxableBase / 100) * t.PorcentajeIva)) AS DECIMAL (10,2)), t.PorcentajeIva, it.transactionTypeSageFk, @@ -204,25 +204,25 @@ BEGIN FROM vn.invoiceInCorrection WHERE correctingFk = vInvoiceInFk; - IF vInvoiceInOriginalFk THEN + IF vInvoiceInOriginalFk THEN UPDATE movContaIVA mci JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk JOIN vn.siiTypeInvoiceIn st ON st.id = iic.siiTypeInvoiceInFk JOIN (SELECT issued, - SUM(sub.taxableBase) taxableBase, + SUM(sub.taxableBase) taxableBase, SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat FROM(SELECT issued, - SUM(iit.taxableBase) taxableBase, + SUM(iit.taxableBase) taxableBase, ti.PorcentajeIva - FROM vn.invoiceIn i + FROM vn.invoiceIn i JOIN vn.invoiceInTax iit ON iit.invoiceInFk = i.id JOIN TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk WHERE i.id = vInvoiceInOriginalFk GROUP BY ti.CodigoIva)sub )invoiceInOriginal JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa' - SET mci.TipoRectificativa = iic.cplusRectificationTypeFk, - mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''), + SET mci.TipoRectificativa = iir.refundCategoryFk, + mci.ClaseAbonoRectificativas = iir.refundType, mci.FechaFacturaOriginal = invoiceInOriginal.issued, mci.FechaOperacion = invoiceInOriginal.issued, mci.BaseImponibleOriginal = invoiceInOriginal.taxableBase, @@ -231,5 +231,4 @@ BEGIN WHERE mci.id = vXDiarioFk; END IF; END$$ -$$ -DELIMITER ; \ No newline at end of file +DELIMITER ;