diff --git a/front/core/components/watcher/locale/es.yml b/front/core/components/watcher/locale/es.yml index 37113b871..83553d20d 100644 --- a/front/core/components/watcher/locale/es.yml +++ b/front/core/components/watcher/locale/es.yml @@ -1,6 +1,4 @@ Are you sure exit without saving?: ¿Seguro que quieres salir sin guardar? Unsaved changes will be lost: Los cambios que no hayas guardado se perderán No changes to save: No hay cambios que guardar -Field are invalid: El campo {{tag}} no es válido Some fields are invalid: Algunos campos no son válidos - diff --git a/front/core/components/watcher/watcher.js b/front/core/components/watcher/watcher.js index 5e3069e02..8b52be69c 100644 --- a/front/core/components/watcher/watcher.js +++ b/front/core/components/watcher/watcher.js @@ -317,10 +317,8 @@ export default class Watcher extends Component { * Checks if the form is valid. */ isInvalid() { - if (this.form && this.form.$invalid) { - const tag = Object.values(this.form.$error)[0][0].$$attr.label; - throw new UserError(this.$t('Field are invalid', {tag: this.$t(tag)})); - } + if (this.form && this.form.$invalid) + throw new UserError('Some fields are invalid'); } /** diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 8a5f4db9f..83dc81d77 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -351,5 +351,5 @@ "sageWithholdingFk" : "Sage con tenencia", "Cannot past travels with entries": "No se pueden pasar envíos con entradas", "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}", - "Field are invalid": "El campo {{tag}} no es válido" + "Field are invalid": "El campo '{{tag}}' no es válido" } diff --git a/loopback/server/middleware.json b/loopback/server/middleware.json index f06395e89..cfc693217 100644 --- a/loopback/server/middleware.json +++ b/loopback/server/middleware.json @@ -35,7 +35,6 @@ } }, "auth:after": { - "./middleware/validate-model": {}, "./middleware/current-user": {}, "./middleware/salix-version": {} }, diff --git a/loopback/server/middleware/error-handler.js b/loopback/server/middleware/error-handler.js index 0c53d9e8b..e0d32d209 100644 --- a/loopback/server/middleware/error-handler.js +++ b/loopback/server/middleware/error-handler.js @@ -1,8 +1,36 @@ + const UserError = require('../../util/user-error'); const logToConsole = require('strong-error-handler/lib/logger'); const validations = [{ validation: message => String(message).startsWith('Value is not'), - message: ({__: $t, body}) => $t('Field are invalid', {tag: $t(Object.keys(body)[0])}) + message: ({__: $t}, _tag) => + $t('Field are invalid', {tag: $t(_tag)}), + handleError: ({method, originalUrl, body}) => { + const {models} = require('vn-loopback/server/server'); + let tag = null; + try { + let [module, id, path] = originalUrl.split('api/')[1].split('/'); + + let model = models[module]; + if (!model) { + module = module.substring(0, module.length - 1); + model = models[module]; + } + if (!model) throw new UserError(''); + const {accepts} = model.sharedClass.methods().find(method => method.name === path); + for (const [key, value] of Object.entries(body)) { + const accept = accepts.find(acc => acc.arg === key); + if (!value && accept.type !== 'any') { + tag = key; + break; + } + } + return tag; + } catch (error) { + throw new Error(error); + } + } + }]; module.exports = function() { return function(err, req, res, next) { @@ -16,7 +44,17 @@ module.exports = function() { if (err.statusCode == 400) { try { validations.forEach(validation => { - err.message = validation.validation(err.message) && validation.message(req); + if (validation.validation(err.message)) { + const error = validation.handleError(req); + if (error) + err.message = validation.message(req, error); + // const tag = handleNullProperty(req); + // if (tag) { + // const message = validation.message(req); + // } + // const tag = validateModel(req); + // if (tag) validation.message(req); + } }); return next(err); diff --git a/loopback/server/middleware/validate-model.js b/loopback/server/middleware/validate-model.js deleted file mode 100644 index 7c1538190..000000000 --- a/loopback/server/middleware/validate-model.js +++ /dev/null @@ -1,33 +0,0 @@ -const {models} = require('vn-loopback/server/server'); -const validatorBodyModel = require('../../../modules/client/back/methods/client/body_model_validator'); -const makeSingular = s => { - if (s == null || s.length == 0) - return s; - - return s.substring(0, s.length - 1); -}; -function blobToB64(data) { - return new Uint8Array(data).reduce(function(data, byte) { - return data + String.fromCharCode(byte); - }, ''); -} -module.exports = function(options) { - return function(req, res, next) { - const {method, originalUrl} = req; - if (['GET', 'DELETE'].includes(method)) return next(); - let [module, id, path] = originalUrl.split('api/')[1].split('/'); - - let model = models[module]; - if (!model) { - module = makeSingular(module); - model = models[module]; - } - const properties = model.definition.rawProperties; - const data = JSON.parse(blobToB64(req.readableBuffer.tail.data)); - let isValid = validatorBodyModel(properties, data); - - if (!isValid.isValid) - next(); - return next(); - }; -}; diff --git a/modules/client/back/methods/client/body_model_validator.js b/modules/client/back/methods/client/body_model_validator.js deleted file mode 100644 index 999c32024..000000000 --- a/modules/client/back/methods/client/body_model_validator.js +++ /dev/null @@ -1,42 +0,0 @@ - -const isNotNull = value => value !== null && value !== undefined && value !== ''; -const validatorBodyModel = (model, body) => { - let isValid = true; - let tag = null; - Object.entries(body).forEach(([key, value]) => { - if (!isValid) return; - const bodyArg = model.find(m => m.arg === key); - if (!bodyArg) return; - // throw new Error(`Property ${key} is not defined in this model`); - const {type} = bodyArg; - tag = key; - if (tag !== 'any') { - isValid = isNotNull(value); - return; - } - - switch (type) { - case 'number': - isValid = /^[0-9]*$/.test(value); - break; - - case 'boolean': - isValid = value instanceof Boolean; - break; - - case 'date': - isValid = (new Date(date) !== 'Invalid Date') && !isNaN(new Date(date)); - break; - - case 'string': - isValid = typeof value == 'string'; - break; - - default: - break; - } - }); - return {isValid, tag}; -}; - -module.exports = validatorBodyModel; diff --git a/modules/client/back/methods/client/specs/bodyValidator.spec.js b/modules/client/back/methods/client/specs/bodyValidator.spec.js deleted file mode 100644 index f4c84975f..000000000 --- a/modules/client/back/methods/client/specs/bodyValidator.spec.js +++ /dev/null @@ -1,414 +0,0 @@ -/* eslint-disable jasmine/no-spec-dupes */ -const validatorBodyModel = require('../body_model_validator'); -fdescribe('Validation Model', () => { - describe('should be number', () => { - it('success', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'number' - - }], {property: 1}); - - expect(isValid).toBeTrue(); - }); - - it('fail', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'number' - - }], {property: null}); - - expect(isValid).toBeFalse(); - }); - }); - - describe('should be string', () => { - it('success as number', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'string' - - }], {property: '1234'}); - - expect(isValid).toBeTrue(); - }); - - it('success as string', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'string' - - }], {property: 'null'}); - - expect(isValid).toBeTrue(); - }); - - it('fail', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'string' - - }], {property: null}); - - expect(isValid).toBeFalse(); - }); - }); - - describe('should be date', () => { - it('success', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'date' - - }], {property: new Date()}); - - expect(isValid).toBeTrue(); - }); - - it('fail', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'date' - - }], {property: null}); - - expect(isValid).toBeFalse(); - }); - }); - - describe('should be boolean', () => { - it('success as true', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'boolean' - - }], {property: true}); - - expect(isValid).toBeTrue(); - }); - - it('success as false', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'boolean' - - }], {property: false}); - - expect(isValid).toBeTrue(); - }); - - it('fail', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'boolean' - - }], {property: null}); - - expect(isValid).toBeFalse(); - }); - }); - - describe('should be any', () => { - it('success', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'any' - - }], {property: '1234'}); - - expect(isValid).toBeTrue(); - }); - - it('fail', () => { - let {isValid} = validatorBodyModel([{ - arg: 'property', - type: 'any' - - }], {property: null}); - - expect(isValid).toBeFalse(); - }); - }); -}); -describe('Validation Client Create', () => { - const newAccount = { - userName: 'Deadpool', - email: 'Deadpool@marvel.com', - fi: '16195279J', - name: 'Wade', - socialName: 'DEADPOOL MARVEL', - street: 'WALL STREET', - city: 'New York', - businessTypeFk: 'florist', - provinceFk: 1 - }; - const CLIENT_MODEL = [ - { - arg: 'socialName', - type: 'string' - }, - { - arg: 'fi', - type: 'string' - }, - { - arg: 'street', - type: 'string' - }, - { - arg: 'postcode', - type: 'string' - }, - { - arg: 'city', - type: 'string' - }, - { - arg: 'countryFk', - type: 'number' - }, - { - arg: 'provinceFk', - type: 'number' - }, - { - arg: 'sageTaxTypeFk', - type: 'any' - }, - { - arg: 'sageTransactionTypeFk', - type: 'any' - }, - { - arg: 'transferorFk', - type: 'any' - }, - { - arg: 'hasToInvoiceByAddress', - type: 'boolean' - }, - { - arg: 'hasToInvoice', - type: 'boolean' - }, - { - arg: 'isActive', - type: 'boolean' - }, - { - arg: 'isFreezed', - type: 'boolean' - }, - { - arg: 'isVies', - type: 'boolean' - }, - { - arg: 'isToBeMailed', - type: 'boolean' - }, - { - arg: 'isEqualizated', - type: 'boolean' - }, - { - arg: 'isTaxDataVerified', - type: 'boolean' - }, - { - arg: 'isTaxDataChecked', - type: 'boolean' - }, - { - arg: 'despiteOfClient', - type: 'number' - }, - { - arg: 'hasIncoterms', - type: 'boolean' - }, - { - arg: 'hasElectronicInvoice', - type: 'boolean' - } - ]; - it(`should not find Deadpool as he's not created yet`, async() => { - let isValid = false; - - isValid = validatorBodyModel(CLIENT_MODEL, newAccount).isValid; - - expect(isValid).toBeTrue(); - }); - - it('should create a new account', async() => { - let isValid = false; - - isValid = validatorBodyModel(CLIENT_MODEL, newAccount).isValid; - - expect(isValid).toBeTrue(); - }); - - it('should not be able to create a user if exists', async() => { - let isValid = false; - - isValid = validatorBodyModel(CLIENT_MODEL, newAccount).isValid; - - expect(isValid).toBeTrue(); - }); -}); -fdescribe('Validation Worker Create', () => { - const defaultWorker = { - // fi: '78457139E', - // name: 'DEFAULTERWORKER', - // firstName: 'DEFAULT', - // lastNames: 'WORKER', - // email: 'defaultWorker@mydomain.com', - // street: 'S/ DEFAULTWORKERSTREET', - // city: 'defaultWorkerCity', - // provinceFk: 1, - // countryFk: 1, - // companyFk: 442, - // postcode: '46680', - // phone: '123456789', - // code: 'DWW', - // bossFk: 9, - // birth: '2022-12-11T23:00:00.000Z', - // payMethodFk: 1, - // roleFk: 1 - }; - const WORKER_MODEL = [ - { - arg: 'fi', - type: 'string', - description: `The worker fi`, - required: true, - }, - { - arg: 'name', - type: 'string', - description: `The user name`, - required: true, - }, - { - arg: 'firstName', - type: 'string', - description: `The worker firstname`, - required: true, - }, - { - arg: 'lastNames', - type: 'string', - description: `The worker lastnames`, - required: true, - }, - { - arg: 'email', - type: 'string', - description: `The worker email`, - required: true, - }, - { - arg: 'street', - type: 'string', - description: `The worker address`, - required: true, - }, - { - arg: 'city', - type: 'string', - description: `The worker city`, - required: true, - }, - { - arg: 'provinceFk', - type: 'number', - description: `The worker province`, - required: true, - }, - { - arg: 'companyFk', - type: 'number', - description: `The worker company`, - required: true, - }, - { - arg: 'postcode', - type: 'string', - description: `The worker postcode`, - required: true, - }, - { - arg: 'phone', - type: 'string', - description: `The worker phone`, - required: true, - }, - { - arg: 'code', - type: 'string', - description: `The worker code`, - required: true, - }, - { - arg: 'bossFk', - type: 'number', - description: `The worker boss`, - required: true, - }, - { - arg: 'birth', - type: 'date', - description: `The worker birth`, - required: true, - }, - { - arg: 'payMethodFk', - type: 'number', - description: `The client payMethod`, - required: true, - }, - { - arg: 'iban', - type: 'string', - description: `The client iban`, - }, - { - arg: 'bankEntityFk', - type: 'number', - description: `The client bank entity`, - } - ]; - - it(`should not find worker as he's not created yet`, async() => { - let isValid = false; - - isValid = validatorBodyModel(WORKER_MODEL, defaultWorker).isValid; - - expect(isValid).toBeTrue(); - }); - - it('should create a new worker', async() => { - let isValid = false; - isValid = validatorBodyModel(WORKER_MODEL, defaultWorker).isValid; - - expect(isValid).toBeTrue(); - }); - - it('should update a new worker', async() => { - let isValid = false; - - isValid = validatorBodyModel(WORKER_MODEL, defaultWorker).isValid; - - expect(isValid).toBeTrue(); - }); - - it('should not be able to create a worker if exists', async() => { - let isValid = false; - let error; - - isValid = validatorBodyModel(WORKER_MODEL, defaultWorker).isValid; - - expect(isValid).toBeTrue(); - }); -}); diff --git a/modules/client/back/methods/client/updateFiscalData.js b/modules/client/back/methods/client/updateFiscalData.js index c87eba6be..5fd886c32 100644 --- a/modules/client/back/methods/client/updateFiscalData.js +++ b/modules/client/back/methods/client/updateFiscalData.js @@ -1,95 +1,4 @@ let UserError = require('vn-loopback/util/user-error'); -const validatorBodyModel = require('./body_model_validator'); -const BODY_MODEL = [ - { - arg: 'socialName', - type: 'string' - }, - { - arg: 'fi', - type: 'string' - }, - { - arg: 'street', - type: 'string' - }, - { - arg: 'postcode', - type: 'string' - }, - { - arg: 'city', - type: 'string' - }, - { - arg: 'countryFk', - type: 'number' - }, - { - arg: 'provinceFk', - type: 'number' - }, - { - arg: 'sageTaxTypeFk', - type: 'any' - }, - { - arg: 'sageTransactionTypeFk', - type: 'any' - }, - { - arg: 'transferorFk', - type: 'any' - }, - { - arg: 'hasToInvoiceByAddress', - type: 'boolean' - }, - { - arg: 'hasToInvoice', - type: 'boolean' - }, - { - arg: 'isActive', - type: 'boolean' - }, - { - arg: 'isFreezed', - type: 'boolean' - }, - { - arg: 'isVies', - type: 'boolean' - }, - { - arg: 'isToBeMailed', - type: 'boolean' - }, - { - arg: 'isEqualizated', - type: 'boolean' - }, - { - arg: 'isTaxDataVerified', - type: 'boolean' - }, - { - arg: 'isTaxDataChecked', - type: 'boolean' - }, - { - arg: 'despiteOfClient', - type: 'number' - }, - { - arg: 'hasIncoterms', - type: 'boolean' - }, - { - arg: 'hasElectronicInvoice', - type: 'boolean' - } -]; module.exports = Self => { Self.remoteMethod('updateFiscalData', { @@ -108,9 +17,92 @@ module.exports = Self => { http: {source: 'path'} }, { - arg: 'data', - type: 'object', - http: {source: 'body'} + arg: 'socialName', + type: 'string' + }, + { + arg: 'fi', + type: 'string' + }, + { + arg: 'street', + type: 'string' + }, + { + arg: 'postcode', + type: 'string' + }, + { + arg: 'city', + type: 'string' + }, + { + arg: 'countryFk', + type: 'number' + }, + { + arg: 'provinceFk', + type: 'number' + }, + { + arg: 'sageTaxTypeFk', + type: 'any' + }, + { + arg: 'sageTransactionTypeFk', + type: 'any' + }, + { + arg: 'transferorFk', + type: 'any' + }, + { + arg: 'hasToInvoiceByAddress', + type: 'boolean' + }, + { + arg: 'hasToInvoice', + type: 'boolean' + }, + { + arg: 'isActive', + type: 'boolean' + }, + { + arg: 'isFreezed', + type: 'boolean' + }, + { + arg: 'isVies', + type: 'boolean' + }, + { + arg: 'isToBeMailed', + type: 'boolean' + }, + { + arg: 'isEqualizated', + type: 'boolean' + }, + { + arg: 'isTaxDataVerified', + type: 'boolean' + }, + { + arg: 'isTaxDataChecked', + type: 'boolean' + }, + { + arg: 'despiteOfClient', + type: 'number' + }, + { + arg: 'hasIncoterms', + type: 'boolean' + }, + { + arg: 'hasElectronicInvoice', + type: 'boolean' } ], returns: { @@ -128,7 +120,9 @@ module.exports = Self => { let tx; const myOptions = {}; const models = Self.app.models; - const {args, req: {__: $t}} = ctx; + const args = ctx.args; + const userId = ctx.req.accessToken.userId; + const $t = ctx.req.__; if (typeof options == 'object') Object.assign(myOptions, options); @@ -154,22 +148,8 @@ module.exports = Self => { // Remove unwanted properties delete args.ctx; delete args.id; - const {isValid, tag} = validatorBodyModel(BODY_MODEL, args.data); - if (!isValid) { - const key = $t(`${tag}`); - throw new Error($t('Model is not valid', {key}) - ); - } - // const isValid = client.isValid(async function(valid) { - // if (!valid) { - // cb(new ValidationError(client), client); - // return; - // } - // // triggerSave(); - // }, args.data, myOptions); - // client.isValid(client.constructor.validations, client.data, {}); - const updatedClient = await client.updateAttributes(args.data, myOptions); + const updatedClient = await client.updateAttributes(args, myOptions); if (tx) await tx.commit(); diff --git a/modules/supplier/back/methods/supplier/updateFiscalData.js b/modules/supplier/back/methods/supplier/updateFiscalData.js index c0f0be14c..271ed8769 100644 --- a/modules/supplier/back/methods/supplier/updateFiscalData.js +++ b/modules/supplier/back/methods/supplier/updateFiscalData.js @@ -1,65 +1,3 @@ -const validatorBodyModel = require('../../../../client/back/methods/client/body_model_validator'); - -const BODY_MODEL = [{ - arg: 'name', - type: 'string' -}, -{ - arg: 'nif', - type: 'string' -}, -{ - arg: 'account', - type: 'any' -}, -{ - arg: 'sageTaxTypeFk', - type: 'any' -}, -{ - arg: 'sageWithholdingFk', - type: 'any' -}, -{ - arg: 'sageTransactionTypeFk', - type: 'any' -}, -{ - arg: 'postCode', - type: 'any' -}, -{ - arg: 'street', - type: 'any' -}, -{ - arg: 'city', - type: 'string' -}, -{ - arg: 'provinceFk', - type: 'any' -}, -{ - arg: 'countryFk', - type: 'any' -}, -{ - arg: 'supplierActivityFk', - type: 'string' -}, -{ - arg: 'healthRegister', - type: 'string' -}, -{ - arg: 'isVies', - type: 'boolean' -}, -{ - arg: 'isTrucker', - type: 'boolean' -}]; module.exports = Self => { Self.remoteMethod('updateFiscalData', { description: 'Updates fiscal data of a supplier', @@ -76,11 +14,65 @@ module.exports = Self => { http: {source: 'path'} }, { - arg: 'data', - type: 'object', - http: {source: 'body'} - } - ], + arg: 'name', + type: 'string' + }, + { + arg: 'nif', + type: 'string' + }, + { + arg: 'account', + type: 'any' + }, + { + arg: 'sageTaxTypeFk', + type: 'any' + }, + { + arg: 'sageWithholdingFk', + type: 'any' + }, + { + arg: 'sageTransactionTypeFk', + type: 'any' + }, + { + arg: 'postCode', + type: 'any' + }, + { + arg: 'street', + type: 'any' + }, + { + arg: 'city', + type: 'string' + }, + { + arg: 'provinceFk', + type: 'any' + }, + { + arg: 'countryFk', + type: 'any' + }, + { + arg: 'supplierActivityFk', + type: 'string' + }, + { + arg: 'healthRegister', + type: 'string' + }, + { + arg: 'isVies', + type: 'boolean' + }, + { + arg: 'isTrucker', + type: 'boolean' + }], returns: { arg: 'res', type: 'string', @@ -94,18 +86,13 @@ module.exports = Self => { Self.updateFiscalData = async(ctx, supplierId) => { const models = Self.app.models; - const {args} = ctx; + const args = ctx.args; const supplier = await models.Supplier.findById(supplierId); // Remove unwanted properties delete args.ctx; delete args.id; - const {isValid, tag} = validatorBodyModel(BODY_MODEL, args.data); - if (!isValid) { - const key = $t(`${tag}`); - throw new Error($t('Model is not valid', {key}) - ); - } - return supplier.updateAttributes(args.data); + + return supplier.updateAttributes(args); }; };