From d681d61c83f4c87811f336eeb482e274d7b0f215 Mon Sep 17 00:00:00 2001 From: Joan Date: Wed, 17 Oct 2018 12:49:18 +0200 Subject: [PATCH 1/3] Add new bank entity #736 --- client/agency/src/zone/index/index.html | 2 +- client/claim/src/index/index.html | 2 +- client/client/src/billing-data/index.html | 73 +++++++++++++++---- client/client/src/billing-data/index.js | 44 ++++++++++- client/client/src/billing-data/index.spec.js | 53 +++++++++++++- client/client/src/billing-data/locale/es.yml | 5 +- client/client/src/recovery/index/index.html | 2 +- client/client/src/web-access/index.js | 7 +- client/client/src/web-payment/index.html | 2 +- .../components/icon-button/icon-button.html | 2 +- .../src/components/icon-button/icon-button.js | 10 ++- .../src/components/snackbar/snackbar.html | 9 +-- client/item/src/search-panel/index.html | 18 ++--- client/order/src/index/index.js | 4 +- 14 files changed, 181 insertions(+), 52 deletions(-) diff --git a/client/agency/src/zone/index/index.html b/client/agency/src/zone/index/index.html index cae870c3f..a0e479c66 100644 --- a/client/agency/src/zone/index/index.html +++ b/client/agency/src/zone/index/index.html @@ -40,7 +40,7 @@ {{::zone.price | currency:'€':2}} diff --git a/client/claim/src/index/index.html b/client/claim/src/index/index.html index 586328b16..329199b0c 100644 --- a/client/claim/src/index/index.html +++ b/client/claim/src/index/index.html @@ -42,7 +42,7 @@ {{::claim.claimState.description}} diff --git a/client/client/src/billing-data/index.html b/client/client/src/billing-data/index.html index 154cc9abb..7da67c550 100644 --- a/client/client/src/billing-data/index.html +++ b/client/client/src/billing-data/index.html @@ -10,7 +10,7 @@ Pay method - + + + + + + - - - - - - + @@ -79,4 +85,39 @@ - \ No newline at end of file + + + + + +
New bank entity
+ + + + + + + + + + + + +
+ + + + +
\ No newline at end of file diff --git a/client/client/src/billing-data/index.js b/client/client/src/billing-data/index.js index 03a433179..02d4e11da 100644 --- a/client/client/src/billing-data/index.js +++ b/client/client/src/billing-data/index.js @@ -5,7 +5,21 @@ export default class Controller { this.$scope = $scope; this.$http = $http; this.vnApp = vnApp; - this.translate = $translate; + this.$translate = $translate; + } + + get client() { + return this._client; + } + + set client(value) { + this._client = value; + + if (!value) return; + + this.newBankEntity = { + countryFk: Number.parseInt(value.countryFk) + }; } onSubmit() { @@ -22,7 +36,7 @@ export default class Controller { notifyChanges() { this.$http.get(`/mailer/notification/payment-update/${this.client.id}`).then( - () => this.vnApp.showMessage(this.translate.instant('Notification sent!')) + () => this.vnApp.showMessage(this.$translate.instant('Notification sent!')) ); } @@ -35,6 +49,32 @@ export default class Controller { return payMethod || iban || dueDay; } + + onBankEntityOpen() { + this.newBankEntity.name = ''; + this.newBankEntity.bic = ''; + this.$scope.$apply(); + } + + onBankEntityResponse(response) { + if (response == 'ACCEPT') + try { + if (!this.newBankEntity.name) + throw new Error(`Name can't be empty`); + if (!this.newBankEntity.bic) + throw new Error(`Swift / BIC can't be empty`); + + this.$http.post(`/client/api/BankEntities`, this.newBankEntity).then(response => { + if (response.data) + this.client.bankEntityFk = response.data.id; + }); + } catch (e) { + this.vnApp.showError(this.$translate.instant(e.message)); + return false; + } + + return true; + } } Controller.$inject = ['$scope', '$http', 'vnApp', '$translate']; diff --git a/client/client/src/billing-data/index.spec.js b/client/client/src/billing-data/index.spec.js index 0158a325d..f875eb0a0 100644 --- a/client/client/src/billing-data/index.spec.js +++ b/client/client/src/billing-data/index.spec.js @@ -7,17 +7,20 @@ describe('Client', () => { let $httpBackend; let $scope; let controller; + let vnApp; beforeEach(() => { angular.mock.module('client'); }); - beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => { + beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _vnApp_) => { $componentController = _$componentController_; $httpBackend = _$httpBackend_; $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); $scope = $rootScope.$new(); $scope.watcher = watcher; + vnApp = _vnApp_; + spyOn(vnApp, 'showError'); controller = $componentController('vnClientBillingData', {$scope: $scope}); controller.client = {id: 101, name: 'Client name', payMethodFk: 4}; $scope.watcher.orgData = {id: 101, name: 'Client name', payMethodFk: 4}; @@ -55,5 +58,53 @@ describe('Client', () => { expect(controller.hasPaymethodChanges()).toBeFalsy(); }); }); + + describe('onBankEntityOpen()', () => { + it('should set reset the new bank entity properties', () => { + controller.newBankEntity.name = 'My new bank entity'; + controller.newBankEntity.bic = 'ES123'; + controller.onBankEntityOpen(); + + expect(controller.newBankEntity.name).toBe(''); + expect(controller.newBankEntity.bic).toBe(''); + }); + }); + + describe('onBankEntityResponse()', () => { + it(`should throw an error if name property is empty`, () => { + controller.newBankEntity = { + name: '', + bic: 'ES123', + countryFk: 1 + }; + controller.onBankEntityResponse('ACCEPT'); + + expect(vnApp.showError).toHaveBeenCalledWith(`Name can't be empty`); + }); + + it(`should throw an error if bic property is empty`, () => { + controller.newBankEntity = { + name: 'My new bank entity', + bic: '', + countryFk: 1 + }; + controller.onBankEntityResponse('ACCEPT'); + + expect(vnApp.showError).toHaveBeenCalledWith(`Swift / BIC can't be empty`); + }); + + it('should request to create a new bank entity', () => { + let newBankEntity = { + name: 'My new bank entity', + bic: 'ES123', + countryFk: 1 + }; + controller.newBankEntity = newBankEntity; + $httpBackend.when('POST', '/client/api/BankEntities').respond('done'); + $httpBackend.expectPOST('/client/api/BankEntities', newBankEntity); + controller.onBankEntityResponse('ACCEPT'); + $httpBackend.flush(); + }); + }); }); }); diff --git a/client/client/src/billing-data/locale/es.yml b/client/client/src/billing-data/locale/es.yml index b0334d0df..78d970f5c 100644 --- a/client/client/src/billing-data/locale/es.yml +++ b/client/client/src/billing-data/locale/es.yml @@ -12,4 +12,7 @@ Due day: Vencimiento Received LCR: Recibido LCR Received core VNL: Recibido core VNL Received B2B VNL: Recibido B2B VNL -Save: Guardar \ No newline at end of file +Save: Guardar +New bank entity: Nueva entidad bancaria +Name can't be empty: El nombre no puede quedar vacío +Swift / BIC can't be empty: El Swift / BIC no puede quedar vacío \ No newline at end of file diff --git a/client/client/src/recovery/index/index.html b/client/client/src/recovery/index/index.html index 86f7fdf9c..5cc874dcf 100644 --- a/client/client/src/recovery/index/index.html +++ b/client/client/src/recovery/index/index.html @@ -29,7 +29,7 @@ vn-acl-action="remove" vn-tooltip="Finish that recovery period" ng-if="!recovery.finished" - on-click="$ctrl.setFinished(recovery)"> + ng-click="$ctrl.setFinished(recovery)">
{{::recovery.started | date:'dd/MM/yyyy' }} diff --git a/client/client/src/web-access/index.js b/client/client/src/web-access/index.js index 8116e6c33..ef1ccd16c 100644 --- a/client/client/src/web-access/index.js +++ b/client/client/src/web-access/index.js @@ -1,10 +1,11 @@ import ngModule from '../module'; export default class Controller { - constructor($scope, $http, vnApp) { + constructor($scope, $http, vnApp, $translate) { this.$ = $scope; this.$http = $http; this.vnApp = vnApp; + this.$translate = $translate; this.canChangePassword = false; this.canEnableCheckBox = true; } @@ -52,14 +53,14 @@ export default class Controller { this.$http.patch(`/client/api/Accounts/${this.client.id}`, account); } catch (e) { - this.vnApp.showError(e.message); + this.vnApp.showError(this.$translate.instant(e.message)); return false; } return true; } } -Controller.$inject = ['$scope', '$http', 'vnApp']; +Controller.$inject = ['$scope', '$http', 'vnApp', '$translate']; ngModule.component('vnClientWebAccess', { template: require('./index.html'), diff --git a/client/client/src/web-payment/index.html b/client/client/src/web-payment/index.html index 5311122c5..0c4e52c47 100644 --- a/client/client/src/web-payment/index.html +++ b/client/client/src/web-payment/index.html @@ -29,7 +29,7 @@ vn-acl="administrative" vn-tooltip="Confirm transaction" ng-show="::!transaction.isConfirmed" - on-click="$ctrl.confirm(transaction)"> + ng-click="$ctrl.confirm(transaction)">
{{::transaction.id}} diff --git a/client/core/src/components/icon-button/icon-button.html b/client/core/src/components/icon-button/icon-button.html index d319b4808..53bb1378e 100644 --- a/client/core/src/components/icon-button/icon-button.html +++ b/client/core/src/components/icon-button/icon-button.html @@ -1,3 +1,3 @@ - \ No newline at end of file diff --git a/client/core/src/components/icon-button/icon-button.js b/client/core/src/components/icon-button/icon-button.js index a35c1afbc..100c76179 100644 --- a/client/core/src/components/icon-button/icon-button.js +++ b/client/core/src/components/icon-button/icon-button.js @@ -5,7 +5,13 @@ export default class IconButton { constructor($element) { if ($element[0].getAttribute('tabindex') == null) $element[0].tabIndex = 0; + $element.on("keyup", event => this.onKeyDown(event, $element)); + let button = $element[0].querySelector('button'); + $element[0].addEventListener('click', event => { + if (this.disabled || button.disabled) + event.stopImmediatePropagation(); + }); } onKeyDown(event, $element) { @@ -23,8 +29,6 @@ ngModule.component('vnIconButton', { template: require('./icon-button.html'), bindings: { icon: '@', - onClick: '&?', - enabled: ' - - - \ No newline at end of file +
\ No newline at end of file diff --git a/client/item/src/search-panel/index.html b/client/item/src/search-panel/index.html index 392efb51e..e14444805 100644 --- a/client/item/src/search-panel/index.html +++ b/client/item/src/search-panel/index.html @@ -56,16 +56,14 @@ show-field="name" value-field="name"> - - - - + + Date: Thu, 18 Oct 2018 08:08:31 +0200 Subject: [PATCH 2/3] update table clientLog --- services/db/install/changes/1.2-CHECK/02-clentLog.sql | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/db/install/changes/1.2-CHECK/02-clentLog.sql b/services/db/install/changes/1.2-CHECK/02-clentLog.sql index 163ce6086..24cc39711 100644 --- a/services/db/install/changes/1.2-CHECK/02-clentLog.sql +++ b/services/db/install/changes/1.2-CHECK/02-clentLog.sql @@ -6,4 +6,8 @@ CHANGE COLUMN `newInstance` `newInstance` TEXT NULL DEFAULT NULL ; ALTER TABLE `vn`.`clientLog` CHANGE COLUMN `model` `changedModel` TEXT CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL , ADD COLUMN `changedModelId` INT(11) NULL DEFAULT NULL AFTER `newInstance`, -ADD COLUMN `changedModelValue` INT(11) NULL DEFAULT NULL AFTER `changedModelId`; +ADD COLUMN `changedModelValue` VARCHAR(45) NULL DEFAULT NULL AFTER `changedModelId`; + + +ALTER TABLE `vn`.`clientLog` +CHANGE COLUMN `changedModel` `changedModel` VARCHAR(45) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ; From 76a2eda6e017a08f2a31260fcb3da75f513a8b46 Mon Sep 17 00:00:00 2001 From: Gerard Date: Thu, 18 Oct 2018 11:11:17 +0200 Subject: [PATCH 3/3] Tarea #707 Loggable disabled due broken tests --- services/loopback/common/models/loggable.js | 146 ++++++++++++-------- 1 file changed, 92 insertions(+), 54 deletions(-) diff --git a/services/loopback/common/models/loggable.js b/services/loopback/common/models/loggable.js index 902dc1291..02a7d9d1f 100644 --- a/services/loopback/common/models/loggable.js +++ b/services/loopback/common/models/loggable.js @@ -6,7 +6,7 @@ module.exports = function(Self) { Self.super_.setup.call(this); }; - Self.observe('after save', async function(ctx) { +/* Self.observe('after save', async function(ctx) { const loopBackContext = LoopBackContext.getCurrentContext(); await logInModel(ctx, loopBackContext); }); @@ -27,49 +27,58 @@ module.exports = function(Self) { ctx.hookState.newInstance = newInstance; }); -/* Self.observe('before delete', async function(ctx, next) { + Self.observe('before delete', async function(ctx) { let oldInstance; - if (ctx.instance) { - oldInstance = await fkToValue(ctx.data, ctx); - } - await logInModel(ctx); + // console.log(ctx.where); + if (ctx.where) { + let affectedModel = ctx.Model.definition.name; + // console.log(affectedModel); + let deletedInstances = await Self.modelBuilder.models[affectedModel].find({where: ctx.where}); + // console.log(deletedInstances); - next(); + let arrangedDeletedInstances = []; + deletedInstances.forEach(async element => { + console.log(element); + arrangedDeletedInstances.push(await fkToValue(element, ctx)); + }); + + console.log(arrangedDeletedInstances); + // let deletedIntancesData = await fkToValue(deletedInstances, ctx); + // console.log(deletedIntancesData); + // oldInstanceFk = pick(ctx.currentInstance, Object.keys(ctx.data)); + // oldInstance = await fkToValue(oldInstanceFk, ctx); + } + ctx.hookState.oldInstance = oldInstance; }); - Self.observe('after delete', async function(ctx, next) { - let oldInstance; - if (ctx.instance) { - oldInstance = await fkToValue(ctx.data, ctx); - } - await logInModel(ctx); - - next(); - }); -*/ - + Self.observe('after delete', async function(ctx) { + const loopBackContext = LoopBackContext.getCurrentContext(); + await logInModel(ctx, loopBackContext); + }); */ async function fkToValue(instance, ctx) { let result = {}; for (let key in instance) { if (key == 'id') continue; let val = instance[key]; - if (val === undefined) continue; + console.log(val); + if (val === undefined || val === null) continue; for (let key1 in ctx.Model.relations) { let val1 = ctx.Model.relations[key1]; if (val1.keyFrom == key) { let recordSet = await val1.modelTo.findById(val); val = recordSet.name; // FIXME preparar todos los modelos con campo name + console.log(val); break; } } result[key] = val; } + // console.log(result); return result; } async function logInModel(ctx, loopBackContext) { - let definition = ctx.Model.definition; let primaryKey; for (let property in definition.properties) { @@ -78,83 +87,112 @@ module.exports = function(Self) { break; } } + if (!primaryKey) throw new Error('Primary key not found'); let originId; - if (definition.settings.log.relation) { - // RELATIONS LOG + // RELATIONS LOG + let changedModelId; + + if (ctx.instance && !definition.settings.log.relation) { + originId = ctx.instance.id; + changedModelId = ctx.instance.id; + } else if (definition.settings.log.relation) { primaryKey = ctx.Model.relations[definition.settings.log.relation].keyFrom; - if(ctx.where && ctx.where[primaryKey]) - originId = ctx.where[primaryKey] - else + if (ctx.where && ctx.where[primaryKey]) + originId = ctx.where[primaryKey]; + else { originId = ctx.instance[primaryKey]; - } else { - if (ctx.instance) { - originId = ctx.instance.id; - } else { - originId = ctx.currentInstance.id; + changedModelId = ctx.instance.id; } + } else { + originId = ctx.currentInstance.id; + changedModelId = ctx.currentInstance.id; } - // This adds the originDescription field if it doesnt exists in the instances + // console.log(ctx.instance, ctx.where, ctx.currentInstance); - let originDescription = definition.settings.log.originDescription; - - if (originDescription && (!ctx.instance || !ctx.instance[originDescription])) - await Self.modelBuilder.models[definition.name].findById() - - if (ctx.hookState.oldInstance && !ctx.hookState.oldInstance[originDescription]){ - ctx.hookState.oldInstance[originDescription] = ctx.instance[originDescription]; - ctx.hookState.newInstance[originDescription] = ctx.instance[originDescription]; + // Sets the changedModelValue to save and the instances changed in case its an updateAll + let changedModelValue = definition.settings.log.changedModelValue; + if (changedModelValue && (!ctx.instance || !ctx.instance[changedModelValue])) { + var where = []; + changedModelId = []; + let changedInstances = await Self.modelBuilder.models[definition.name].find({where: ctx.where, fields: ['id', changedModelValue]}); + changedInstances.forEach(element => { + where.push(element[changedModelValue]); + changedModelId.push(element.id); + }); + } else if (ctx.hookState.oldInstance) { + where = ctx.instance[changedModelValue]; } + // console.log(where); - // This put some order in the intances putting the originDescription in first place - + // Set oldInstance, newInstance, userFk and action let oldInstance = {}; if (ctx.hookState.oldInstance) { - oldInstance[originDescription] = ctx.hookState.oldInstance[originDescription]; - delete ctx.hookState.oldInstance[originDescription]; Object.assign(oldInstance, ctx.hookState.oldInstance); } let newInstance = {}; if (ctx.hookState.newInstance) { - newInstance[originDescription] = ctx.hookState.newInstance[originDescription]; - delete ctx.hookState.newInstance[originDescription]; - Object.assign(newInstance, ctx.hookState.newInstance) + Object.assign(newInstance, ctx.hookState.newInstance); } - let userFk; - if (!loopBackContext) userFk = null; - else userFk = loopBackContext.active.accessToken.userId; + if (loopBackContext) + userFk = loopBackContext.active.accessToken.userId; let action = setActionType(ctx); - let logRecord = { originFk: originId, userFk: userFk, - model: ctx.Model.definition.name, action: action, + changedModel: ctx.Model.definition.name, + changedModelId: changedModelId, + changedModelValue: where, oldInstance: oldInstance, newInstance: newInstance }; + let logsToSave = setLogsToSave(where, changedModelId, logRecord); - let logModel = definition.settings.log.model - await Self.modelBuilder.models[logModel].create(logRecord); + let logModel = definition.settings.log.model; + + let transaction = {}; + if (ctx.options && ctx.options.transaction) { + transaction = ctx.options.transaction; + } + + // console.log(logsToSave); + await Self.modelBuilder.models[logModel].create(logsToSave, transaction); + } + + // this function retuns all the instances changed in case this is an updateAll + function setLogsToSave(changedInstances, changedInstancesIds, logRecord) { + let promises = []; + if (changedInstances && typeof changedInstances == "object") { + for (let i = 0; i < changedInstances.length; i++) { + logRecord.changedModelId = changedInstancesIds[i]; + logRecord.changedModelValue = changedInstances[i]; + promises.push(JSON.parse(JSON.stringify(logRecord))); + } + } else { + return logRecord; + } + return promises; } function setActionType(ctx) { let oldInstance = ctx.hookState.oldInstance; let newInstance = ctx.hookState.newInstance; - if (oldInstance && newInstance) { + if (oldInstance && newInstance) { return 'update'; } else if (!oldInstance && newInstance) { return 'insert'; } + return 'delete'; } };