From 708c822ab097e3beb2e05a9738f51e6c21bd3ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joan=20S=C3=A1nchez?= Date: Wed, 14 Mar 2018 11:36:57 +0100 Subject: [PATCH] Credit classification & credit insurance task #150, #151, #152 --- client/client/routes.json | 51 ++++++++++++ client/client/src/client.js | 4 + .../credit-classification-create.html | 24 ++++++ .../credit-classification-create.js | 20 +++++ .../credit-classification-list.html | 43 ++++++++++ .../credit-classification-list.js | 68 ++++++++++++++++ .../credit-classification-list.spec.js | 80 +++++++++++++++++++ .../credit-classification-list/locale/es.yml | 4 + .../credit-insurance-create.html | 42 ++++++++++ .../credit-insurance-create.js | 20 +++++ .../src/credit-insurance-create/locale/es.yml | 1 + .../credit-insurance-list.html | 28 +++++++ .../credit-insurance-list.js | 17 ++++ .../src/credit-insurance-list/locale/es.yml | 1 + client/client/src/locale/es.yml | 2 +- client/client/src/summary/client-summary.html | 8 +- .../common/methods/creditInsurance/filter.js | 14 ++++ .../common/models/credit-classification.json | 2 +- .../client/common/models/credit-insurance.js | 22 +++++ .../common/models/credit-insurance.json | 2 +- services/loopback/common/models/client.json | 5 ++ 21 files changed, 451 insertions(+), 7 deletions(-) create mode 100644 client/client/src/credit-classification-create/credit-classification-create.html create mode 100644 client/client/src/credit-classification-create/credit-classification-create.js create mode 100644 client/client/src/credit-classification-list/credit-classification-list.html create mode 100644 client/client/src/credit-classification-list/credit-classification-list.js create mode 100644 client/client/src/credit-classification-list/credit-classification-list.spec.js create mode 100644 client/client/src/credit-classification-list/locale/es.yml create mode 100644 client/client/src/credit-insurance-create/credit-insurance-create.html create mode 100644 client/client/src/credit-insurance-create/credit-insurance-create.js create mode 100644 client/client/src/credit-insurance-create/locale/es.yml create mode 100644 client/client/src/credit-insurance-list/credit-insurance-list.html create mode 100644 client/client/src/credit-insurance-list/credit-insurance-list.js create mode 100644 client/client/src/credit-insurance-list/locale/es.yml create mode 100644 services/client/common/methods/creditInsurance/filter.js create mode 100644 services/client/common/models/credit-insurance.js diff --git a/client/client/routes.json b/client/client/routes.json index c466ad7f9..73eb28fd3 100644 --- a/client/client/routes.json +++ b/client/client/routes.json @@ -220,6 +220,57 @@ "params": { "client": "$ctrl.client" } + }, + { + "url": "/credit-classification", + "abstract": true, + "state": "clientCard.creditClassification", + "component": "ui-view", + "acl": ["creditInsurance"] + }, + { + "url": "/list", + "state": "clientCard.creditClassification.list", + "component": "vn-client-credit-classification-list", + "params": { + "client": "$ctrl.client" + }, + "menu": { + "description": "Credit contracts", + "icon": "security" + }, + "acl": ["creditInsurance"] + }, + { + "url": "/create", + "state": "clientCard.creditClassification.create", + "component": "vn-client-credit-classification-create", + "params": { + "client": "$ctrl.client" + } + }, + { + "url": "/credit-insurance", + "abstract": true, + "state": "clientCard.creditInsurance", + "component": "ui-view", + "acl": ["creditInsurance"] + }, + { + "url": "/:classificationId/list", + "state": "clientCard.creditInsurance.list", + "component": "vn-client-credit-insurance-list", + "params": { + "client": "$ctrl.client" + } + }, + { + "url": "/:classificationId/create", + "state": "clientCard.creditInsurance.create", + "component": "vn-client-credit-insurance-create", + "params": { + "client": "$ctrl.client" + } } ] } diff --git a/client/client/src/client.js b/client/client/src/client.js index 935a33b43..f583127a2 100644 --- a/client/client/src/client.js +++ b/client/client/src/client.js @@ -23,3 +23,7 @@ import './invoices/invoices'; import './summary/client-summary'; import './recovery-list/recovery-list'; import './recovery-create/recovery-create'; +import './credit-classification-list/credit-classification-list'; +import './credit-classification-create/credit-classification-create'; +import './credit-insurance-list/credit-insurance-list'; +import './credit-insurance-create/credit-insurance-create'; diff --git a/client/client/src/credit-classification-create/credit-classification-create.html b/client/client/src/credit-classification-create/credit-classification-create.html new file mode 100644 index 000000000..a8aa58ada --- /dev/null +++ b/client/client/src/credit-classification-create/credit-classification-create.html @@ -0,0 +1,24 @@ + + + +
+ + New contract + + + + + + + + +
diff --git a/client/client/src/credit-classification-create/credit-classification-create.js b/client/client/src/credit-classification-create/credit-classification-create.js new file mode 100644 index 000000000..9e5c5de1d --- /dev/null +++ b/client/client/src/credit-classification-create/credit-classification-create.js @@ -0,0 +1,20 @@ +import ngModule from '../module'; + +class Controller { + constructor($filter, $state) { + this.creditClassification = { + started: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm') + }; + this.$state = $state; + } +} + +Controller.$inject = ['$filter', '$state']; + +ngModule.component('vnClientCreditClassificationCreate', { + template: require('./credit-classification-create.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-classification-list/credit-classification-list.html b/client/client/src/credit-classification-list/credit-classification-list.html new file mode 100644 index 000000000..827e73453 --- /dev/null +++ b/client/client/src/credit-classification-list/credit-classification-list.html @@ -0,0 +1,43 @@ + + + Contract credit insurance + + + + + lock_outline + + +
Since {{::classification.started | date:'dd/MM/yyyy'}}
+
To {{classification.finished | date:'dd/MM/yyyy'}}
+
+ + + Credit {{insurance.credit}} + Grade + - + {{insurance.grade}} + Date {{insurance.created | date:'dd/MM/yyyy' }} + + + + + +
+
+
+
+ + +
\ No newline at end of file diff --git a/client/client/src/credit-classification-list/credit-classification-list.js b/client/client/src/credit-classification-list/credit-classification-list.js new file mode 100644 index 000000000..6b8d479e9 --- /dev/null +++ b/client/client/src/credit-classification-list/credit-classification-list.js @@ -0,0 +1,68 @@ +import ngModule from '../module'; + +class Controller { + + constructor($http, $scope) { + this.$http = $http; + this.$scope = $scope; + } + + $onChanges() { + if (this.client && this.client.id) + this._getClassifications(this.client.id); + } + + _getClassifications(clientId) { + let filter = { + include: [ + { + relation: 'creditInsurances', + scope: { + fields: ['id', 'credit', 'created', 'grade'], + order: 'created DESC', + limit: 2 + } + } + + ], + where: {client: clientId} + }; + filter = encodeURIComponent(JSON.stringify(filter)); + + let query = `/client/api/CreditClassifications?filter=${filter}`; + this.$http.get(query).then(res => { + if (res.data) + this.classifications = res.data; + }); + } + + canCreateNew() { + if (!this.classifications) + return false; + + let items = this.classifications; + for (let i = 0; i < items.length; i++) { + if (!items[i].finished) + return false; + } + + return true; + } + + closeContract(classification) { + let params = {finished: Date.now()}; + this.$http.patch(`/client/api/CreditClassifications/${classification.id}`, params).then(() => { + this._getClassifications(this.client.id); + }); + } +} + +Controller.$inject = ['$http', '$scope']; + +ngModule.component('vnClientCreditClassificationList', { + template: require('./credit-classification-list.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-classification-list/credit-classification-list.spec.js b/client/client/src/credit-classification-list/credit-classification-list.spec.js new file mode 100644 index 000000000..c233b6dc8 --- /dev/null +++ b/client/client/src/credit-classification-list/credit-classification-list.spec.js @@ -0,0 +1,80 @@ +import './credit-classification-list.js'; + +describe('Client', () => { + describe('Component vnClientCreditClassificationList', () => { + let $componentController; + let controller; + let $httpBackend; + + beforeEach(() => { + angular.mock.module('client'); + }); + + beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => { + $componentController = _$componentController_; + $httpBackend = _$httpBackend_; + controller = $componentController('vnClientCreditClassificationList'); + })); + + describe('_getClassifications()', () => { + it('should perform a GET query to define the classifications property in the controller', () => { + let res = ['some classifications']; + let query = '/client/api/CreditClassifications?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22creditInsurances%22%2C%22scope%22%3A%7B%22fields%22%3A%5B%22id%22%2C%22credit%22%2C%22created%22%2C%22grade%22%5D%2C%22order%22%3A%22created%20DESC%22%2C%22limit%22%3A2%7D%7D%5D%2C%22where%22%3A%7B%7D%7D'; + + $httpBackend.whenGET(query).respond(res); + $httpBackend.expectGET(query); + controller._getClassifications(); + $httpBackend.flush(); + + expect(controller.classifications).toEqual(['some classifications']); + }); + }); + + describe('canCreateNew()', () => { + it(`should return false if doesn't have classifications`, () => { + let result = controller.canCreateNew(); + + expect(result).toBeFalsy(); + }); + + it(`should return false if finds a classification without due date`, () => { + controller.classifications = [ + {finished: Date.now()}, + {finished: null} + ]; + + let result = controller.canCreateNew(); + + expect(result).toBeFalsy(); + }); + + it(`should return true if all classifications are defined with due date`, () => { + controller.classifications = [ + {finished: Date.now()}, + {finished: Date.now()} + ]; + + let result = controller.canCreateNew(); + + expect(result).toBeTruthy(); + }); + }); + + describe('closeContract()', () => { + it('should perform a GET query to set a due date to a contract', () => { + let res = ['pepinillos']; + controller.client = {id: 101}; + let classification = {id: 1}; + let query = '/client/api/CreditClassifications/1'; + spyOn(controller, '_getClassifications'); + + $httpBackend.whenPATCH(query).respond(res); + $httpBackend.expectPATCH(query); + controller.closeContract(classification); + $httpBackend.flush(); + + expect(controller._getClassifications).toHaveBeenCalledWith(101); + }); + }); + }); +}); diff --git a/client/client/src/credit-classification-list/locale/es.yml b/client/client/src/credit-classification-list/locale/es.yml new file mode 100644 index 000000000..aec6b185a --- /dev/null +++ b/client/client/src/credit-classification-list/locale/es.yml @@ -0,0 +1,4 @@ +Contract credit insurance: Contratos de seguro de crédito +New contract: Nuevo contrato +Close contract: Cerrar contrato +Edit contract: Modificar contrato \ No newline at end of file diff --git a/client/client/src/credit-insurance-create/credit-insurance-create.html b/client/client/src/credit-insurance-create/credit-insurance-create.html new file mode 100644 index 000000000..8d8005187 --- /dev/null +++ b/client/client/src/credit-insurance-create/credit-insurance-create.html @@ -0,0 +1,42 @@ + + + +
+ + New credit + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/client/client/src/credit-insurance-create/credit-insurance-create.js b/client/client/src/credit-insurance-create/credit-insurance-create.js new file mode 100644 index 000000000..f9d22189f --- /dev/null +++ b/client/client/src/credit-insurance-create/credit-insurance-create.js @@ -0,0 +1,20 @@ +import ngModule from '../module'; + +class Controller { + constructor($state, $filter) { + this.insurance = { + created: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm') + }; + this.classificationId = $state.params.classificationId; + } +} + +Controller.$inject = ['$state', '$filter']; + +ngModule.component('vnClientCreditInsuranceCreate', { + template: require('./credit-insurance-create.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-insurance-create/locale/es.yml b/client/client/src/credit-insurance-create/locale/es.yml new file mode 100644 index 000000000..deb27ae21 --- /dev/null +++ b/client/client/src/credit-insurance-create/locale/es.yml @@ -0,0 +1 @@ +New credit: Añadir crédito \ No newline at end of file diff --git a/client/client/src/credit-insurance-list/credit-insurance-list.html b/client/client/src/credit-insurance-list/credit-insurance-list.html new file mode 100644 index 000000000..ba3931013 --- /dev/null +++ b/client/client/src/credit-insurance-list/credit-insurance-list.html @@ -0,0 +1,28 @@ + + + + + Requested credits + + + + + + + + {{insurance.credit}} + {{insurance.grade}} + {{insurance.created | date: 'dd/MM/yyyy'}} + + + + + + + + + \ No newline at end of file diff --git a/client/client/src/credit-insurance-list/credit-insurance-list.js b/client/client/src/credit-insurance-list/credit-insurance-list.js new file mode 100644 index 000000000..73403f375 --- /dev/null +++ b/client/client/src/credit-insurance-list/credit-insurance-list.js @@ -0,0 +1,17 @@ +import ngModule from '../module'; + +class Controller { + constructor($state) { + this.classificationId = $state.params.classificationId; + } +} + +Controller.$inject = ['$state']; + +ngModule.component('vnClientCreditInsuranceList', { + template: require('./credit-insurance-list.html'), + controller: Controller, + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-insurance-list/locale/es.yml b/client/client/src/credit-insurance-list/locale/es.yml new file mode 100644 index 000000000..b21b6b030 --- /dev/null +++ b/client/client/src/credit-insurance-list/locale/es.yml @@ -0,0 +1 @@ +Requested credits: Créditos solicitados \ No newline at end of file diff --git a/client/client/src/locale/es.yml b/client/client/src/locale/es.yml index bb2984d9b..c46f0430a 100644 --- a/client/client/src/locale/es.yml +++ b/client/client/src/locale/es.yml @@ -17,7 +17,7 @@ Save: Guardar Pay method : Forma de pago Address: Consignatario Credit : Crédito -Secured credit: Crédito asegurado +Credit contracts: Contratos de crédito Verified data: Datos comprobados Mandate: Mandato Amount: Importe \ No newline at end of file diff --git a/client/client/src/summary/client-summary.html b/client/client/src/summary/client-summary.html index e506ae23e..a720f9c41 100644 --- a/client/client/src/summary/client-summary.html +++ b/client/client/src/summary/client-summary.html @@ -123,8 +123,8 @@
Recovery
-

Since {{$ctrl.recovery.started}}

-

To {{$ctrl.recovery.finished}}

+

Since {{$ctrl.recovery.started | date:'dd/MM/yyyy'}}

+

To {{$ctrl.recovery.finished | date:'dd/MM/yyyy'}}

Amount {{$ctrl.recovery.amount | currency:'€':2}}

Period {{$ctrl.recovery.period}}

@@ -145,8 +145,8 @@

Secured credit - - - {{$ctrl.summary.creditInsurance | currency:'€':2}} + - + {{$ctrl.summary.creditInsurance | currency:'€':2}}

diff --git a/services/client/common/methods/creditInsurance/filter.js b/services/client/common/methods/creditInsurance/filter.js new file mode 100644 index 000000000..121c3a407 --- /dev/null +++ b/services/client/common/methods/creditInsurance/filter.js @@ -0,0 +1,14 @@ +module.exports = Self => { + Self.installMethod('filter', filterParams); + + function filterParams(params) { + return { + where: { + creditClassification: params.creditClassification + }, + skip: (params.page - 1) * params.size, + limit: params.size, + order: params.order + }; + } +}; diff --git a/services/client/common/models/credit-classification.json b/services/client/common/models/credit-classification.json index 01087314a..74edb6640 100644 --- a/services/client/common/models/credit-classification.json +++ b/services/client/common/models/credit-classification.json @@ -33,7 +33,7 @@ "model": "Client", "foreignKey": "client" }, - "creditInsurance": { + "creditInsurances": { "type": "hasMany", "model": "CreditInsurance", "foreignKey": "creditClassification" diff --git a/services/client/common/models/credit-insurance.js b/services/client/common/models/credit-insurance.js new file mode 100644 index 000000000..95902ab9c --- /dev/null +++ b/services/client/common/models/credit-insurance.js @@ -0,0 +1,22 @@ +module.exports = function(Self) { + require('../methods/creditInsurance/filter.js')(Self); + + Self.validateBinded('credit', Self.validateCredit, { + message: 'The credit must be an integer greater than or equal to zero', + allowNull: false, // FIXME: Ignored by loopback when it's false + allowBlank: false + }); + + Self.validateCredit = function(credit) { + return (credit >= 0 && credit % 1 == 0); + }; + + Self.validateBinded('grade', Self.validateGrade, { + message: 'The grade must be an integer greater than or equal to zero', + allowNull: true + }); + + Self.validateGrade = function(grade) { + return (typeof grade === 'undefined' || (grade >= 0 && grade % 1 == 0)); + }; +}; diff --git a/services/client/common/models/credit-insurance.json b/services/client/common/models/credit-insurance.json index a6d280bc6..58dd53ccc 100644 --- a/services/client/common/models/credit-insurance.json +++ b/services/client/common/models/credit-insurance.json @@ -27,7 +27,7 @@ } }, "relations": { - "creditClassification": { + "classification": { "type": "belongsTo", "model": "CreditClassification", "foreignKey": "creditClassification" diff --git a/services/loopback/common/models/client.json b/services/loopback/common/models/client.json index c7120e67a..c47e3e8a3 100644 --- a/services/loopback/common/models/client.json +++ b/services/loopback/common/models/client.json @@ -156,6 +156,11 @@ "type": "hasMany", "model": "Greuge", "foreignKey": "clientFk" + }, + "creditClassifications": { + "type": "hasMany", + "model": "CreditClassification", + "foreignKey": "client" } } } \ No newline at end of file