From 6605e5ae4cbbde79e568544b710b8b1730765b25 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 2 Dec 2020 12:05:47 +0100 Subject: [PATCH 01/18] zoneLog --- db/changes/10260-december/00-zoneLog.sql | 18 ++++++ modules/zone/back/model-config.json | 3 + modules/zone/back/models/zone-log.json | 58 ++++++++++++++++++++ modules/zone/back/models/zone-warehouse.json | 6 +- modules/zone/back/models/zone.json | 6 +- modules/zone/front/index.js | 1 + modules/zone/front/log/index.html | 1 + modules/zone/front/log/index.js | 7 +++ modules/zone/front/routes.json | 6 ++ 9 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 db/changes/10260-december/00-zoneLog.sql create mode 100644 modules/zone/back/models/zone-log.json create mode 100644 modules/zone/front/log/index.html create mode 100644 modules/zone/front/log/index.js diff --git a/db/changes/10260-december/00-zoneLog.sql b/db/changes/10260-december/00-zoneLog.sql new file mode 100644 index 000000000..13d81bc92 --- /dev/null +++ b/db/changes/10260-december/00-zoneLog.sql @@ -0,0 +1,18 @@ +CREATE TABLE `vn`.`zoneLog` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `originFk` int(10) NOT NULL, + `userFk` int(10) unsigned DEFAULT NULL, + `action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL, + `creationDate` timestamp NULL DEFAULT current_timestamp(), + `description` text CHARACTER SET utf8 DEFAULT NULL, + `changedModel` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL, + `oldInstance` text COLLATE utf8_unicode_ci DEFAULT NULL, + `newInstance` text COLLATE utf8_unicode_ci DEFAULT NULL, + `changedModelId` int(11) DEFAULT NULL, + `changedModelValue` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `originFk` (`originFk`), + KEY `userFk` (`userFk`), + CONSTRAINT `zoneLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `vn`.`zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `zoneLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; \ No newline at end of file diff --git a/modules/zone/back/model-config.json b/modules/zone/back/model-config.json index f353be088..05da8b2c3 100644 --- a/modules/zone/back/model-config.json +++ b/modules/zone/back/model-config.json @@ -31,5 +31,8 @@ }, "ZoneEstimatedDelivery": { "dataSource": "vn" + }, + "ZoneLog": { + "dataSource": "vn" } } diff --git a/modules/zone/back/models/zone-log.json b/modules/zone/back/models/zone-log.json new file mode 100644 index 000000000..ddca9261b --- /dev/null +++ b/modules/zone/back/models/zone-log.json @@ -0,0 +1,58 @@ +{ + "name": "ZoneLog", + "base": "VnModel", + "options": { + "mysql": { + "table": "zoneLog" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "forceId": false + }, + "originFk": { + "type": "Number", + "required": true + }, + "userFk": { + "type": "Number" + }, + "action": { + "type": "String", + "required": true + }, + "changedModel": { + "type": "String" + }, + "oldInstance": { + "type": "Object" + }, + "newInstance": { + "type": "Object" + }, + "creationDate": { + "type": "Date" + }, + "changedModelId": { + "type": "String" + }, + "changedModelValue": { + "type": "String" + }, + "description": { + "type": "String" + } + }, + "relations": { + "user": { + "type": "belongsTo", + "model": "Account", + "foreignKey": "userFk" + } + }, + "scope": { + "order": ["creationDate DESC", "id DESC"] + } +} diff --git a/modules/zone/back/models/zone-warehouse.json b/modules/zone/back/models/zone-warehouse.json index 14c4e84a4..0f0e43f4a 100644 --- a/modules/zone/back/models/zone-warehouse.json +++ b/modules/zone/back/models/zone-warehouse.json @@ -1,6 +1,10 @@ { "name": "ZoneWarehouse", - "base": "VnModel", + "base": "Loggable", + "log": { + "model":"ZoneLog", + "relation": "zone" + }, "options": { "mysql": { "table": "zoneWarehouse" diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json index e94146946..1d1ccfd90 100644 --- a/modules/zone/back/models/zone.json +++ b/modules/zone/back/models/zone.json @@ -1,6 +1,10 @@ { "name": "Zone", - "base": "VnModel", + "base": "Loggable", + "log": { + "model":"ZoneLog", + "showField": "name" + }, "options": { "mysql": { "table": "zone" diff --git a/modules/zone/front/index.js b/modules/zone/front/index.js index 26c491709..dc20eea47 100644 --- a/modules/zone/front/index.js +++ b/modules/zone/front/index.js @@ -16,3 +16,4 @@ import './calendar'; import './location'; import './calendar'; import './upcoming-deliveries'; +import './log'; diff --git a/modules/zone/front/log/index.html b/modules/zone/front/log/index.html new file mode 100644 index 000000000..539afda82 --- /dev/null +++ b/modules/zone/front/log/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/zone/front/log/index.js b/modules/zone/front/log/index.js new file mode 100644 index 000000000..8c3be2423 --- /dev/null +++ b/modules/zone/front/log/index.js @@ -0,0 +1,7 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +ngModule.vnComponent('vnZoneLog', { + template: require('./index.html'), + controller: Section, +}); diff --git a/modules/zone/front/routes.json b/modules/zone/front/routes.json index 6c799dcc8..0134c3b78 100644 --- a/modules/zone/front/routes.json +++ b/modules/zone/front/routes.json @@ -14,6 +14,7 @@ {"state": "zone.card.basicData", "icon": "settings"}, {"state": "zone.card.location", "icon": "my_location"}, {"state": "zone.card.warehouses", "icon": "home"}, + {"state": "zone.card.log", "icon": "history"}, {"state": "zone.card.events", "icon": "today"} ] }, @@ -84,6 +85,11 @@ "params": { "zone": "$ctrl.zone" } + }, { + "url" : "/log", + "state": "zone.card.log", + "component": "vn-zone-log", + "description": "Log" } ] } \ No newline at end of file From 6eeecc553ba9fc301104dfa213a14946a419d6d9 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 2 Dec 2020 12:49:50 +0100 Subject: [PATCH 02/18] zoneLog calendar --- modules/zone/back/models/zone-event.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/zone/back/models/zone-event.json b/modules/zone/back/models/zone-event.json index 9ac1007b5..54c9c4a7d 100644 --- a/modules/zone/back/models/zone-event.json +++ b/modules/zone/back/models/zone-event.json @@ -1,6 +1,10 @@ { "name": "ZoneEvent", - "base": "VnModel", + "base": "Loggable", + "log": { + "model":"ZoneLog", + "relation": "zone" + }, "options": { "mysql": { "table": "zoneEvent" From 6416b0ad799f9abad1cc03e62ae8423bf6ce231c Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 22 Dec 2020 14:56:21 +0100 Subject: [PATCH 03/18] 2666 - Closure invalid email notification --- .../components/descriptor-popover/index.js | 2 ++ .../ticket/front/tracking/index/index.html | 4 +-- modules/worker/front/log/index.html | 8 ++--- modules/worker/front/log/locale/es.yml | 3 +- print/methods/closure.js | 34 +++++++++++++++++++ 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/front/salix/components/descriptor-popover/index.js b/front/salix/components/descriptor-popover/index.js index b746f5c81..3ec5be1ae 100644 --- a/front/salix/components/descriptor-popover/index.js +++ b/front/salix/components/descriptor-popover/index.js @@ -4,6 +4,8 @@ import './style.scss'; export default class DescriptorPopover extends Popover { show(parent, id) { + if (!id) return; + super.show(parent); this.id = id; diff --git a/modules/ticket/front/tracking/index/index.html b/modules/ticket/front/tracking/index/index.html index 42d2197d0..7cb9431ab 100644 --- a/modules/ticket/front/tracking/index/index.html +++ b/modules/ticket/front/tracking/index/index.html @@ -23,9 +23,9 @@ {{::tracking.state.name}} - {{::tracking.worker.user.name | dashIfEmpty}} + {{::tracking.worker.user.name || 'System' | translate}} {{::tracking.created | date:'dd/MM/yyyy HH:mm'}} diff --git a/modules/worker/front/log/index.html b/modules/worker/front/log/index.html index bfa60a8c3..b7cf9fc77 100644 --- a/modules/worker/front/log/index.html +++ b/modules/worker/front/log/index.html @@ -33,7 +33,7 @@ {{::log.user.name | dashIfEmpty}} + translate>{{::log.user.name || 'System' | translate}}
@@ -54,7 +54,7 @@ {{::log.user.name | dashIfEmpty}} + translate>{{::log.user.name || 'System' | translate}} @@ -70,7 +70,7 @@
{{::old.key}}: - {{::old.value}} + {{::old.value | dashIfEmpty}}
@@ -81,7 +81,7 @@ id="newInstance">
{{::new.key}}: - {{::new.value}} + {{::new.value | dashIfEmpty}}
{ SELECT t.id, t.clientFk, + c.name clientName, c.email recipient, c.salesPersonFk, c.isToBeMailed, @@ -196,6 +197,10 @@ module.exports = app => { const email = new Email('delivery-note-link', args); await email.send(); } catch (error) { + // Domain not found + if (error.responseCode == 450) + return invalidEmail(ticket); + // Save tickets on a list of failed ids failedtickets.push({ id: ticket.id, @@ -220,4 +225,33 @@ module.exports = app => { }); } } + + async function invalidEmail(ticket) { + await db.rawSql(`UPDATE client SET email = NULL WHERE id = :clientId`, { + clientId: ticket.clientFk + }); + + const oldInstance = `{"email": "${ticket.recipient}"}`; + const newInstance = `{"email": ""}`; + await db.rawSql(` + INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance) + VALUES (:clientId, :userId, 'UPDATE', 'Client', :oldInstance, :newInstance)`, { + clientId: ticket.clientFk, + userId: null, + oldInstance: oldInstance, + newInstance: newInstance + }); + + const body = `No se ha podido enviar el albarán ${ticket.id} + al cliente ${ticket.clientFk} - ${ticket.clientName} + porque la dirección de email "${ticket.recipient}" no es correcta o no está disponible.

+ Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente. + Actualiza la dirección de email con una correcta.`; + + smtp.send({ + to: ticket.salesPersonEmail, + subject: 'No se ha podido enviar el albarán', + html: body + }); + } }; From a19064cb1b6088c491630caced5428081865ceec Mon Sep 17 00:00:00 2001 From: Jorge Padawan Date: Wed, 23 Dec 2020 12:23:37 +0100 Subject: [PATCH 04/18] Nueva tabla entryObservation y he juntado la consulta de 1260-navidad con 1260-holydays --- db/changes/10260-holidays/00-ACL.sql | 3 ++- db/changes/10260-holidays/00-entryObservation.sql | 11 +++++++++++ db/changes/10260-navidad/00-acl.sql | 2 -- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 db/changes/10260-holidays/00-entryObservation.sql delete mode 100644 db/changes/10260-navidad/00-acl.sql diff --git a/db/changes/10260-holidays/00-ACL.sql b/db/changes/10260-holidays/00-ACL.sql index 1f8045bc7..e72e6fa73 100644 --- a/db/changes/10260-holidays/00-ACL.sql +++ b/db/changes/10260-holidays/00-ACL.sql @@ -1 +1,2 @@ -INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) VALUES ('Image', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee') \ No newline at end of file +INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) VALUES ('Image', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('PayDem', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); \ No newline at end of file diff --git a/db/changes/10260-holidays/00-entryObservation.sql b/db/changes/10260-holidays/00-entryObservation.sql new file mode 100644 index 000000000..f72d64b01 --- /dev/null +++ b/db/changes/10260-holidays/00-entryObservation.sql @@ -0,0 +1,11 @@ +CREATE TABLE `vn`.`entryObservation` ( + id int NOT NULL AUTO_INCREMENT, + entryFk int NOT NULL, + observationTypeFk TINYINT(3) UNSIGNED, + description TEXT, + PRIMARY KEY (id), + CONSTRAINT entry_id_entryFk + FOREIGN KEY (entryFk) REFERENCES entry(id), + CONSTRAINT observationType_id_observationTypeFk + FOREIGN KEY (observationTypeFk) REFERENCES observationType(id) +); \ No newline at end of file diff --git a/db/changes/10260-navidad/00-acl.sql b/db/changes/10260-navidad/00-acl.sql deleted file mode 100644 index 9fba4786b..000000000 --- a/db/changes/10260-navidad/00-acl.sql +++ /dev/null @@ -1,2 +0,0 @@ - INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) - VALUES ('PayDem', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); From 2948747da3497c2f016b74481f84852bc9390243 Mon Sep 17 00:00:00 2001 From: Jorge Padawan Date: Wed, 23 Dec 2020 12:25:12 +0100 Subject: [PATCH 05/18] Seccion nueva, "Note" mas campo entryObservation --- modules/entry/back/model-config.json | 3 + .../entry/back/models/entry-observation.js | 9 +++ .../entry/back/models/entry-observation.json | 38 ++++++++++ modules/entry/front/index.js | 1 + modules/entry/front/note/index.html | 72 +++++++++++++++++++ modules/entry/front/note/index.js | 20 ++++++ modules/entry/front/routes.json | 11 ++- 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 modules/entry/back/models/entry-observation.js create mode 100644 modules/entry/back/models/entry-observation.json create mode 100644 modules/entry/front/note/index.html create mode 100644 modules/entry/front/note/index.js diff --git a/modules/entry/back/model-config.json b/modules/entry/back/model-config.json index 0e37b947f..eddef9c41 100644 --- a/modules/entry/back/model-config.json +++ b/modules/entry/back/model-config.json @@ -7,5 +7,8 @@ }, "EntryLog": { "dataSource": "vn" + }, + "EntryObservation": { + "dataSource": "vn" } } diff --git a/modules/entry/back/models/entry-observation.js b/modules/entry/back/models/entry-observation.js new file mode 100644 index 000000000..77d15d85c --- /dev/null +++ b/modules/entry/back/models/entry-observation.js @@ -0,0 +1,9 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`The observation type can't be repeated`); + return err; + }); +}; diff --git a/modules/entry/back/models/entry-observation.json b/modules/entry/back/models/entry-observation.json new file mode 100644 index 000000000..87d3fd964 --- /dev/null +++ b/modules/entry/back/models/entry-observation.json @@ -0,0 +1,38 @@ +{ + "name": "EntryObservation", + "base": "Loggable", + "log": { + "model": "EntryLog", + "relation": "entry" + }, + "options": { + "mysql": { + "table": "entryObservation" + } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "description": "Identifier" + }, + "description": { + "type": "String", + "required": true + } + }, + "relations": { + "entry": { + "type": "belongsTo", + "model": "Entry", + "foreignKey": "entryFk", + "required": true + }, + "observationType": { + "type": "belongsTo", + "model": "ObservationType", + "foreignKey": "observationTypeFk", + "required": true + } + } +} diff --git a/modules/entry/front/index.js b/modules/entry/front/index.js index e92f23fc1..14aecc8db 100644 --- a/modules/entry/front/index.js +++ b/modules/entry/front/index.js @@ -10,6 +10,7 @@ import './latest-buys-search-panel'; import './descriptor'; import './descriptor-popover'; import './card'; +import './note'; import './summary'; import './log'; import './buy'; diff --git a/modules/entry/front/note/index.html b/modules/entry/front/note/index.html new file mode 100644 index 000000000..5f3c7f77e --- /dev/null +++ b/modules/entry/front/note/index.html @@ -0,0 +1,72 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/modules/entry/front/note/index.js b/modules/entry/front/note/index.js new file mode 100644 index 000000000..fccd60913 --- /dev/null +++ b/modules/entry/front/note/index.js @@ -0,0 +1,20 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + onSubmit() { + this.$.watcher.check(); + this.$.model.save().then(() => { + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + }); + } +} + +ngModule.vnComponent('vnEntryObservation', { + template: require('./index.html'), + controller: Controller, + bindings: { + entry: '<' + } +}); diff --git a/modules/entry/front/routes.json b/modules/entry/front/routes.json index a430a95fa..010e738b3 100644 --- a/modules/entry/front/routes.json +++ b/modules/entry/front/routes.json @@ -12,6 +12,7 @@ "card": [ {"state": "entry.card.basicData", "icon": "settings"}, {"state": "entry.card.buy", "icon": "icon-lines"}, + {"state": "entry.card.observation", "icon": "insert_drive_file"}, {"state": "entry.card.log", "icon": "history"} ] }, @@ -61,7 +62,15 @@ "params": { "entry": "$ctrl.entry" } - }, { + },{ + "url": "/observation", + "state": "entry.card.observation", + "component": "vn-entry-observation", + "description": "Notes", + "params": { + "entry": "$ctrl.entry" + } + },{ "url" : "/log", "state": "entry.card.log", "component": "vn-entry-log", From a21476e3df80bf6f136df3807280c786d44ad6e0 Mon Sep 17 00:00:00 2001 From: bernat Date: Wed, 23 Dec 2020 12:42:41 +0100 Subject: [PATCH 06/18] fix searchbar index --- db/dump/fixtures.sql | 2 +- e2e/paths/02-client/15_user_config.spec.js | 2 +- modules/route/front/main/index.html | 5 ++--- modules/route/front/main/index.js | 3 ++- modules/ticket/front/main/index.html | 2 +- modules/ticket/front/main/index.js | 2 +- modules/travel/front/main/index.html | 3 ++- modules/travel/front/main/index.js | 8 ++++++++ 8 files changed, 18 insertions(+), 9 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 4ad5321b0..aa15b774f 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1638,7 +1638,7 @@ INSERT INTO `vn`.`orderTicket`(`orderFk`, `ticketFk`) INSERT INTO `vn`.`userConfig` (`userFk`, `warehouseFk`, `companyFk`) VALUES - (1, 2, 69), + (1, 1, 69), (5, 1, 442), (9, 1, 442), (18, 3, 567); diff --git a/e2e/paths/02-client/15_user_config.spec.js b/e2e/paths/02-client/15_user_config.spec.js index 0e18c07ad..2954ff522 100644 --- a/e2e/paths/02-client/15_user_config.spec.js +++ b/e2e/paths/02-client/15_user_config.spec.js @@ -71,7 +71,7 @@ describe('User config', () => { expect(expectedLocalWarehouse).toBeTruthy(); expect(expectedLocalBank).toBeTruthy(); expect(expectedLocalCompany).toBeTruthy(); - expect(userWarehouse).toEqual('Warehouse Two'); + expect(userWarehouse).toEqual('Warehouse One'); expect(userCompany).toEqual('CCs'); }); diff --git a/modules/route/front/main/index.html b/modules/route/front/main/index.html index f0de3f09b..16243be03 100644 --- a/modules/route/front/main/index.html +++ b/modules/route/front/main/index.html @@ -2,15 +2,14 @@ vn-id="model" url="Routes/filter" limit="20" - order="created DESC" - auto-load="true"> + order="created DESC"> diff --git a/modules/route/front/main/index.js b/modules/route/front/main/index.js index 8aa6552e1..a6d5bedd1 100644 --- a/modules/route/front/main/index.js +++ b/modules/route/front/main/index.js @@ -10,7 +10,8 @@ export default class Route extends ModuleMain { let from = new Date(); from.setHours(0, 0, 0, 0); - this.filter = {from, to, warehouseFk: this.vnConfig.warehouseFk}; + this.filterParams = {from, to, warehouseFk: this.vnConfig.warehouseFk}; + this.$.model.applyFilter(null, this.filterParams); } } diff --git a/modules/ticket/front/main/index.html b/modules/ticket/front/main/index.html index 7ea5c86e6..953dc8a6b 100644 --- a/modules/ticket/front/main/index.html +++ b/modules/ticket/front/main/index.html @@ -11,7 +11,7 @@ info="Search ticket by id or alias" model="model" fetch-params="$ctrl.fetchParams($params)" - suggested-filter="$ctrl.defaultFilter"> + suggested-filter="$ctrl.filterParams"> diff --git a/modules/ticket/front/main/index.js b/modules/ticket/front/main/index.js index 9bbedbcc9..78334ba97 100644 --- a/modules/ticket/front/main/index.js +++ b/modules/ticket/front/main/index.js @@ -5,7 +5,7 @@ export default class Ticket extends ModuleMain { constructor() { super(); - this.defaultFilter = { + this.filterParams = { scopeDays: 1 }; } diff --git a/modules/travel/front/main/index.html b/modules/travel/front/main/index.html index 56167c6fc..feb1e8b01 100644 --- a/modules/travel/front/main/index.html +++ b/modules/travel/front/main/index.html @@ -10,7 +10,8 @@ panel="vn-travel-search-panel" info="Search travels by id" model="model" - fetch-params="$ctrl.fetchParams($params)"> + fetch-params="$ctrl.fetchParams($params)" + suggested-filter="$ctrl.filterParams"> diff --git a/modules/travel/front/main/index.js b/modules/travel/front/main/index.js index f04cc750d..d6f103033 100644 --- a/modules/travel/front/main/index.js +++ b/modules/travel/front/main/index.js @@ -2,6 +2,14 @@ import ngModule from '../module'; import ModuleMain from 'salix/components/module-main'; export default class Travel extends ModuleMain { + constructor() { + super(); + + this.filterParams = { + scopeDays: 1 + }; + } + fetchParams($params) { if (!Object.entries($params).length) $params.scopeDays = 1; From 3517bdea415feb31b282ced953e66e90f94141ec Mon Sep 17 00:00:00 2001 From: Jorge Padawan Date: Wed, 23 Dec 2020 13:31:55 +0100 Subject: [PATCH 07/18] =?UTF-8?q?A=C3=B1adido=20a=20las=20foreignKeys=20el?= =?UTF-8?q?=20valor=20UNIQUE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/changes/10260-holidays/00-entryObservation.sql | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/db/changes/10260-holidays/00-entryObservation.sql b/db/changes/10260-holidays/00-entryObservation.sql index f72d64b01..6184cf3bd 100644 --- a/db/changes/10260-holidays/00-entryObservation.sql +++ b/db/changes/10260-holidays/00-entryObservation.sql @@ -8,4 +8,7 @@ CREATE TABLE `vn`.`entryObservation` ( FOREIGN KEY (entryFk) REFERENCES entry(id), CONSTRAINT observationType_id_observationTypeFk FOREIGN KEY (observationTypeFk) REFERENCES observationType(id) -); \ No newline at end of file +); + +ALTER TABLE `vn`.`entryObservation` +ADD UNIQUE INDEX `entryFk_observationTypeFk_UNIQUE` (`entryFk` ASC,`observationTypeFk` ASC); \ No newline at end of file From 259842c22de493210ffba283a7826ef5fd4a5bf8 Mon Sep 17 00:00:00 2001 From: Jorge Padawan Date: Wed, 23 Dec 2020 13:32:58 +0100 Subject: [PATCH 08/18] Retirado el parametro required por no utilizarse --- modules/entry/back/models/entry-observation.json | 3 +-- modules/ticket/back/models/ticket-observation.json | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/entry/back/models/entry-observation.json b/modules/entry/back/models/entry-observation.json index 87d3fd964..535735d83 100644 --- a/modules/entry/back/models/entry-observation.json +++ b/modules/entry/back/models/entry-observation.json @@ -25,8 +25,7 @@ "entry": { "type": "belongsTo", "model": "Entry", - "foreignKey": "entryFk", - "required": true + "foreignKey": "entryFk" }, "observationType": { "type": "belongsTo", diff --git a/modules/ticket/back/models/ticket-observation.json b/modules/ticket/back/models/ticket-observation.json index 51469c7a6..ba4f85ce8 100644 --- a/modules/ticket/back/models/ticket-observation.json +++ b/modules/ticket/back/models/ticket-observation.json @@ -25,8 +25,7 @@ "ticket": { "type": "belongsTo", "model": "Ticket", - "foreignKey": "ticketFk", - "required": true + "foreignKey": "ticketFk" }, "observationType": { "type": "belongsTo", From 8ede30398b1577814a2d292ceb5779c5c13baba5 Mon Sep 17 00:00:00 2001 From: carlosjr Date: Thu, 24 Dec 2020 11:31:20 +0100 Subject: [PATCH 09/18] clone feature for routes index --- modules/route/back/methods/route/clone.js | 56 +++++++++++++++++++ .../back/methods/route/specs/clone.spec.js | 31 ++++++++++ modules/route/back/models/route.js | 1 + modules/route/front/basic-data/locale/es.yml | 2 + modules/route/front/index/index.html | 36 ++++++++++-- modules/route/front/index/index.js | 16 ++++++ modules/route/front/index/index.spec.js | 10 ++++ modules/route/front/index/locale/es.yml | 5 +- 8 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 modules/route/back/methods/route/clone.js create mode 100644 modules/route/back/methods/route/specs/clone.spec.js diff --git a/modules/route/back/methods/route/clone.js b/modules/route/back/methods/route/clone.js new file mode 100644 index 000000000..ece232ccf --- /dev/null +++ b/modules/route/back/methods/route/clone.js @@ -0,0 +1,56 @@ +module.exports = Self => { + Self.remoteMethod('clone', { + description: 'Clones the selected routes', + accessType: 'WRITE', + accepts: [ + { + arg: 'ids', + type: ['number'], + required: true, + description: 'The routes ids to clone' + }, + { + arg: 'started', + type: 'date', + required: true, + description: 'The started date for all routes' + } + ], + returns: { + type: ['Object'], + root: true + }, + http: { + path: `/clone`, + verb: 'POST' + } + }); + + Self.clone = async(ids, started) => { + const tx = await Self.beginTransaction({}); + try { + const options = {transaction: tx}; + const originalRoutes = await Self.find({ + where: {id: {inq: ids}}, + fields: ['workerFk', 'agencyModeFk', 'vehicleFk', 'description'] + }, options); + + if (ids.length != originalRoutes.length) + throw new Error(`The amount of routes found don't match`); + + const routes = originalRoutes.map(route => { + route.started = started; + route.created = new Date(); + return route; + }); + + const clones = await Self.create(routes, options); + + await tx.commit(); + return clones; + } catch (e) { + await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/route/back/methods/route/specs/clone.spec.js b/modules/route/back/methods/route/specs/clone.spec.js new file mode 100644 index 000000000..c0f5f04f1 --- /dev/null +++ b/modules/route/back/methods/route/specs/clone.spec.js @@ -0,0 +1,31 @@ +const app = require('vn-loopback/server/server'); + +describe('route clone()', () => { + const startDate = new Date(); + it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => { + const ids = [996, 997, 998, 999]; + + let error; + + try { + await app.models.Route.clone(ids, startDate); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toEqual(`The amount of routes found don't match`); + }); + + it('should clone two routes', async() => { + const ids = [1, 2]; + + const clones = await app.models.Route.clone(ids, startDate); + + expect(clones.length).toEqual(2); + + // restores + for (const clone of clones) + await app.models.Route.destroyById(clone.id); + }); +}); diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 6320a888c..4423131bf 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -6,6 +6,7 @@ module.exports = Self => { require('../methods/route/updateVolume')(Self); require('../methods/route/getDeliveryPoint')(Self); require('../methods/route/insertTicket')(Self); + require('../methods/route/clone')(Self); Self.validate('kmStart', validateDistance, { message: 'Distance must be lesser than 1000' diff --git a/modules/route/front/basic-data/locale/es.yml b/modules/route/front/basic-data/locale/es.yml index f0414b5b1..a98f20215 100644 --- a/modules/route/front/basic-data/locale/es.yml +++ b/modules/route/front/basic-data/locale/es.yml @@ -3,3 +3,5 @@ Date started: Fecha inicio Km start: Km de inicio Km end: Km de fin Description: Descripción +Hour started: Hora inicio +Hour finished: Hora fin diff --git a/modules/route/front/index/index.html b/modules/route/front/index/index.html index d71bcbc48..7bbadefe4 100644 --- a/modules/route/front/index/index.html +++ b/modules/route/front/index/index.html @@ -44,7 +44,7 @@ {{::route.agencyName | dashIfEmpty}} {{::route.vehiclePlateNumber | dashIfEmpty}} - {{::route.created | date:'dd/MM/yyyy' | dashIfEmpty}} + {{::route.created | dashIfEmpty | date:'dd/MM/yyyy'}} {{::route.m3 | dashIfEmpty}} {{::route.description | dashIfEmpty}} @@ -59,19 +59,26 @@ + + - -
+ + - -
\ No newline at end of file +
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/route/front/index/index.js b/modules/route/front/index/index.js index 4400bdbb1..2dc767f4c 100644 --- a/modules/route/front/index/index.js +++ b/modules/route/front/index/index.js @@ -40,6 +40,22 @@ export default class Controller extends Section { }); } + openClonationDialog() { + this.startedDate = new Date(); + this.$.clonationDialog.show(); + } + + cloneSelectedRoutes() { + const routesIds = []; + for (let route of this.checked) + routesIds.push(route.id); + + return this.$http.post('Routes/clone', {ids: routesIds, started: this.startedDate}).then(() => { + this.$.model.refresh(); + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } + onDrop($event) { const target = $event.target; const droppable = target.closest(this.droppableElement); diff --git a/modules/route/front/index/index.spec.js b/modules/route/front/index/index.spec.js index b66ecaf00..8346f924c 100644 --- a/modules/route/front/index/index.spec.js +++ b/modules/route/front/index/index.spec.js @@ -60,6 +60,16 @@ describe('Component vnRouteIndex', () => { }); }); + describe('cloneSelectedRoutes()', () => { + it('should perform an http request to Routes/clone', () => { + controller.startedDate = new Date(); + + $httpBackend.expect('POST', 'Routes/clone').respond(); + controller.cloneSelectedRoutes(); + $httpBackend.flush(); + }); + }); + describe('onDrop()', () => { it('should call the insert method when dragging a ticket number', () => { jest.spyOn(controller, 'insert'); diff --git a/modules/route/front/index/locale/es.yml b/modules/route/front/index/locale/es.yml index 0c09b21ee..40cd5f2b5 100644 --- a/modules/route/front/index/locale/es.yml +++ b/modules/route/front/index/locale/es.yml @@ -1,2 +1,5 @@ Vehicle: Vehículo -Download selected routes as PDF: Descargar rutas seleccionadas como PDF \ No newline at end of file +Download selected routes as PDF: Descargar rutas seleccionadas como PDF +Clone selected routes: Clonar rutas seleccionadas +Select the starting date: Seleccione fecha de inicio +Starting date: Fecha de inicio \ No newline at end of file From 68f2976c2de94494b65e90e31205cd9ec2fdf97c Mon Sep 17 00:00:00 2001 From: carlosjr Date: Thu, 24 Dec 2020 13:15:14 +0100 Subject: [PATCH 10/18] e2e path updated for clonation --- e2e/helpers/selectors.js | 9 +++++++- ...te.spec.js => 03_create_and_clone.spec.js} | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) rename e2e/paths/08-route/{03_create.spec.js => 03_create_and_clone.spec.js} (68%) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 11087d2d4..0ed3607ad 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -674,7 +674,14 @@ export default { confirmButton: '.vn-confirm.shown button[response="accept"]', }, routeIndex: { - addNewRouteButton: 'vn-route-index a[ui-sref="route.create"]' + anyResult: 'vn-table a', + firstRouteCheckbox: 'a:nth-child(1) vn-td:nth-child(1) > vn-check', + addNewRouteButton: 'vn-route-index a[ui-sref="route.create"]', + cloneButton: 'vn-route-index button > vn-icon[icon="icon-clone"]', + submitClonationButton: 'tpl-buttons > button[response="accept"]', + openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]', + searchAgencyAutocomlete: 'vn-route-search-panel vn-autocomplete[ng-model="filter.agencyModeFk"]', + advancedSearchButton: 'vn-route-search-panel button[type=submit]', }, createRouteView: { worker: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.workerFk"]', diff --git a/e2e/paths/08-route/03_create.spec.js b/e2e/paths/08-route/03_create_and_clone.spec.js similarity index 68% rename from e2e/paths/08-route/03_create.spec.js rename to e2e/paths/08-route/03_create_and_clone.spec.js index 670f7e17b..f2de57a85 100644 --- a/e2e/paths/08-route/03_create.spec.js +++ b/e2e/paths/08-route/03_create_and_clone.spec.js @@ -57,5 +57,26 @@ describe('Route create path', () => { it(`should confirm the redirection to the created route summary`, async() => { await page.waitForState('route.card.summary'); }); + + it(`should navigate back to the route index`, async() => { + await page.waitToClick(selectors.globalItems.returnToModuleIndexButton); + await page.waitForState('route.index'); + }); + + it(`should clone the first route`, async() => { + await page.waitToClick(selectors.routeIndex.firstRouteCheckbox); + await page.waitToClick(selectors.routeIndex.cloneButton); + await page.waitToClick(selectors.routeIndex.submitClonationButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should search for the agency of the cloned routes and find two results`, async() => { + await page.waitToClick(selectors.routeIndex.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.routeIndex.searchAgencyAutocomlete, 'inhouse pickup'); + await page.waitToClick(selectors.routeIndex.advancedSearchButton); + await page.waitForNumberOfElements(selectors.routeIndex.anyResult, 2); + }); }); }); From 3f9446d94f4b81780630e2460f2121fc2d6a786c Mon Sep 17 00:00:00 2001 From: carlosjr Date: Thu, 24 Dec 2020 16:48:56 +0100 Subject: [PATCH 11/18] e2e path updated + extension refactor --- e2e/helpers/extensions.js | 11 ++++++++--- e2e/paths/08-route/03_create_and_clone.spec.js | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index b38b3f718..71f834476 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -300,9 +300,14 @@ let actions = { }, waitForNumberOfElements: async function(selector, count) { - return await this.waitForFunction((selector, count) => { - return document.querySelectorAll(selector).length == count; - }, {}, selector, count); + try { + await this.waitForFunction((selector, count) => { + return document.querySelectorAll(selector).length == count; + }, {}, selector, count); + } catch (error) { + const amount = await this.countElement(selector); + throw new Error(`actual amount of elements was: ${amount} instead of ${count}, ${error}`); + } }, waitForClassNotPresent: async function(selector, className) { diff --git a/e2e/paths/08-route/03_create_and_clone.spec.js b/e2e/paths/08-route/03_create_and_clone.spec.js index f2de57a85..c42bbdc55 100644 --- a/e2e/paths/08-route/03_create_and_clone.spec.js +++ b/e2e/paths/08-route/03_create_and_clone.spec.js @@ -63,6 +63,13 @@ describe('Route create path', () => { await page.waitForState('route.index'); }); + it(`should count the amount of routes before clonation`, async() => { + await page.waitForNumberOfElements(selectors.routeIndex.anyResult, 8); + const result = await page.countElement(selectors.routeIndex.anyResult); + + expect(result).toEqual(8); + }); + it(`should clone the first route`, async() => { await page.waitToClick(selectors.routeIndex.firstRouteCheckbox); await page.waitToClick(selectors.routeIndex.cloneButton); @@ -72,11 +79,11 @@ describe('Route create path', () => { expect(message.text).toContain('Data saved!'); }); - it(`should search for the agency of the cloned routes and find two results`, async() => { - await page.waitToClick(selectors.routeIndex.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.routeIndex.searchAgencyAutocomlete, 'inhouse pickup'); - await page.waitToClick(selectors.routeIndex.advancedSearchButton); - await page.waitForNumberOfElements(selectors.routeIndex.anyResult, 2); + it(`should reload the section and count the amount of routes after clonation`, async() => { + await page.waitForNumberOfElements(selectors.routeIndex.anyResult, 9); + const result = await page.countElement(selectors.routeIndex.anyResult); + + expect(result).toEqual(9); }); }); }); From 0715f8ac81bc633bfb3387ee0b3becde7351cb08 Mon Sep 17 00:00:00 2001 From: carlosjr Date: Mon, 28 Dec 2020 09:44:21 +0100 Subject: [PATCH 12/18] now loopback reconects to db --- loopback/server/connectors/vn-mysql.js | 95 ++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/loopback/server/connectors/vn-mysql.js b/loopback/server/connectors/vn-mysql.js index 4e1345cd6..fde0ddcf6 100644 --- a/loopback/server/connectors/vn-mysql.js +++ b/loopback/server/connectors/vn-mysql.js @@ -246,3 +246,98 @@ exports.initialize = function initialize(dataSource, callback) { dataSource.connector.connect(callback); } }; + +MySQL.prototype.connect = function(callback) { + const self = this; + const options = generateOptions(this.settings); + + if (this.client) { + if (callback) { + process.nextTick(function() { + callback(null, self.client); + }); + } + } else + this.client = connectionHandler(options, callback); + + function connectionHandler(options, callback) { + const client = mysql.createPool(options); + client.getConnection(function(err, connection) { + const conn = connection; + if (!err) { + if (self.debug) + debug('MySQL connection is established: ' + self.settings || {}); + + connection.release(); + } else { + if (err.code == 'ECONNREFUSED' || err.code == 'PROTOCOL_CONNECTION_LOST') { // PROTOCOL_CONNECTION_LOST + console.error(`MySQL connection lost (${err.code}). Retrying..`); + + return setTimeout(() => + connectionHandler(options, callback), 5000); + } + if (self.debug || !callback) + console.error('MySQL connection is failed: ' + self.settings || {}, err); + } + callback && callback(err, conn); + }); + + return client; + } +}; + +function generateOptions(settings) { + const s = settings || {}; + if (s.collation) { + // Charset should be first 'chunk' of collation. + s.charset = s.collation.substr(0, s.collation.indexOf('_')); + } else { + s.collation = 'utf8_general_ci'; + s.charset = 'utf8'; + } + + s.supportBigNumbers = (s.supportBigNumbers || false); + s.timezone = (s.timezone || 'local'); + + if (isNaN(s.connectionLimit)) + s.connectionLimit = 10; + + let options; + if (s.url) { + // use url to override other settings if url provided + options = s.url; + } else { + options = { + host: s.host || s.hostname || 'localhost', + port: s.port || 3306, + user: s.username || s.user, + password: s.password, + timezone: s.timezone, + socketPath: s.socketPath, + charset: s.collation.toUpperCase(), // Correct by docs despite seeming odd. + supportBigNumbers: s.supportBigNumbers, + connectionLimit: s.connectionLimit, + }; + + // Don't configure the DB if the pool can be used for multiple DBs + if (!s.createDatabase) + options.database = s.database; + + // Take other options for mysql driver + // See https://github.com/strongloop/loopback-connector-mysql/issues/46 + for (const p in s) { + if (p === 'database' && s.createDatabase) + continue; + + if (options[p] === undefined) + options[p] = s[p]; + } + // Legacy UTC Date Processing fallback - SHOULD BE TRANSITIONAL + if (s.legacyUtcDateProcessing === undefined) + s.legacyUtcDateProcessing = true; + + if (s.legacyUtcDateProcessing) + options.timezone = 'Z'; + } + return options; +} From f16eaf105be99c8a105a8fe0574865da767c44c8 Mon Sep 17 00:00:00 2001 From: carlosjr Date: Mon, 28 Dec 2020 09:46:33 +0100 Subject: [PATCH 13/18] enabled back end unit tests for jenkins --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d87695cc4..444eaefc4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -69,13 +69,13 @@ pipeline { } } } - /* stage('Backend') { + stage('Backend') { steps { nodejs('node-lts') { sh 'gulp launchBackTest --ci' } } - } */ + } } } stage('Build') { From 846117d3bdbe1ec10ef9fbba2aeae74b89ec41a6 Mon Sep 17 00:00:00 2001 From: carlosjr Date: Mon, 28 Dec 2020 10:16:25 +0100 Subject: [PATCH 14/18] backend unit tests disabled for jenkins --- Jenkinsfile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 444eaefc4..06eb85561 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -69,13 +69,13 @@ pipeline { } } } - stage('Backend') { - steps { - nodejs('node-lts') { - sh 'gulp launchBackTest --ci' - } - } - } + // stage('Backend') { + // steps { + // nodejs('node-lts') { + // sh 'gulp launchBackTest --ci' + // } + // } + // } } } stage('Build') { From 67072f5c2372fd84d908d4781ce27448ec1b487c Mon Sep 17 00:00:00 2001 From: carlosjr Date: Mon, 28 Dec 2020 14:13:22 +0100 Subject: [PATCH 15/18] e2e path for route index now works focused and full run --- e2e/paths/08-route/03_create_and_clone.spec.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/e2e/paths/08-route/03_create_and_clone.spec.js b/e2e/paths/08-route/03_create_and_clone.spec.js index c42bbdc55..be758f788 100644 --- a/e2e/paths/08-route/03_create_and_clone.spec.js +++ b/e2e/paths/08-route/03_create_and_clone.spec.js @@ -63,11 +63,14 @@ describe('Route create path', () => { await page.waitForState('route.index'); }); + let count; it(`should count the amount of routes before clonation`, async() => { - await page.waitForNumberOfElements(selectors.routeIndex.anyResult, 8); - const result = await page.countElement(selectors.routeIndex.anyResult); + await page.waitForFunction(selector => { + return document.querySelectorAll(selector).length > 6; + }, {}, selectors.routeIndex.anyResult); + count = await page.countElement(selectors.routeIndex.anyResult); - expect(result).toEqual(8); + expect(count).toBeGreaterThanOrEqual(7); }); it(`should clone the first route`, async() => { @@ -80,10 +83,10 @@ describe('Route create path', () => { }); it(`should reload the section and count the amount of routes after clonation`, async() => { - await page.waitForNumberOfElements(selectors.routeIndex.anyResult, 9); + await page.waitForNumberOfElements(selectors.routeIndex.anyResult, count + 1); const result = await page.countElement(selectors.routeIndex.anyResult); - expect(result).toEqual(9); + expect(result).toEqual(count + 1); }); }); }); From 2886e02328db37fea4dc01fa39bed770a984a6f7 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 29 Dec 2020 08:50:12 +0100 Subject: [PATCH 16/18] Enabled loggable for locations --- .../{10260-december => 10260-holidays}/00-zoneLog.sql | 0 modules/zone/back/models/zone-included.json | 7 ++++++- modules/zone/back/models/zone.json | 5 ----- 3 files changed, 6 insertions(+), 6 deletions(-) rename db/changes/{10260-december => 10260-holidays}/00-zoneLog.sql (100%) diff --git a/db/changes/10260-december/00-zoneLog.sql b/db/changes/10260-holidays/00-zoneLog.sql similarity index 100% rename from db/changes/10260-december/00-zoneLog.sql rename to db/changes/10260-holidays/00-zoneLog.sql diff --git a/modules/zone/back/models/zone-included.json b/modules/zone/back/models/zone-included.json index 9f9508824..e462b7a65 100644 --- a/modules/zone/back/models/zone-included.json +++ b/modules/zone/back/models/zone-included.json @@ -1,6 +1,11 @@ { "name": "ZoneIncluded", - "base": "VnModel", + "base": "Loggable", + "log": { + "model": "ZoneLog", + "relation": "zone", + "showField": "isIncluded" + }, "options": { "mysql": { "table": "zoneIncluded" diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json index 1d1ccfd90..bafef0a95 100644 --- a/modules/zone/back/models/zone.json +++ b/modules/zone/back/models/zone.json @@ -43,11 +43,6 @@ } }, "relations": { - "geolocations": { - "type": "hasMany", - "model": "ZoneGeo", - "foreignKey": "zoneFk" - }, "agencyMode": { "type": "belongsTo", "model": "AgencyMode", From 20862db8546bae63d37f037917430982fef9ecaf Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 29 Dec 2020 13:39:10 +0100 Subject: [PATCH 17/18] 2690 - Duplicated foreign key fix --- loopback/common/models/vn-model.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js index f56183df2..56fb7e656 100644 --- a/loopback/common/models/vn-model.js +++ b/loopback/common/models/vn-model.js @@ -146,8 +146,14 @@ module.exports = function(Self) { function replaceErr(err, replaceErrFunc) { if (Array.isArray(err)) { let errs = []; - for (let e of err) - errs.push(replaceErrFunc(e)); + const errors = err.filter(error => { + return error != undefined && error != null; + }); + for (let e of errors) { + if (!(e instanceof UserError)) + errs.push(replaceErrFunc(e)); + else errs.push(e); + } return errs; } return replaceErrFunc(err); From edd25a347bd6c04806f84767b57f1983bd9cf3db Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 29 Dec 2020 13:44:12 +0100 Subject: [PATCH 18/18] Moved line --- loopback/common/models/vn-model.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js index 56fb7e656..cc3eede8e 100644 --- a/loopback/common/models/vn-model.js +++ b/loopback/common/models/vn-model.js @@ -145,10 +145,10 @@ module.exports = function(Self) { rewriteDbError(replaceErrFunc) { function replaceErr(err, replaceErrFunc) { if (Array.isArray(err)) { - let errs = []; const errors = err.filter(error => { return error != undefined && error != null; }); + let errs = []; for (let e of errors) { if (!(e instanceof UserError)) errs.push(replaceErrFunc(e));