#1356 advanced search refactor
This commit is contained in:
parent
a6fa9f98fb
commit
4e5c6ff882
|
@ -0,0 +1,128 @@
|
|||
|
||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('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: 'search',
|
||||
type: 'String',
|
||||
description: 'Searchs the invoiceOut by id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'clientFk',
|
||||
type: 'Integer',
|
||||
description: 'The client id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'hasPdf',
|
||||
type: 'Boolean',
|
||||
description: 'Whether the the invoiceOut has PDF or not',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'amount',
|
||||
type: 'Number',
|
||||
description: 'The amount filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'min',
|
||||
type: 'Number',
|
||||
description: 'The minimun amount flter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'max',
|
||||
type: 'Number',
|
||||
description: 'The maximun amount flter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'issued',
|
||||
type: 'Date',
|
||||
description: 'The issued date filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'created',
|
||||
type: 'Date',
|
||||
description: 'The created date filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'dued',
|
||||
type: 'Date',
|
||||
description: 'The due date filter',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/filter`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.filter = async(ctx, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {ref: {like: `%${value}%`}};
|
||||
case 'min':
|
||||
return {amount: {gte: value}};
|
||||
case 'max':
|
||||
return {amount: {lte: value}};
|
||||
case 'hasPdf':
|
||||
return {'i.pdf': value};
|
||||
case 'created':
|
||||
return {'i.created': value};
|
||||
case 'amount':
|
||||
case 'clientFk':
|
||||
case 'companyFk':
|
||||
case 'issued':
|
||||
case 'dued':
|
||||
return {[param]: value};
|
||||
}
|
||||
});
|
||||
|
||||
filter = mergeFilters(ctx.args.filter, {where});
|
||||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`SELECT
|
||||
i.id,
|
||||
i.ref,
|
||||
i.issued,
|
||||
i.amount,
|
||||
i.created,
|
||||
i.dued,
|
||||
i.clientFk,
|
||||
i.pdf AS hasPdf,
|
||||
c.socialName AS clientSocialName,
|
||||
co.code AS companyCode
|
||||
FROM invoiceOut i
|
||||
LEFT JOIN client c ON c.id = i.clientFk
|
||||
LEFT JOIN company co ON co.id = i.companyFk`
|
||||
);
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
let itemsIndex = stmts.push(stmt) - 1;
|
||||
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql);
|
||||
return itemsIndex === 0 ? result : result[itemsIndex];
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/invoiceOut/filter')(Self);
|
||||
require('../methods/invoiceOut/summary')(Self);
|
||||
require('../methods/invoiceOut/download')(Self);
|
||||
};
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/api/InvoiceOuts"
|
||||
filter="::$ctrl.filter"
|
||||
url="/api/InvoiceOuts/filter"
|
||||
limit="20"
|
||||
data="invoicesOut"
|
||||
order="issued DESC"
|
||||
auto-load="false">
|
||||
data="invoiceOuts"
|
||||
order="issued DESC">
|
||||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-invoice-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
auto-load="true"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search invoices by reference"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
|
@ -36,7 +32,7 @@
|
|||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<a ng-repeat="invoiceOut in invoicesOut"
|
||||
<a ng-repeat="invoiceOut in invoiceOuts"
|
||||
class="clickable vn-tr searchResult"
|
||||
ui-sref="invoiceOut.card.summary({id: {{::invoiceOut.id}}})">
|
||||
<vn-td>{{::invoiceOut.ref | dashIfEmpty}}</vn-td>
|
||||
|
@ -46,11 +42,11 @@
|
|||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showClientDescriptor($event, invoiceOut.clientFk)">
|
||||
{{::invoiceOut.client.name | dashIfEmpty}}
|
||||
{{::invoiceOut.clientSocialName | dashIfEmpty}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{::invoiceOut.created | dateTime:'dd/MM/yyyy' | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::invoiceOut.company.code | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::invoiceOut.companyCode | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::invoiceOut.dued | dateTime:'dd/MM/yyyy' | dashIfEmpty}}</vn-td>
|
||||
<vn-td>
|
||||
<vn-icon-button
|
||||
|
|
|
@ -5,42 +5,6 @@ export default class Controller {
|
|||
this.accessToken = vnToken.token;
|
||||
this.$ = $scope;
|
||||
this.selectedInvoiceOut = null;
|
||||
|
||||
this.filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'company',
|
||||
scope: {
|
||||
fields: ['code']
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {ref: {like: `%${value}%`}};
|
||||
case 'min':
|
||||
return {amount: {gte: value}};
|
||||
case 'max':
|
||||
return {amount: {lte: value}};
|
||||
case 'hasPdf':
|
||||
case 'amount':
|
||||
case 'clientFk':
|
||||
case 'companyFk':
|
||||
case 'issued':
|
||||
case 'created':
|
||||
case 'dued':
|
||||
return {[param]: value};
|
||||
}
|
||||
}
|
||||
|
||||
showClientDescriptor(event, clientFk) {
|
||||
|
@ -68,6 +32,13 @@ export default class Controller {
|
|||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
onSearch(params) {
|
||||
if (params)
|
||||
this.$.model.applyFilter(null, params);
|
||||
else
|
||||
this.$.model.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', 'vnToken'];
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-two>
|
||||
<h4 translate>Desglose impositivo</h4>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<h4 translate>Desglose impositivo</h4>
|
||||
<vn-tr>
|
||||
<vn-th>Type</vn-th>
|
||||
<vn-th>Taxable base</vn-th>
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
Driver: Conductor
|
||||
Vehicle: Vehículo
|
||||
Packages: Bultos
|
||||
Starting time: H. Inicio
|
||||
Finishing time: H. Fin
|
||||
Km Start: Km de inicio
|
||||
Km End: Km de fin
|
||||
PC: CP
|
||||
Date: Fecha
|
||||
Created: Creada
|
||||
Due: Vencimiento
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import "variables";
|
||||
|
||||
|
||||
vn-route-summary .summary {
|
||||
vn-invoice-out-summary .summary {
|
||||
max-width: $width-large;
|
||||
|
||||
vn-icon[icon=insert_drive_file]{
|
||||
|
|
|
@ -41,7 +41,7 @@ module.exports = Self => {
|
|||
}, {
|
||||
arg: 'hasVisible',
|
||||
type: 'Boolean',
|
||||
description: 'Whether the the item has o not visible',
|
||||
description: 'Whether the the item has visible or not',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'isActive',
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
|
||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('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: 'search',
|
||||
type: 'String',
|
||||
description: 'Searchs the route by id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'workerFk',
|
||||
type: 'Integer',
|
||||
description: 'The worker id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'agencyModeFk',
|
||||
type: 'Integer',
|
||||
description: 'The agencyMode id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'to',
|
||||
type: 'Date',
|
||||
description: 'The to date filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'from',
|
||||
type: 'Date',
|
||||
description: 'The to date filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'vehicleFk',
|
||||
type: 'Integer',
|
||||
description: 'The vehicle id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'm3',
|
||||
type: 'Number',
|
||||
description: 'The m3 filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'description',
|
||||
type: 'String',
|
||||
description: 'The description filter',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/filter`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.filter = async(ctx, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {'r.id': value};
|
||||
case 'from':
|
||||
return {'r.created': {gte: value}};
|
||||
case 'to':
|
||||
return {'r.created': {lte: value}};
|
||||
case 'm3':
|
||||
return {'r.m3': value};
|
||||
case 'description':
|
||||
return {'r.description': {like: `%${value}%`}};
|
||||
case 'workerFk':
|
||||
case 'vehicleFk':
|
||||
case 'agencyModeFk':
|
||||
return {[param]: value};
|
||||
}
|
||||
});
|
||||
|
||||
filter = mergeFilters(ctx.args.filter, {where});
|
||||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`SELECT
|
||||
r.id,
|
||||
r.workerFk,
|
||||
r.created,
|
||||
r.vehicleFk,
|
||||
r.agencyModeFk,
|
||||
r.time,
|
||||
r.isOk,
|
||||
r.kmStart,
|
||||
r.kmEnd,
|
||||
r.started,
|
||||
r.finished,
|
||||
r.gestdocFk,
|
||||
r.cost,
|
||||
r.m3,
|
||||
r.description,
|
||||
am.name agencyName,
|
||||
u.nickname AS workerNickname,
|
||||
v.numberPlate AS vehiclePlateNumber
|
||||
FROM route r
|
||||
LEFT JOIN agencyMode am ON am.id = r.agencyModeFk
|
||||
LEFT JOIN vehicle v ON v.id = r.vehicleFk
|
||||
LEFT JOIN worker w ON w.id = r.workerFk
|
||||
LEFT JOIN account.user u ON u.id = w.userFk`
|
||||
);
|
||||
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
let itemsIndex = stmts.push(stmt) - 1;
|
||||
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql);
|
||||
return itemsIndex === 0 ? result : result[itemsIndex];
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/route/filter')(Self);
|
||||
require('../methods/route/summary')(Self);
|
||||
require('../methods/route/getTickets')(Self);
|
||||
require('../methods/route/guessPriority')(Self);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/api/Routes"
|
||||
filter="::$ctrl.filter"
|
||||
url="/api/Routes/filter"
|
||||
limit="20"
|
||||
data="routes"
|
||||
order="created DESC">
|
||||
|
@ -11,9 +10,7 @@
|
|||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-route-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
auto-load="true"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search routes by id"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
|
@ -41,12 +38,12 @@
|
|||
<vn-td expand>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, route.worker.id)">
|
||||
{{::route.worker.user.nickname}}
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, route.workerFk)">
|
||||
{{::route.workerNickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{::route.agencyMode.name | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::route.vehicle.numberPlate | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::route.agencyName | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::route.vehiclePlateNumber | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::route.created | dateTime:'dd/MM/yyyy' | dashIfEmpty}}</vn-td>
|
||||
<vn-td number>{{::route.m3 | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::route.description | dashIfEmpty}}</vn-td>
|
||||
|
@ -72,7 +69,7 @@
|
|||
</vn-dialog>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor"
|
||||
user-id="$ctrl.selectedWorker">
|
||||
worker-fk="$ctrl.selectedWorker">
|
||||
</vn-worker-descriptor-popover>
|
||||
<a ui-sref="route.create" vn-tooltip="New route" vn-bind="+" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
|
|
|
@ -4,61 +4,15 @@ export default class Controller {
|
|||
constructor($scope, vnToken) {
|
||||
this.accessToken = vnToken.token;
|
||||
this.$ = $scope;
|
||||
|
||||
this.filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'agencyMode',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'vehicle',
|
||||
scope: {
|
||||
fields: ['numberPlate']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'worker',
|
||||
scope: {
|
||||
fields: ['userFk'],
|
||||
include: {
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['nickname']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {id: value};
|
||||
case 'from':
|
||||
return {created: {gte: value}};
|
||||
case 'to':
|
||||
return {created: {lte: value}};
|
||||
case 'workerFk':
|
||||
case 'vehicleFk':
|
||||
case 'agencyModeFk':
|
||||
case 'm3':
|
||||
case 'description':
|
||||
return {[param]: value};
|
||||
}
|
||||
}
|
||||
|
||||
showWorkerDescriptor(event, userId) {
|
||||
showWorkerDescriptor(event, workerFk) {
|
||||
if (event.defaultPrevented) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
this.selectedWorker = userId;
|
||||
this.selectedWorker = workerFk;
|
||||
this.$.workerDescriptor.parent = event.target;
|
||||
this.$.workerDescriptor.show();
|
||||
}
|
||||
|
@ -69,6 +23,13 @@ export default class Controller {
|
|||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
onSearch(params) {
|
||||
if (params)
|
||||
this.$.model.applyFilter(null, params);
|
||||
else
|
||||
this.$.model.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', 'vnToken'];
|
||||
|
|
Loading…
Reference in New Issue