# 702 Client.risk

This commit is contained in:
Javi Gallego 2018-10-19 08:40:32 +02:00
parent 76a2eda6e0
commit c6c40de2fc
19 changed files with 309 additions and 144 deletions

View File

@ -205,14 +205,32 @@
} }
}, },
{ {
"url": "/invoice", "url": "/risk",
"state": "client.card.invoice", "abstract": true,
"component": "vn-client-invoice", "state": "client.card.risk",
"description": "Invoices", "component": "ui-view"
},
{
"url": "/index",
"state": "client.card.risk.index",
"component": "vn-client-risk-index",
"description": "Risk",
"params": {
"client": "$ctrl.client"
},
"menu": { "menu": {
"icon": "icon-invoices" "icon": "icon-invoices"
} }
}, },
{
"url": "/create",
"state": "client.card.risk.create",
"component": "vn-client-risk-create",
"description": "New payment",
"params": {
"client": "$ctrl.client"
}
},
{ {
"url": "/recovery", "url": "/recovery",
"abstract": true, "abstract": true,

View File

@ -19,8 +19,9 @@ import './credit/index';
import './credit/create'; import './credit/create';
import './greuge/index'; import './greuge/index';
import './greuge/create'; import './greuge/create';
import './risk/index';
import './risk/create';
import './mandate'; import './mandate';
import './invoice';
import './summary'; import './summary';
import './recovery/index'; import './recovery/index';
import './recovery/create'; import './recovery/create';

View File

@ -1,42 +0,0 @@
<vn-crud-model
vn-id="model"
url="/client/api/InvoiceOuts"
filter="{}"
link="{clientFk: $ctrl.$stateParams.id}"
limit="20"
data="invoices">
</vn-crud-model>
<vn-vertical>
<vn-card pad-large>
<vn-vertical>
<vn-title>Invoices</vn-title>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="ref" default-order="DESC">Reference</vn-th>
<vn-th field="issued">Issue date</vn-th>
<vn-th field="dued">Due date</vn-th>
<vn-th field="amount">Amount</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="invoice in invoices">
<vn-td>{{::invoice.ref}}</vn-td>
<vn-td>{{::invoice.issued | date:'dd/MM/yyyy' }}</vn-td>
<vn-td>{{::invoice.dued | date:'dd/MM/yyyy' }}</vn-td>
<vn-td>{{::invoice.amount | currency:' €': 2}}</vn-td>
</vn-tr>
</vn-tbody>
<vn-empty-rows ng-if="model.data.length === 0" translate>
No results
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
</vn-card>
</vn-vertical>

View File

@ -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
});

View File

@ -1,4 +0,0 @@
Reference: Referencia
Issue date: Fecha de emisión
Due date: Vencimiento
Amount: Total

View File

@ -0,0 +1,79 @@
<vn-crud-model
vn-id="model"
url="/client/api/receipts/filter"
params= "{
params: {
clientFk:$ctrl.$stateParams.id
}
}"
limit="20"
data="risks">
</vn-crud-model>
<vn-crud-model
vn-id="riskModel"
url="/client/api/ClientRisks"
filter="::$ctrl.filter"
data="riskTotal">
</vn-crud-model>
<vn-vertical>
<vn-card pad-large>
<vn-horizontal>
<vn-title vn-two>Risk</vn-title>
<div class="totalBox" ng-if="riskTotal.length">
<h6> Total por empresa</h6>
<vn-auto ng-repeat="riskByCompany in riskTotal">
<vn-label-value label={{riskByCompany.company.code}}
value="{{riskByCompany.amount | currency: ' €': 2}}">
</vn-label-value>
</vn-auto>
</div>
</vn-horizontal>
<vn-vertical>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th>Date</vn-th>
<vn-th>Creation date</vn-th>
<vn-th>Employee</vn-th>
<vn-th>Reference</vn-th>
<vn-th>Bank</vn-th>
<vn-th>Debit</vn-th>
<vn-th>Credit</vn-th>
<vn-th>Conciliated</vn-th>
<vn-th>Company</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="risk in risks">
<vn-td>{{::risk.payed | dateTime:'dd/MM/yyyy'}}</vn-td>
<vn-td>{{::risk.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
<vn-td>{{::risk.firstName}} {{::risk.name}}</vn-td>
<vn-td>{{::risk.reference}}</vn-td>
<vn-td>{{::risk.bankFk}}</vn-td>
<vn-td>{{::risk.debit | currency: ' €': 2}}</vn-td>
<vn-td>{{::risk.credit | currency: ' €': 2}}</vn-td>
<vn-td>
<vn-check
field="risk.isConciliate"
disabled="true">
</vn-check>
</vn-td>
<vn-td>{{::risk.company}}</vn-td>
</vn-tr>
</vn-tbody>
<vn-empty-rows ng-if="model.data.length === 0" translate>
No results
</vn-empty-rows>
</vn-table>
</vn-vertical>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
</vn-card>
</vn-vertical>
<a ui-sref="client.card.risk.create" vn-tooltip="New payment"
vn-bind="+" fixed-bottom-right>
<vn-float-button vn-acl="administrative" vn-acl-action="remove" icon="add"></vn-float-button>
</a>

View File

@ -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
});

