From 590de622f58629547aca85a1925628ac490980ee Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 2 Nov 2020 14:30:33 +0100 Subject: [PATCH] Added model validations --- db/changes/10250-curfew/00-ACL.sql | 3 + db/dump/fixtures.sql | 4 +- loopback/locale/es.json | 4 +- .../util}/specs/validateIban.spec.js | 0 .../util}/specs/validateTin.spec.js | 0 .../util}/validateIban.js | 0 .../util}/validateTin.js | 0 modules/client/back/models/client.js | 13 ++-- modules/client/front/locale/es.yml | 2 +- .../supplier/specs/updateFiscalData.spec.js | 8 +-- modules/supplier/back/models/supplier.js | 59 +++++++++++++++++++ modules/supplier/front/fiscal-data/index.html | 10 +++- modules/supplier/front/index.js | 3 +- modules/supplier/front/routes.json | 3 +- 14 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 db/changes/10250-curfew/00-ACL.sql rename {modules/client/back/validations => loopback/util}/specs/validateIban.spec.js (100%) rename {modules/client/back/validations => loopback/util}/specs/validateTin.spec.js (100%) rename {modules/client/back/validations => loopback/util}/validateIban.js (100%) rename {modules/client/back/validations => loopback/util}/validateTin.js (100%) diff --git a/db/changes/10250-curfew/00-ACL.sql b/db/changes/10250-curfew/00-ACL.sql new file mode 100644 index 0000000000..c4987c405b --- /dev/null +++ b/db/changes/10250-curfew/00-ACL.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Supplier', 'updateFiscalData', 'WRITE', 'ALLOW', 'ROLE', 'administrative'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Supplier', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SupplierLog', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 9072195110..5cfcf92c68 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1211,8 +1211,8 @@ INSERT INTO `vn`.`annualAverageInvoiced`(`clientFk`, `invoiced`) INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`) VALUES (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1), - (2, 'Farmer King', 'The farmer', 4000020002, 1, 'B22222222', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8), - (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, 'C33333333', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3); + (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8), + (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3); INSERT INTO `cache`.`cache_calc`(`id`, `cache_id`, `cacheName`, `params`, `last_refresh`, `expires`, `created`, `connection_id`) VALUES diff --git a/loopback/locale/es.json b/loopback/locale/es.json index c3fe287eb9..580bd374fd 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -156,5 +156,7 @@ "shipped": "F. envío", "landed": "F. entrega", "addressFk": "Consignatario", - "companyFk": "Empresa" + "companyFk": "Empresa", + "The social name cannot be empty": "La razón social no puede quedar en blanco", + "The nif cannot be empty": "El NIF no puede quedar en blanco" } \ No newline at end of file diff --git a/modules/client/back/validations/specs/validateIban.spec.js b/loopback/util/specs/validateIban.spec.js similarity index 100% rename from modules/client/back/validations/specs/validateIban.spec.js rename to loopback/util/specs/validateIban.spec.js diff --git a/modules/client/back/validations/specs/validateTin.spec.js b/loopback/util/specs/validateTin.spec.js similarity index 100% rename from modules/client/back/validations/specs/validateTin.spec.js rename to loopback/util/specs/validateTin.spec.js diff --git a/modules/client/back/validations/validateIban.js b/loopback/util/validateIban.js similarity index 100% rename from modules/client/back/validations/validateIban.js rename to loopback/util/validateIban.js diff --git a/modules/client/back/validations/validateTin.js b/loopback/util/validateTin.js similarity index 100% rename from modules/client/back/validations/validateTin.js rename to loopback/util/validateTin.js diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 36bc60dfa5..01e5add6d9 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -1,7 +1,9 @@ -let request = require('request-promise-native'); -let UserError = require('vn-loopback/util/user-error'); -let getFinalState = require('vn-loopback/util/hook').getFinalState; -let isMultiple = require('vn-loopback/util/hook').isMultiple; +const request = require('request-promise-native'); +const UserError = require('vn-loopback/util/user-error'); +const getFinalState = require('vn-loopback/util/hook').getFinalState; +const isMultiple = require('vn-loopback/util/hook').isMultiple; +const validateTin = require('vn-loopback/util/validateTin'); +const validateIban = require('vn-loopback/util/validateIban'); const LoopBackContext = require('loopback-context'); module.exports = Self => { @@ -63,7 +65,7 @@ module.exports = Self => { Self.validateAsync('iban', ibanNeedsValidation, { message: 'The IBAN does not have the correct format' }); - let validateIban = require('../validations/validateIban'); + async function ibanNeedsValidation(err, done) { let filter = { fields: ['code'], @@ -83,7 +85,6 @@ module.exports = Self => { message: 'Invalid TIN' }); - let validateTin = require('../validations/validateTin'); async function tinIsValid(err, done) { if (!this.isTaxDataChecked) return done(); diff --git a/modules/client/front/locale/es.yml b/modules/client/front/locale/es.yml index e332a0229c..166bdbe1b7 100644 --- a/modules/client/front/locale/es.yml +++ b/modules/client/front/locale/es.yml @@ -7,7 +7,7 @@ Has to invoice: Factura Notify by email: Notificar vía e-mail Country: País Street: Domicilio fiscal -City: Municipio +City: Ciudad Postcode: Código postal Province: Provincia Address: Consignatario diff --git a/modules/supplier/back/methods/supplier/specs/updateFiscalData.spec.js b/modules/supplier/back/methods/supplier/specs/updateFiscalData.spec.js index 84e7029143..0eec549263 100644 --- a/modules/supplier/back/methods/supplier/specs/updateFiscalData.spec.js +++ b/modules/supplier/back/methods/supplier/specs/updateFiscalData.spec.js @@ -57,7 +57,7 @@ describe('Supplier updateFiscalData', () => { ctx.args = { name: 'Weapon Dealer', - nif: 'B11111111', + nif: 'A68446004', account: '4000000005', sageTaxTypeFk: 5, sageWithholdingFk: 2, @@ -65,13 +65,13 @@ describe('Supplier updateFiscalData', () => { postCode: '46460', city: 'VALENCIA', provinceFk: 2, - countryFk: 2, + countryFk: 1, }; const result = await app.models.Supplier.updateFiscalData(ctx, supplierId); expect(result.name).toEqual('Weapon Dealer'); - expect(result.nif).toEqual('B11111111'); + expect(result.nif).toEqual('A68446004'); expect(result.account).toEqual('4000000005'); expect(result.sageTaxTypeFk).toEqual(5); expect(result.sageWithholdingFk).toEqual(2); @@ -79,7 +79,7 @@ describe('Supplier updateFiscalData', () => { expect(result.postCode).toEqual('46460'); expect(result.city).toEqual('VALENCIA'); expect(result.provinceFk).toEqual(2); - expect(result.countryFk).toEqual(2); + expect(result.countryFk).toEqual(1); // Restores ctx.args = defaultData; diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js index d042037e78..1e5773a6ba 100644 --- a/modules/supplier/back/models/supplier.js +++ b/modules/supplier/back/models/supplier.js @@ -1,5 +1,64 @@ +const UserError = require('vn-loopback/util/user-error'); +const validateTin = require('vn-loopback/util/validateTin'); + module.exports = Self => { require('../methods/supplier/filter')(Self); require('../methods/supplier/getSummary')(Self); require('../methods/supplier/updateFiscalData')(Self); + + Self.validatesPresenceOf('name', { + message: 'The social name cannot be empty' + }); + + Self.validatesUniquenessOf('name', { + message: 'The supplier name must be unique' + }); + + Self.validatesPresenceOf('city', { + message: 'City cannot be empty' + }); + + Self.validatesPresenceOf('nif', { + message: 'The nif cannot be empty' + }); + + Self.validatesUniquenessOf('nif', { + message: 'TIN must be unique' + }); + + Self.validateAsync('nif', tinIsValid, { + message: 'Invalid TIN' + }); + + async function tinIsValid(err, done) { + const filter = { + fields: ['code'], + where: {id: this.countryFk} + }; + const country = await Self.app.models.Country.findOne(filter); + const code = country ? country.code.toLowerCase() : null; + + if (!this.nif || !validateTin(this.nif, code)) + err(); + done(); + } + + function isAlpha(value) { + const regexp = new RegExp(/^[ñça-zA-Z0-9\s]*$/i); + + return regexp.test(value); + } + + Self.observe('before save', async function(ctx) { + let changes = ctx.data || ctx.instance; + let orgData = ctx.currentInstance; + + const socialName = changes.name || orgData.name; + const hasChanges = orgData && changes; + const socialNameChanged = hasChanges + && orgData.socialName != socialName; + + if ((socialNameChanged) && !isAlpha(socialName)) + throw new UserError('The socialName has an invalid format'); + }); }; diff --git a/modules/supplier/front/fiscal-data/index.html b/modules/supplier/front/fiscal-data/index.html index 32fd38ad4c..a36a98441e 100644 --- a/modules/supplier/front/fiscal-data/index.html +++ b/modules/supplier/front/fiscal-data/index.html @@ -44,13 +44,15 @@ vn-focus label="Social name" ng-model="$ctrl.supplier.name" - rule - info="You can use letters and spaces"> + info="You can use letters and spaces" + required="true" + rule> @@ -120,7 +122,9 @@ url="Towns/location" fields="['id', 'name', 'provinceFk']" show-field="name" - value-field="name"> + value-field="name" + required="true" + rule> {{name}}, {{province.name}} ({{province.country.country}}) diff --git a/modules/supplier/front/index.js b/modules/supplier/front/index.js index a4017bbd98..5f52bc97f1 100644 --- a/modules/supplier/front/index.js +++ b/modules/supplier/front/index.js @@ -5,5 +5,6 @@ import './card'; import './descriptor'; import './index/'; import './search-panel'; -import './log'; import './summary'; +import './fiscal-data'; +import './log'; diff --git a/modules/supplier/front/routes.json b/modules/supplier/front/routes.json index d1f0701a1d..a5bc48c9a9 100644 --- a/modules/supplier/front/routes.json +++ b/modules/supplier/front/routes.json @@ -54,7 +54,8 @@ "description": "Fiscal data", "params": { "supplier": "$ctrl.supplier" - } + }, + "acl": ["administrative"] }, { "url" : "/log", "state": "supplier.card.log",