diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b938797e7..a672e79864 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [24.20.01] - 2024-05-14
+### Fixed
+- (Worker -> time-control) Corrección de errores
+- (InvoiceOut -> Crear factura) Cuando falla al crear una factura, se devuelve un error
+
## [24.18.01] - 2024-05-07
## [24.16.01] - 2024-04-18
diff --git a/back/model-config.json b/back/model-config.json
index ebcdb7bce8..e64386300e 100644
--- a/back/model-config.json
+++ b/back/model-config.json
@@ -124,6 +124,9 @@
"Postcode": {
"dataSource": "vn"
},
+ "ReferenceRate": {
+ "dataSource": "vn"
+ },
"SageWithholding": {
"dataSource": "vn"
},
@@ -177,5 +180,11 @@
},
"ProductionConfig": {
"dataSource": "vn"
+ },
+ "AgencyLog": {
+ "dataSource": "vn"
+ },
+ "AgencyWorkCenter": {
+ "dataSource": "vn"
}
-}
\ No newline at end of file
+}
diff --git a/back/models/agency-log.json b/back/models/agency-log.json
new file mode 100644
index 0000000000..04b0b29950
--- /dev/null
+++ b/back/models/agency-log.json
@@ -0,0 +1,9 @@
+{
+ "name": "AgencyLog",
+ "base": "Log",
+ "options": {
+ "mysql": {
+ "table": "agencyLog"
+ }
+ }
+}
diff --git a/back/models/agency-workCenter.js b/back/models/agency-workCenter.js
new file mode 100644
index 0000000000..32114355e8
--- /dev/null
+++ b/back/models/agency-workCenter.js
@@ -0,0 +1,8 @@
+const UserError = require('vn-loopback/util/user-error');
+module.exports = Self => {
+ Self.rewriteDbError(function(err) {
+ if (err.code === 'ER_DUP_ENTRY')
+ return new UserError(`This workCenter is already assigned to this agency`);
+ return err;
+ });
+};
diff --git a/back/models/agency-workCenter.json b/back/models/agency-workCenter.json
new file mode 100644
index 0000000000..adf1e5bcb0
--- /dev/null
+++ b/back/models/agency-workCenter.json
@@ -0,0 +1,41 @@
+{
+ "name": "AgencyWorkCenter",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "agencyWorkCenter"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "number",
+ "forceId": false
+ },
+ "agencyFk": {
+ "type": "number",
+ "required": false
+ },
+ "workCenterFk": {
+ "type": "number",
+ "required": false
+ }
+ },
+ "relations": {
+ "agency": {
+ "type": "belongsTo",
+ "model": "WorkCenter",
+ "foreignKey": "agencyFk"
+ },
+ "workCenter": {
+ "type": "belongsTo",
+ "model": "WorkCenter",
+ "foreignKey": "workCenterFk"
+ }
+ },
+ "scope": {
+ "include":{
+ "relation": "workCenter"
+ }
+ }
+}
diff --git a/back/models/collection.json b/back/models/collection.json
index 3e428ef609..cb8dc3d7cd 100644
--- a/back/models/collection.json
+++ b/back/models/collection.json
@@ -1,6 +1,11 @@
{
"name": "Collection",
"base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "collection"
+ }
+ },
"acls": [{
"property": "validations",
"accessType": "EXECUTE",
@@ -9,4 +14,3 @@
"permission": "ALLOW"
}]
}
-
\ No newline at end of file
diff --git a/back/models/reference-rate.json b/back/models/reference-rate.json
new file mode 100644
index 0000000000..fe732f3ef4
--- /dev/null
+++ b/back/models/reference-rate.json
@@ -0,0 +1,36 @@
+{
+ "name": "ReferenceRate",
+ "base": "PersistedModel",
+ "options": {
+ "mysql": {
+ "table": "referenceRate"
+ }
+ },
+ "properties": {
+ "id": {
+ "type": "number",
+ "id": true,
+ "description": "Identifier"
+ },
+ "currencyFk": {
+ "type": "number",
+ "required": true
+ },
+ "dated": {
+ "type": "date",
+ "required": true
+ },
+ "value": {
+ "type": "number",
+ "required": true
+ }
+ },
+ "acls": [
+ {
+ "accessType": "READ",
+ "principalType": "ROLE",
+ "principalId": "$everyone",
+ "permission": "ALLOW"
+ }
+ ]
+}
diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql
index ff58af2e24..4b106aec58 100644
--- a/db/dump/fixtures.before.sql
+++ b/db/dump/fixtures.before.sql
@@ -160,7 +160,8 @@ INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`)
(1, 'EUR', 'Euro', 1),
(2, 'USD', 'Dollar USA', 1.4),
(3, 'GBP', 'Libra', 1),
- (4, 'JPY', 'Yen Japones', 1);
+ (4, 'JPY', 'Yen Japones', 1),
+ (5, 'CNY', 'Yuan Chino', 1.2);
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`, `hasDailyInvoice`, `CEE`)
VALUES
@@ -3787,3 +3788,6 @@ INSERT INTO `vn`.`accountReconciliationConfig`(currencyFk, warehouseFk)
INSERT INTO vn.workerTeam(id, team, workerFk)
VALUES
(8, 1, 19);
+
+INSERT INTO vn.workCenter (id, name, payrollCenterFk, counter, warehouseFk, street, geoFk, deliveryManAdjustment)
+ VALUES(100, 'workCenterOne', 1, NULL, 1, 'gotham', NULL, NULL);
\ No newline at end of file
diff --git a/db/routines/vn/procedures/ticketCalculateClon.sql b/db/routines/vn/procedures/ticketCalculateClon.sql
index 7ded84f45c..a564915905 100644
--- a/db/routines/vn/procedures/ticketCalculateClon.sql
+++ b/db/routines/vn/procedures/ticketCalculateClon.sql
@@ -29,7 +29,7 @@ BEGIN
FROM sale
WHERE ticketFk = vTicketNew AND price > 0;
- CALL sale_recalcComponent('imbalance');
+ CALL sale_recalcComponent('buyerDiscount');
DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales;
diff --git a/db/routines/vn/procedures/workerTimeControl_clockIn.sql b/db/routines/vn/procedures/workerTimeControl_clockIn.sql
index e585284871..a1ce53bc2e 100644
--- a/db/routines/vn/procedures/workerTimeControl_clockIn.sql
+++ b/db/routines/vn/procedures/workerTimeControl_clockIn.sql
@@ -121,15 +121,17 @@ BEGIN
CALL util.throw(vErrorCode);
END IF;
+
-- DIRECCION CORRECTA
CALL workerTimeControl_direction(vWorkerFk, vTimed);
IF (SELECT
- IF(IF(option1 IN ('inMiddle', 'outMiddle'),
+ IF((IF(option1 IN ('inMiddle', 'outMiddle'),
'middle',
option1) <> vDirection
AND IF(option2 IN ('inMiddle', 'outMiddle'),
'middle',
- IFNULL(option2, '')) <> vDirection,
+ IFNULL(option2, '')) <> vDirection)
+ OR (option1 IS NULL AND option2 IS NULL),
TRUE ,
FALSE)
FROM tmp.workerTimeControlDirection
@@ -137,12 +139,17 @@ BEGIN
SET vIsError = TRUE;
END IF;
- DROP TEMPORARY TABLE tmp.workerTimeControlDirection;
+
IF vIsError THEN
SET vErrorCode = 'WRONG_DIRECTION';
+ IF(SELECT option1 IS NULL AND option2 IS NULL
+ FROM tmp.workerTimeControlDirection) THEN
+
+ SET vErrorCode = 'DAY_MAX_TIME';
+ END IF;
CALL util.throw(vErrorCode);
END IF;
-
+ DROP TEMPORARY TABLE tmp.workerTimeControlDirection;
-- FICHADAS IMPARES
SELECT timed INTO vLastIn
FROM workerTimeControl
diff --git a/db/routines/vn/triggers/agency_beforeInsert.sql b/db/routines/vn/triggers/agency_beforeInsert.sql
new file mode 100644
index 0000000000..8ff3958e16
--- /dev/null
+++ b/db/routines/vn/triggers/agency_beforeInsert.sql
@@ -0,0 +1,8 @@
+DELIMITER $$
+CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`agency_beforeInsert`
+ BEFORE INSERT ON `agency`
+ FOR EACH ROW
+BEGIN
+ SET NEW.editorFk = account.myUser_getId();
+END$$
+DELIMITER ;
diff --git a/db/versions/10992-goldenIvy/00-acl.sql b/db/versions/10992-goldenIvy/00-acl.sql
new file mode 100644
index 0000000000..1d1c3ce911
--- /dev/null
+++ b/db/versions/10992-goldenIvy/00-acl.sql
@@ -0,0 +1,2 @@
+INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
+ VALUES ('InvoiceIn', 'exchangeRateUpdate', '*', 'ALLOW', 'ROLE', 'employee');
diff --git a/db/versions/10992-goldenIvy/00-referenceRate.sql b/db/versions/10992-goldenIvy/00-referenceRate.sql
new file mode 100644
index 0000000000..db53f328f2
--- /dev/null
+++ b/db/versions/10992-goldenIvy/00-referenceRate.sql
@@ -0,0 +1,4 @@
+ALTER TABLE vn.referenceRate DROP INDEX `PRIMARY`;
+ALTER TABLE vn.referenceRate ADD id INT auto_increment PRIMARY KEY;
+ALTER TABLE vn.referenceRate CHANGE id id int(11) auto_increment NOT NULL FIRST;
+CREATE UNIQUE INDEX referenceRate_currencyFk_IDX USING BTREE ON vn.referenceRate (currencyFk,dated);
diff --git a/db/versions/10995-navyErica/01-agencyLogCreate.sql b/db/versions/10995-navyErica/01-agencyLogCreate.sql
new file mode 100644
index 0000000000..0b8a1ed878
--- /dev/null
+++ b/db/versions/10995-navyErica/01-agencyLogCreate.sql
@@ -0,0 +1,24 @@
+-- vn.agencyLog definition
+ALTER TABLE vn.agency ADD IF NOT EXISTS editorFk int(10) unsigned DEFAULT NULL NULL;
+
+ALTER TABLE vn.agency ADD CONSTRAINT agency_user_FK FOREIGN KEY (editorFk) REFERENCES `account`.`user`(id);
+
+CREATE TABLE IF NOT EXISTS `vn`.`agencyLog` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `originFk` smallint(5) unsigned DEFAULT NULL,
+ `userFk` int(10) unsigned DEFAULT NULL,
+ `action` set('insert','update','delete','select') NOT NULL,
+ `creationDate` timestamp NULL DEFAULT current_timestamp(),
+ `description` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
+ `changedModel` enum('agency','agencyMode') NOT NULL DEFAULT 'agency',
+ `oldInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`oldInstance`)),
+ `newInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`newInstance`)),
+ `changedModelId` int(11) NOT NULL,
+ `changedModelValue` varchar(45) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `logAgencyUserFk` (`userFk`),
+ KEY `agencyLog_changedModel` (`changedModel`,`changedModelId`,`creationDate`),
+ KEY `agencyLog_originFk` (`originFk`,`creationDate`),
+ CONSTRAINT `agencyOriginFk` FOREIGN KEY (`originFk`) REFERENCES `agency` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `agencyUserFk` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
\ No newline at end of file
diff --git a/db/versions/10995-navyErica/02-agencyWorkCenterCreate.sql b/db/versions/10995-navyErica/02-agencyWorkCenterCreate.sql
new file mode 100644
index 0000000000..179fbc63c9
--- /dev/null
+++ b/db/versions/10995-navyErica/02-agencyWorkCenterCreate.sql
@@ -0,0 +1,18 @@
+CREATE TABLE IF NOT EXISTS `vn`.`agencyWorkCenter` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `agencyFk` smallint(5) unsigned NOT NULL,
+ `workCenterFk` int(11) NOT NULL,
+ `editorFk` int(10) unsigned DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `agencyWorkCenter_unique` (`agencyFk`,`workCenterFk`),
+ KEY `agencyWorkCenter_workCenter_FK` (`workCenterFk`),
+ KEY `agencyWorkCenter_user_FK` (`editorFk`),
+ CONSTRAINT `agencyWorkCenter_agency_FK` FOREIGN KEY (`agencyFk`) REFERENCES `agency` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `agencyWorkCenter_user_FK` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `agencyWorkCenter_workCenter_FK` FOREIGN KEY (`workCenterFk`) REFERENCES `workCenter` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='refs #4988';
+
+INSERT INTO vn.agencyWorkCenter (agencyFk, workCenterFk)
+ SELECT id, workCenterFk
+ FROM vn.agency
+ WHERE workCenterFk IS NOT NULL;
diff --git a/db/versions/10995-navyErica/03-tableAcl.sql b/db/versions/10995-navyErica/03-tableAcl.sql
new file mode 100644
index 0000000000..f3fc4d3369
--- /dev/null
+++ b/db/versions/10995-navyErica/03-tableAcl.sql
@@ -0,0 +1,19 @@
+-- Place your SQL code here
+INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
+ VALUES ('AgencyLog','*','READ','ALLOW','ROLE','employee');
+
+INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
+ VALUES ('AgencyWorkCenter','*','READ','ALLOW','ROLE','employee');
+
+INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
+ VALUES('AgencyMode', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
+
+INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
+ VALUES('Agency', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
+
+INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
+ VALUES ('Agency','*','WRITE','ALLOW','ROLE','deliveryAssistant');
+
+INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
+ VALUES ('AgencyWorkCenter','*','WRITE','ALLOW','ROLE','deliveryAssistant');
+
diff --git a/db/versions/11007-greenRose/00-firstScript.sql b/db/versions/11007-greenRose/00-firstScript.sql
index 69959f0b40..154a75532a 100644
--- a/db/versions/11007-greenRose/00-firstScript.sql
+++ b/db/versions/11007-greenRose/00-firstScript.sql
@@ -1,4 +1,3 @@
-
CREATE OR REPLACE TABLE `vn`.`farmingDeliveryNote` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`farmingFk` int(10) unsigned NOT NULL,
@@ -10,3 +9,8 @@ CREATE OR REPLACE TABLE `vn`.`farmingDeliveryNote` (
CONSTRAINT `farmingDeliveryNoteFk_FK` FOREIGN KEY (`deliveryNoteFk`) REFERENCES `deliveryNote` (`id`),
CONSTRAINT `farmingDeliveryNoteFk_FK_1` FOREIGN KEY (`farmingFk`) REFERENCES `farming` (`id`)
);
+
+INSERT IGNORE INTO `vn`.`farmingDeliveryNote` (farmingFk, deliveryNoteFk, amount)
+ SELECT farmingFk, id, amount
+ FROM vn.deliveryNote dn
+ WHERE farmingFk;
\ No newline at end of file
diff --git a/db/versions/11014-orangePalmetto/00-firstScript.sql b/db/versions/11014-orangePalmetto/00-firstScript.sql
new file mode 100644
index 0000000000..fe85c7ec68
--- /dev/null
+++ b/db/versions/11014-orangePalmetto/00-firstScript.sql
@@ -0,0 +1,2 @@
+-- Place your SQL code here
+ALTER TABLE vn.claimBeginning MODIFY COLUMN quantity double DEFAULT 0 NULL;
diff --git a/e2e/paths/09-invoice-out/03_manualInvoice.spec.js b/e2e/paths/09-invoice-out/03_manualInvoice.spec.js
index dfaa55ef93..a1856f1b1b 100644
--- a/e2e/paths/09-invoice-out/03_manualInvoice.spec.js
+++ b/e2e/paths/09-invoice-out/03_manualInvoice.spec.js
@@ -40,7 +40,7 @@ describe('InvoiceOut manual invoice path', () => {
await page.waitToClick(selectors.invoiceOutIndex.createInvoice);
await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm);
- await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceClient, 'Max Eisenhardt');
+ await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceClient, 'Petter Parker');
await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceSerial, 'Global nacional');
await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceTaxArea, 'national');
await page.waitToClick(selectors.invoiceOutIndex.saveInvoice);
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index d7f9564fe4..d7e41233ee 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -353,5 +353,8 @@
"This password can only be changed by the user themselves": "Esta contraseña solo puede ser modificada por el propio usuario",
"They're not your subordinate": "No es tu subordinado/a.",
"No results found": "No se han encontrado resultados",
- "InvoiceIn is already booked": "La factura recibida está contabilizada"
-}
\ No newline at end of file
+ "InvoiceIn is already booked": "La factura recibida está contabilizada",
+ "This workCenter is already assigned to this agency": "Este centro de trabajo ya está asignado a esta agencia",
+ "Select ticket or client": "Elija un ticket o un client",
+ "It was not able to create the invoice": "No se pudo crear la factura"
+}
diff --git a/modules/claim/back/methods/claim/createFromSales.js b/modules/claim/back/methods/claim/createFromSales.js
index 30093e43d8..1af479dbb5 100644
--- a/modules/claim/back/methods/claim/createFromSales.js
+++ b/modules/claim/back/methods/claim/createFromSales.js
@@ -83,7 +83,6 @@ module.exports = Self => {
const newClaimBeginning = models.ClaimBeginning.create({
saleFk: sale.id,
claimFk: newClaim.id,
- quantity: sale.quantity
}, myOptions);
promises.push(newClaimBeginning);
diff --git a/modules/claim/back/methods/claim/specs/createFromSales.spec.js b/modules/claim/back/methods/claim/specs/createFromSales.spec.js
index fe009c1c3e..25414d1db7 100644
--- a/modules/claim/back/methods/claim/specs/createFromSales.spec.js
+++ b/modules/claim/back/methods/claim/specs/createFromSales.spec.js
@@ -37,7 +37,7 @@ describe('Claim createFromSales()', () => {
let claimBeginning = await models.ClaimBeginning.findOne({where: {claimFk: claim.id}}, options);
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
- expect(claimBeginning.quantity).toEqual(newSale[0].quantity);
+ expect(claimBeginning.quantity).toEqual(0);
await tx.rollback();
} catch (e) {
@@ -67,7 +67,7 @@ describe('Claim createFromSales()', () => {
const claimBeginning = await models.ClaimBeginning.findOne({where: {claimFk: claim.id}}, options);
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
- expect(claimBeginning.quantity).toEqual(newSale[0].quantity);
+ expect(claimBeginning.quantity).toEqual(0);
await tx.rollback();
} catch (e) {
diff --git a/modules/claim/back/models/claim-beginning.json b/modules/claim/back/models/claim-beginning.json
index d224586da4..ba6e838081 100644
--- a/modules/claim/back/models/claim-beginning.json
+++ b/modules/claim/back/models/claim-beginning.json
@@ -16,8 +16,7 @@
"description": "Identifier"
},
"quantity": {
- "type": "number",
- "required": true
+ "type": "number"
}
},
"relations": {
diff --git a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js
new file mode 100644
index 0000000000..3ad06b242b
--- /dev/null
+++ b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js
@@ -0,0 +1,64 @@
+const axios = require('axios');
+const {DOMParser} = require('xmldom');
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+ Self.remoteMethod('exchangeRateUpdate', {
+ description: 'Updates the exchange rates from an XML feed',
+ accessType: 'WRITE',
+ accepts: [],
+ http: {
+ path: '/exchangeRateUpdate',
+ verb: 'post'
+ }
+ });
+
+ Self.exchangeRateUpdate = async() => {
+ const response = await axios.get('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml');
+ const xmlData = response.data;
+
+ const doc = new DOMParser({errorHandler: {warning: () => {}}})?.parseFromString(xmlData, 'text/xml');
+ const cubes = doc?.getElementsByTagName('Cube');
+ if (!cubes || cubes.length === 0)
+ throw new UserError('No cubes found. Exiting the method.');
+
+ const models = Self.app.models;
+
+ const maxDateRecord = await models.ReferenceRate.findOne({order: 'dated DESC'});
+
+ const maxDate = maxDateRecord?.dated ? new Date(maxDateRecord.dated) : null;
+
+ for (const cube of Array.from(cubes)) {
+ if (cube.nodeType === doc.ELEMENT_NODE && cube.attributes.getNamedItem('time')) {
+ const xmlDate = new Date(cube.getAttribute('time'));
+ const xmlDateWithoutTime = new Date(xmlDate.getFullYear(), xmlDate.getMonth(), xmlDate.getDate());
+ if (!maxDate || maxDate < xmlDateWithoutTime) {
+ for (const rateCube of Array.from(cube.childNodes)) {
+ if (rateCube.nodeType === doc.ELEMENT_NODE) {
+ const currencyCode = rateCube.getAttribute('currency');
+ const rate = rateCube.getAttribute('rate');
+ if (['USD', 'CNY', 'GBP'].includes(currencyCode)) {
+ const currency = await models.Currency.findOne({where: {code: currencyCode}});
+ if (!currency) throw new UserError(`Currency not found for code: ${currencyCode}`);
+ const existingRate = await models.ReferenceRate.findOne({
+ where: {currencyFk: currency.id, dated: xmlDate}
+ });
+
+ if (existingRate) {
+ if (existingRate.value !== rate)
+ await existingRate.updateAttributes({value: rate});
+ } else {
+ await models.ReferenceRate.create({
+ currencyFk: currency.id,
+ dated: xmlDate,
+ value: rate
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+};
diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js
new file mode 100644
index 0000000000..0fd7ea165d
--- /dev/null
+++ b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js
@@ -0,0 +1,52 @@
+describe('exchangeRateUpdate functionality', function() {
+ const axios = require('axios');
+ const models = require('vn-loopback/server/server').models;
+
+ beforeEach(function() {
+ spyOn(axios, 'get').and.returnValue(Promise.resolve({
+ data: `
{{$t('total')}} | +{{total.price | currency('EUR', $i18n.locale)}} | ++ |