View File

@ -0,0 +1,6 @@
Creation date: Fecha de creación
Reference: Referencia
Bank: Caja
Debit: Debe
Conciliated: Conciliado
New payment: Añadir pago

View File

@ -190,7 +190,7 @@
value="{{$ctrl.summary.creditInsurance | currency:'€ ':2}}"> value="{{$ctrl.summary.creditInsurance | currency:'€ ':2}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Balance" <vn-label-value label="Balance"
value="{{$ctrl.summary.clientRisks[0].amount | currency:'€ ':2}}"> value="{{$ctrl.summary.sumRisk | currency:'€ ':2}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Balance due" <vn-label-value label="Balance due"
value="{{$ctrl.summary.defaulters[0].amount | currency:'€ ':2}}" value="{{$ctrl.summary.defaulters[0].amount | currency:'€ ':2}}"

View File

@ -16,9 +16,19 @@ class Controller {
if (res.data.classifications.length) if (res.data.classifications.length)
this.grade = res.data.classifications[0].insurances[0].grade; this.grade = res.data.classifications[0].insurances[0].grade;
this.summary.sumRisk = this.sumRisk();
} }
}); });
} }
sumRisk() {
let total = 0;
this.summary.clientRisks.forEach(risk => {
total += risk.amount;
});
return total;
}
} }
Controller.$inject = ['$http']; Controller.$inject = ['$http'];

View File

@ -21,32 +21,34 @@ describe('Client', () => {
describe('$onChanges()', () => { describe('$onChanges()', () => {
it('should perform a GET query and define summary property', () => { it('should perform a GET query and define summary property', () => {
let res = {name: 'Superman', classifications: []}; let res = {name: 'Superman', classifications: []};
spyOn(controller, "sumRisk");
$httpBackend.when('GET', `/client/api/Clients/101/summary`).respond(200, res); $httpBackend.when('GET', `/client/api/Clients/101/summary`).respond(200, res);
$httpBackend.expect('GET', `/client/api/Clients/101/summary`); $httpBackend.expect('GET', `/client/api/Clients/101/summary`);
controller.$onChanges(); controller.$onChanges();
$httpBackend.flush(); $httpBackend.flush();
expect(controller.summary).toBeDefined(); expect(controller.summary).toBeDefined();
expect(controller.summary.name).toEqual('Superman'); expect(controller.summary.name).toEqual('Superman');
expect(controller.grade).toBeUndefined();
}); });
});
it('should perform a GET query and define summary and grade property', () => { describe('sumRisk()', () => {
let res = { it('should sum property amount of an array', () => {
name: 'Superman', controller.summary = {
classifications: [{insurances: [ clientRisks: [{
{id: 1, grade: 1} companyFk: 442,
]}] amount: 100
}; },
$httpBackend.when('GET', `/client/api/Clients/101/summary`).respond(200, res); {
$httpBackend.expect('GET', `/client/api/Clients/101/summary`); companyFk: 567,
controller.$onChanges(); amount: 200
$httpBackend.flush(); }]};
expect(controller.summary).toBeDefined(); let result = controller.sumRisk();
expect(controller.summary.name).toEqual('Superman');
expect(controller.grade).toBeDefined(); expect(result).toEqual(300);
expect(controller.grade).toEqual(1);
}); });
}); });
}); });

