From c6c40de2fc36dadfe0e6d4c007ffb5b9dc1f5c10 Mon Sep 17 00:00:00 2001 From: jgallego Date: Fri, 19 Oct 2018 08:40:32 +0200 Subject: [PATCH 1/3] # 702 Client.risk --- client/client/routes.json | 26 ++++- client/client/src/client.js | 3 +- client/client/src/invoice/index.html | 42 ------- client/client/src/invoice/index.js | 14 --- client/client/src/invoice/locale/es.yml | 4 - client/client/src/risk/index/index.html | 79 +++++++++++++ client/client/src/risk/index/index.js | 25 +++++ client/client/src/risk/index/locale/es.yml | 6 + client/client/src/summary/index.html | 2 +- client/client/src/summary/index.js | 10 ++ client/client/src/summary/index.spec.js | 34 +++--- services/agency/package.json | 2 +- .../client/common/methods/receipt/filter.js | 74 ++++++++++++ .../methods/receipt/specs/filter.spec.js | 13 +++ services/client/common/models/receipt.js | 3 + services/client/common/models/receipt.json | 105 +++++++++--------- .../db/install/changes/1.2-CHECK/06.ACL.sql | 3 +- .../loopback/common/methods/client/summary.js | 6 +- services/loopback/common/models/client.json | 2 +- 19 files changed, 309 insertions(+), 144 deletions(-) delete mode 100644 client/client/src/invoice/index.html delete mode 100644 client/client/src/invoice/index.js delete mode 100644 client/client/src/invoice/locale/es.yml create mode 100644 client/client/src/risk/index/index.html create mode 100644 client/client/src/risk/index/index.js create mode 100644 client/client/src/risk/index/locale/es.yml create mode 100644 services/client/common/methods/receipt/filter.js create mode 100644 services/client/common/methods/receipt/specs/filter.spec.js create mode 100644 services/client/common/models/receipt.js diff --git a/client/client/routes.json b/client/client/routes.json index 353d87d2e..5d3311a0f 100644 --- a/client/client/routes.json +++ b/client/client/routes.json @@ -205,14 +205,32 @@ } }, { - "url": "/invoice", - "state": "client.card.invoice", - "component": "vn-client-invoice", - "description": "Invoices", + "url": "/risk", + "abstract": true, + "state": "client.card.risk", + "component": "ui-view" + }, + { + "url": "/index", + "state": "client.card.risk.index", + "component": "vn-client-risk-index", + "description": "Risk", + "params": { + "client": "$ctrl.client" + }, "menu": { "icon": "icon-invoices" } }, + { + "url": "/create", + "state": "client.card.risk.create", + "component": "vn-client-risk-create", + "description": "New payment", + "params": { + "client": "$ctrl.client" + } + }, { "url": "/recovery", "abstract": true, diff --git a/client/client/src/client.js b/client/client/src/client.js index a6cc97716..007a1c970 100644 --- a/client/client/src/client.js +++ b/client/client/src/client.js @@ -19,8 +19,9 @@ import './credit/index'; import './credit/create'; import './greuge/index'; import './greuge/create'; +import './risk/index'; +import './risk/create'; import './mandate'; -import './invoice'; import './summary'; import './recovery/index'; import './recovery/create'; diff --git a/client/client/src/invoice/index.html b/client/client/src/invoice/index.html deleted file mode 100644 index 64e6f2d84..000000000 --- a/client/client/src/invoice/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - Invoices - - - - Reference - Issue date - Due date - Amount - - - - - - {{::invoice.ref}} - {{::invoice.issued | date:'dd/MM/yyyy' }} - {{::invoice.dued | date:'dd/MM/yyyy' }} - {{::invoice.amount | currency:' €': 2}} - - - - No results - - - - - - - \ No newline at end of file diff --git a/client/client/src/invoice/index.js b/client/client/src/invoice/index.js deleted file mode 100644 index fd973ceb9..000000000 --- a/client/client/src/invoice/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import ngModule from '../module'; - -class Controller { - constructor($stateParams) { - this.$stateParams = $stateParams; - } -} - -Controller.$inject = ['$stateParams']; - -ngModule.component('vnClientInvoice', { - template: require('./index.html'), - controller: Controller -}); diff --git a/client/client/src/invoice/locale/es.yml b/client/client/src/invoice/locale/es.yml deleted file mode 100644 index 819827284..000000000 --- a/client/client/src/invoice/locale/es.yml +++ /dev/null @@ -1,4 +0,0 @@ -Reference: Referencia -Issue date: Fecha de emisión -Due date: Vencimiento -Amount: Total \ No newline at end of file diff --git a/client/client/src/risk/index/index.html b/client/client/src/risk/index/index.html new file mode 100644 index 000000000..95c7fd431 --- /dev/null +++ b/client/client/src/risk/index/index.html @@ -0,0 +1,79 @@ + + + + + + + + Risk +
+
Total por empresa
+ + + + +
+
+ + + + + Date + Creation date + Employee + Reference + Bank + Debit + Credit + Conciliated + Company + + + + + {{::risk.payed | dateTime:'dd/MM/yyyy'}} + {{::risk.created | dateTime:'dd/MM/yyyy HH:mm'}} + {{::risk.firstName}} {{::risk.name}} + {{::risk.reference}} + {{::risk.bankFk}} + {{::risk.debit | currency: ' €': 2}} + {{::risk.credit | currency: ' €': 2}} + + + + + {{::risk.company}} + + + + No results + + + + + +
+
+ + + + \ No newline at end of file diff --git a/client/client/src/risk/index/index.js b/client/client/src/risk/index/index.js new file mode 100644 index 000000000..348e9b107 --- /dev/null +++ b/client/client/src/risk/index/index.js @@ -0,0 +1,25 @@ +import ngModule from '../../module'; + +class Controller { + constructor($stateParams) { + this.$stateParams = $stateParams; + + this.filter = { + include: { + relation: "company", + scope: { + fields: ["code"] + } + }, + where: { + clientFk: $stateParams.id + }}; + } +} + +Controller.$inject = ['$stateParams']; + +ngModule.component('vnClientRiskIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/client/client/src/risk/index/locale/es.yml b/client/client/src/risk/index/locale/es.yml new file mode 100644 index 000000000..78af91b1a --- /dev/null +++ b/client/client/src/risk/index/locale/es.yml @@ -0,0 +1,6 @@ +Creation date: Fecha de creación +Reference: Referencia +Bank: Caja +Debit: Debe +Conciliated: Conciliado +New payment: Añadir pago \ No newline at end of file diff --git a/client/client/src/summary/index.html b/client/client/src/summary/index.html index 7972475c5..4d41ad036 100644 --- a/client/client/src/summary/index.html +++ b/client/client/src/summary/index.html @@ -190,7 +190,7 @@ value="{{$ctrl.summary.creditInsurance | currency:'€ ':2}}"> + value="{{$ctrl.summary.sumRisk | currency:'€ ':2}}"> { + total += risk.amount; + }); + return total; + } } Controller.$inject = ['$http']; diff --git a/client/client/src/summary/index.spec.js b/client/client/src/summary/index.spec.js index 99c20e37d..33f0b579b 100644 --- a/client/client/src/summary/index.spec.js +++ b/client/client/src/summary/index.spec.js @@ -21,32 +21,34 @@ describe('Client', () => { describe('$onChanges()', () => { it('should perform a GET query and define summary property', () => { let res = {name: 'Superman', classifications: []}; + + spyOn(controller, "sumRisk"); $httpBackend.when('GET', `/client/api/Clients/101/summary`).respond(200, res); $httpBackend.expect('GET', `/client/api/Clients/101/summary`); + controller.$onChanges(); $httpBackend.flush(); expect(controller.summary).toBeDefined(); expect(controller.summary.name).toEqual('Superman'); - expect(controller.grade).toBeUndefined(); }); + }); - it('should perform a GET query and define summary and grade property', () => { - let res = { - name: 'Superman', - classifications: [{insurances: [ - {id: 1, grade: 1} - ]}] - }; - $httpBackend.when('GET', `/client/api/Clients/101/summary`).respond(200, res); - $httpBackend.expect('GET', `/client/api/Clients/101/summary`); - controller.$onChanges(); - $httpBackend.flush(); + describe('sumRisk()', () => { + it('should sum property amount of an array', () => { + controller.summary = { + clientRisks: [{ + companyFk: 442, + amount: 100 + }, + { + companyFk: 567, + amount: 200 + }]}; - expect(controller.summary).toBeDefined(); - expect(controller.summary.name).toEqual('Superman'); - expect(controller.grade).toBeDefined(); - expect(controller.grade).toEqual(1); + let result = controller.sumRisk(); + + expect(result).toEqual(300); }); }); }); diff --git a/services/agency/package.json b/services/agency/package.json index 02585bae3..1de5babf5 100644 --- a/services/agency/package.json +++ b/services/agency/package.json @@ -16,4 +16,4 @@ "dependencies": { "vn-loopback": "file:../loopback" } -} \ No newline at end of file +} diff --git a/services/client/common/methods/receipt/filter.js b/services/client/common/methods/receipt/filter.js new file mode 100644 index 000000000..d64413197 --- /dev/null +++ b/services/client/common/methods/receipt/filter.js @@ -0,0 +1,74 @@ +const ParameterizedSQL = require('vn-loopback/node_modules/loopback-connector').ParameterizedSQL; + +module.exports = Self => { + Self.remoteMethod('filter', { + description: 'Find all instances of the model matched by filter from the data source.', + accessType: 'READ', + accepts: [ + { + arg: 'filter', + type: 'Object', + description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', + http: {source: 'query'} + }, { + arg: 'params', + type: 'Object', + description: 'clientFk', + http: {source: 'query'} + } + ], + returns: { + type: ['Object'], + root: true + }, + http: { + path: `/filter`, + verb: 'GET' + } + }); + + Self.filter = async (filter, params) => { + let stmt = new ParameterizedSQL( + `SELECT + r.id, + r.isConciliate, + r.payed, + c.code AS company, + r.created, + '' description, + 0 AS debit, + r.amountPaid AS credit, + r.bankFk, + firstName, + name, + r.clientFk + FROM vn.receipt r + JOIN vn.worker w ON w.id = r.workerFk + JOIN vn.company c ON c.id = r.companyFk + WHERE clientFk = ? + UNION ALL + SELECT + i.id, + TRUE, + i.dued, + c.code AS company, + i.created, + CONCAT(' N/FRA ', i.ref) description, + i.amount AS debit, + 0 credit, + NULL bank, + NULL firstName, + NULL name, + i.clientFk + FROM vn.invoiceOut i + JOIN vn.company c ON c.id = i.companyFk + WHERE clientFk = ? + ORDER BY payed DESC, created DESC`, [ + params.clientFk, + params.clientFk + ]); + + stmt.merge(Self.buildPagination(filter)); + return await Self.rawStmt(stmt); + }; +}; diff --git a/services/client/common/methods/receipt/specs/filter.spec.js b/services/client/common/methods/receipt/specs/filter.spec.js new file mode 100644 index 000000000..381f98eec --- /dev/null +++ b/services/client/common/methods/receipt/specs/filter.spec.js @@ -0,0 +1,13 @@ +const app = require(`${servicesDir}/client/server/server`); + +describe('receipt filter()', () => { + it('should call the filter method', async() => { + let filter = {limit: 20}; + let params = { + clientFk: 101 + }; + let result = await app.models.Receipt.filter(filter, params); + + expect(result.length).toBeGreaterThan(0); + }); +}); diff --git a/services/client/common/models/receipt.js b/services/client/common/models/receipt.js new file mode 100644 index 000000000..97907c457 --- /dev/null +++ b/services/client/common/models/receipt.js @@ -0,0 +1,3 @@ +module.exports = function(Self) { + require('../methods/receipt/filter')(Self); +}; diff --git a/services/client/common/models/receipt.json b/services/client/common/models/receipt.json index ad18ff44d..1e99a3d0c 100644 --- a/services/client/common/models/receipt.json +++ b/services/client/common/models/receipt.json @@ -5,59 +5,54 @@ "mysql": { "table": "receipt" } -}, -"properties": { - "id": { - "id": true, - "type": "Number", - "description": "Identifier" - }, - "ref": { - "id": true, - "type": "String", - "required": true - }, - "amountPaid": { - "type": "Number" - }, - "amountUnpaid": { - "type": "Number" - }, - "payed": { - "type": "date" - }, - "worcreated": { - "type": "date" - }, - "isConciliate": { - "type": "date" - } -}, -"relations": { - "client": { - "type": "belongsTo", - "model": "Client", - "foreignKey": "clientFk" - }, - "company": { - "type": "belongsTo", - "model": "Company", - "foreignKey": "companyFk" - }, - "worker": { - "type": "belongsTo", - "model": "Worker", - "foreignKey": "workerFk" - }, - "bank": { - "type": "belongsTo", - "model": "Bank", - "foreignKey": "bankFk" - }, - "invoice": { - "type": "belongsTo", - "model": "InvoiceOut", - "foreignKey": "invoiceFk" - } - } + }, + "properties": { + "id": { + "id": true, + "type": "Number", + "description": "Identifier" + }, + "amountPaid": { + "type": "Number" + }, + "amountUnpaid": { + "type": "Number" + }, + "payed": { + "type": "date" + }, + "created": { + "type": "date" + }, + "isConciliate": { + "type": "date" + } + }, + "relations": { + "client": { + "type": "belongsTo", + "model": "Client", + "foreignKey": "clientFk" + }, + "company": { + "type": "belongsTo", + "model": "Company", + "foreignKey": "companyFk" + }, + "worker": { + "type": "belongsTo", + "model": "Worker", + "foreignKey": "workerFk" + }, + "bank": { + "type": "belongsTo", + "model": "Bank", + "foreignKey": "bankFk" + }, + "invoice": { + "type": "belongsTo", + "model": "InvoiceOut", + "foreignKey": "invoiceFk" + } + } } \ No newline at end of file diff --git a/services/db/install/changes/1.2-CHECK/06.ACL.sql b/services/db/install/changes/1.2-CHECK/06.ACL.sql index ffb794099..947f7c4a9 100644 --- a/services/db/install/changes/1.2-CHECK/06.ACL.sql +++ b/services/db/install/changes/1.2-CHECK/06.ACL.sql @@ -8,7 +8,8 @@ VALUES (109, 'UserConfig', '*', '*', 'ALLOW', 'ROLE', 'employee'), (110, 'Bank', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), (111, 'ClientLog', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), -(112, 'Defaulter', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); +(112, 'Defaulter', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), +(113, 'ClientRisk', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); UPDATE salix.ACL SET model='ItemTag', property='*', accessType='WRITE', permission='ALLOW', principalType='ROLE', principalId='marketingBoss' WHERE id=52; \ No newline at end of file diff --git a/services/loopback/common/methods/client/summary.js b/services/loopback/common/methods/client/summary.js index 04b4d8579..57d742a13 100644 --- a/services/loopback/common/methods/client/summary.js +++ b/services/loopback/common/methods/client/summary.js @@ -70,11 +70,9 @@ module.exports = Self => { } }, { - relation: 'clientsRisk', + relation: 'clientRisks', scope: { - where: {companyFk: 442}, - fields: ['amount'], - limit: 1 + fields: ['amount', 'companyFk'] } }, { diff --git a/services/loopback/common/models/client.json b/services/loopback/common/models/client.json index 007f027d5..c53b61699 100644 --- a/services/loopback/common/models/client.json +++ b/services/loopback/common/models/client.json @@ -183,7 +183,7 @@ "model": "Defaulter", "foreignKey": "clientFk" }, - "clientsRisk": { + "clientRisks": { "type": "hasMany", "model": "ClientRisk", "foreignKey": "clientFk" From 1b504febb8343226e54d8bc535aca7b767599aa6 Mon Sep 17 00:00:00 2001 From: Gerard Date: Fri, 19 Oct 2018 14:50:15 +0200 Subject: [PATCH 2/3] fixed ACLS --- client/client/src/basic-data/index.html | 5 ++-- .../client/specs/updateBasicData.spec.js | 25 +++++++++++++++---- .../common/methods/client/updateBasicData.js | 13 +++++++--- .../methods/client/updateBillingData.js | 2 +- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/client/client/src/basic-data/index.html b/client/client/src/basic-data/index.html index b4547ba6e..beb4bc745 100644 --- a/client/client/src/basic-data/index.html +++ b/client/client/src/basic-data/index.html @@ -1,4 +1,4 @@ - + + vn-acl="salesAssistant, employee" + acl-conditional-to-employee="{{!$ctrl.client.isTaxDataChecked}}"> {{firstName}} {{name}} { afterAll(async() => { let id = 101; + let ctx = {req: {accessToken: {userId: 1}}}; let validparams = {email: 'BruceWayne@verdnatura.es'}; - await app.models.Client.updateBasicData(validparams, id); + await app.models.Client.updateBasicData(ctx, validparams, id); }); it('should return an error if the params aint valid', async() => { let error; - + let ctx = {req: {accessToken: {userId: 1}}}; let id = 101; let invalidparams = {invalid: 'param for update'}; - await app.models.Client.updateBasicData(invalidparams, id) + await app.models.Client.updateBasicData(ctx, invalidparams, id) + .catch(e => { + error = e; + }); + + expect(error.toString()).toContain(`You don't have enough privileges to do that`); + }); + + it('should return an error if the client has isTaxDataChecked and employee try to change his salesPerson', async() => { + let error; + let ctx = {req: {accessToken: {userId: 1}}}; + let id = 101; + let params = {salesPerson: 3}; + + await app.models.Client.updateBasicData(ctx, params, id) .catch(e => { error = e; }); @@ -29,8 +44,8 @@ describe('Client updateBasicData', () => { expect(client.email).toEqual('BruceWayne@verdnatura.es'); let validparams = {email: 'myNewEmail@myDomain.es'}; - - let result = await app.models.Client.updateBasicData(validparams, id); + let ctx = {req: {accessToken: {userId: 1}}}; + let result = await app.models.Client.updateBasicData(ctx, validparams, id); expect(result.email).toEqual('myNewEmail@myDomain.es'); }); diff --git a/services/loopback/common/methods/client/updateBasicData.js b/services/loopback/common/methods/client/updateBasicData.js index 33721a5c5..bd05fde22 100644 --- a/services/loopback/common/methods/client/updateBasicData.js +++ b/services/loopback/common/methods/client/updateBasicData.js @@ -1,7 +1,7 @@ let UserError = require('../../helpers').UserError; module.exports = Self => { - Self.remoteMethod('updateBasicData', { + Self.remoteMethodCtx('updateBasicData', { description: 'Updates billing data of a client', accessType: 'WRITE', accepts: [{ @@ -28,7 +28,9 @@ module.exports = Self => { } }); - Self.updateBasicData = async(params, id) => { + Self.updateBasicData = async(ctx, params, id) => { + let userId = ctx.req.accessToken.userId; + let validUpdateParams = [ 'contact', 'name', @@ -39,11 +41,14 @@ module.exports = Self => { 'contactChannelFk' ]; + let isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant'); + let client = await Self.app.models.Client.findById(id); + for (const key in params) { - if (validUpdateParams.indexOf(key) === -1) + if (validUpdateParams.indexOf(key) === -1 || key == 'salesPersonFk' && client.isTaxDataChecked && !isSalesAssistant) throw new UserError(`You don't have enough privileges to do that`); } - let client = await Self.app.models.Client.findById(id); + return await client.updateAttributes(params); }; }; diff --git a/services/loopback/common/methods/client/updateBillingData.js b/services/loopback/common/methods/client/updateBillingData.js index c361807ad..21f20e77a 100644 --- a/services/loopback/common/methods/client/updateBillingData.js +++ b/services/loopback/common/methods/client/updateBillingData.js @@ -45,7 +45,7 @@ module.exports = Self => { let isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant'); let client = await Self.app.models.Client.findOne({where: {id: id}}); - if (!isSalesAssistant) + if (!isSalesAssistant && client.isTaxDataChecked) throw new UserError(`You don't have enough privileges to do that`); return client.updateAttributes(data); From 7bbda50901c499b4789921c34834d0b6ca3fc7c3 Mon Sep 17 00:00:00 2001 From: Gerard Date: Fri, 19 Oct 2018 14:54:45 +0200 Subject: [PATCH 3/3] fixed typo --- services/loopback/common/methods/client/updateBillingData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/loopback/common/methods/client/updateBillingData.js b/services/loopback/common/methods/client/updateBillingData.js index 21f20e77a..c361807ad 100644 --- a/services/loopback/common/methods/client/updateBillingData.js +++ b/services/loopback/common/methods/client/updateBillingData.js @@ -45,7 +45,7 @@ module.exports = Self => { let isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant'); let client = await Self.app.models.Client.findOne({where: {id: id}}); - if (!isSalesAssistant && client.isTaxDataChecked) + if (!isSalesAssistant) throw new UserError(`You don't have enough privileges to do that`); return client.updateAttributes(data);