View File

@ -16,4 +16,4 @@
"dependencies": { "dependencies": {
"vn-loopback": "file:../loopback" "vn-loopback": "file:../loopback"
} }
} }

View File

@ -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);
};
};

View File

@ -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);
});
});

View File

@ -0,0 +1,3 @@
module.exports = function(Self) {
require('../methods/receipt/filter')(Self);
};

View File

@ -5,59 +5,54 @@
"mysql": { "mysql": {
"table": "receipt" "table": "receipt"
} }
}, },
"properties": { "properties": {
"id": { "id": {
"id": true, "id": true,
"type": "Number", "type": "Number",
"description": "Identifier" "description": "Identifier"
}, },
"ref": { "amountPaid": {
"id": true, "type": "Number"
"type": "String", },
"required": true "amountUnpaid": {
}, "type": "Number"
"amountPaid": { },
"type": "Number" "payed": {
}, "type": "date"
"amountUnpaid": { },
"type": "Number" "created": {
}, "type": "date"
"payed": { },
"type": "date" "isConciliate": {
}, "type": "date"
"worcreated": { }
"type": "date" },
}, "relations": {
"isConciliate": { "client": {
"type": "date" "type": "belongsTo",
} "model": "Client",
}, "foreignKey": "clientFk"
"relations": { },
"client": { "company": {
"type": "belongsTo", "type": "belongsTo",
"model": "Client", "model": "Company",
"foreignKey": "clientFk" "foreignKey": "companyFk"
}, },
"company": { "worker": {
"type": "belongsTo", "type": "belongsTo",
"model": "Company", "model": "Worker",
"foreignKey": "companyFk" "foreignKey": "workerFk"
}, },
"worker": { "bank": {
"type": "belongsTo", "type": "belongsTo",
"model": "Worker", "model": "Bank",
"foreignKey": "workerFk" "foreignKey": "bankFk"
}, },
"bank": { "invoice": {
"type": "belongsTo", "type": "belongsTo",
"model": "Bank", "model": "InvoiceOut",
"foreignKey": "bankFk" "foreignKey": "invoiceFk"
}, }
"invoice": { }
"type": "belongsTo",
"model": "InvoiceOut",
"foreignKey": "invoiceFk"
}
}
} }

View File

@ -8,7 +8,8 @@ VALUES
(109, 'UserConfig', '*', '*', 'ALLOW', 'ROLE', 'employee'), (109, 'UserConfig', '*', '*', 'ALLOW', 'ROLE', 'employee'),
(110, 'Bank', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), (110, 'Bank', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
(111, 'ClientLog', '*', '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 UPDATE salix.ACL
SET model='ItemTag', property='*', accessType='WRITE', permission='ALLOW', principalType='ROLE', principalId='marketingBoss' SET model='ItemTag', property='*', accessType='WRITE', permission='ALLOW', principalType='ROLE', principalId='marketingBoss'
WHERE id=52; WHERE id=52;

View File

@ -70,11 +70,9 @@ module.exports = Self => {
} }
}, },
{ {
relation: 'clientsRisk', relation: 'clientRisks',
scope: { scope: {
where: {companyFk: 442}, fields: ['amount', 'companyFk']
fields: ['amount'],
limit: 1
} }
}, },
{ {

View File

@ -183,7 +183,7 @@
"model": "Defaulter", "model": "Defaulter",
"foreignKey": "clientFk" "foreignKey": "clientFk"
}, },
"clientsRisk": { "clientRisks": {
"type": "hasMany", "type": "hasMany",
"model": "ClientRisk", "model": "ClientRisk",
"foreignKey": "clientFk" "foreignKey": "clientFk"