Merge pull request '3684-agencyTerm_search-panel' (#900) from 3684-agencyTerm_search-panel into dev
gitea/salix/pipeline/head This commit looks good Details

Reviewed-on: #900
Reviewed-by: Joan Sanchez <joan@verdnatura.es>
This commit is contained in:
Joan Sanchez 2022-03-23 10:50:50 +00:00
commit e85c0c53c6
9 changed files with 241 additions and 31 deletions

View File

@ -1,4 +1,6 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; 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 => { module.exports = Self => {
Self.remoteMethodCtx('filter', { Self.remoteMethodCtx('filter', {
@ -9,7 +11,31 @@ module.exports = Self => {
arg: 'filter', arg: 'filter',
type: 'object', type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'} },
{
arg: 'search',
type: 'string',
description: `If it's and integer searchs by invoiceInFk, otherwise it searchs by the supplierName`,
},
{
arg: 'agencyModeFk',
type: 'integer',
description: 'The agency agencyModeFk id',
},
{
arg: 'agencyFk',
type: 'integer',
description: 'The agencyFk id',
},
{
arg: 'from',
type: 'date',
description: 'The from date filter',
},
{
arg: 'to',
type: 'date',
description: 'The to date filter',
} }
], ],
returns: { returns: {
@ -29,6 +55,25 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const where = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
return /^\d+$/.test(value)
? {'invoiceInFk': {inq: value}}
: {'supplierName': {like: `%${value}%`}};
case 'agencyModeFk':
return {'agencyModeFk': value};
case 'agencyFk':
return {'agencyFk': value};
case 'from':
return {'created': {gte: value}};
case 'to':
return {'created': {lte: value}};
}
});
filter = mergeFilters(filter, {where});
const stmts = []; const stmts = [];
const stmt = new ParameterizedSQL( const stmt = new ParameterizedSQL(
`SELECT * `SELECT *
@ -61,7 +106,8 @@ module.exports = Self => {
) a` ) a`
); );
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeWhere(filter.where));
stmt.merge(conn.makePagination(filter));
const agencyTerm = stmts.push(stmt) - 1; const agencyTerm = stmts.push(stmt) - 1;
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');

View File

@ -1,9 +1,12 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
describe('AgencyTerm filter()', () => { describe('AgencyTerm filter()', () => {
const authUserId = 9; const authUserId = 9;
const today = new Date();
today.setHours(2, 0, 0, 0);
it('should return all the tickets matching the filter', async() => { it('should return all results matching the filter', async() => {
const tx = await models.AgencyTerm.beginTransaction({}); const tx = await models.AgencyTerm.beginTransaction({});
try { try {
@ -23,4 +26,84 @@ describe('AgencyTerm filter()', () => {
throw e; throw e;
} }
}); });
it('should return results matching "search" searching by integer', async() => {
let ctx = {
args: {
search: 1,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(1);
});
it('should return results matching "search" searching by string', async() => {
let ctx = {
args: {
search: 'Plants SL',
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(2);
});
it('should return results matching "from" and "to"', async() => {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const from = new Date();
from.setHours(0, 0, 0, 0);
const to = new Date();
to.setHours(23, 59, 59, 999);
const ctx = {
args: {
from: from,
to: to
}
};
const results = await models.AgencyTerm.filter(ctx, options);
expect(results.length).toBe(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "agencyModeFk"', async() => {
let ctx = {
args: {
agencyModeFk: 1,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(1);
});
it('should return results matching "agencyFk"', async() => {
let ctx = {
args: {
agencyFk: 2,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(2);
});
}); });

View File

@ -1,4 +1,5 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('Route filter()', () => { describe('Route filter()', () => {
let today = new Date(); let today = new Date();
@ -17,29 +18,33 @@ describe('Route filter()', () => {
expect(result[0].id).toEqual(1); expect(result[0].id).toEqual(1);
}); });
// #1428 cuadrar formato de horas it('should return results matching "from" and "to"', async() => {
xit('should return the routes matching "from"', async() => { const tx = await models.Buy.beginTransaction({});
let ctx = { const options = {transaction: tx};
args: {
from: today,
}
};
let result = await app.models.Route.filter(ctx); try {
const from = new Date();
from.setHours(0, 0, 0, 0);
expect(result.length).toEqual(7); const to = new Date();
}); to.setHours(23, 59, 59, 999);
it('should return the routes matching "to"', async() => { const ctx = {
let ctx = { args: {
args: { from: from,
to: today, to: to
} }
}; };
let result = await app.models.Route.filter(ctx); const results = await models.Route.filter(ctx, options);
expect(result.length).toEqual(7); expect(results.length).toBe(7);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return the routes matching "m3"', async() => { it('should return the routes matching "m3"', async() => {

View File

@ -0,0 +1,47 @@
<div class="search-panel">
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
<vn-horizontal class="vn-px-lg vn-pt-lg">
<vn-textfield
vn-one
label="General search"
ng-model="filter.search"
vn-focus>
</vn-textfield>
</vn-horizontal>
<vn-horizontal class="vn-px-lg">
<vn-autocomplete vn-one
url="AgencyModes"
label="Agency route"
show-field="name"
value-field="id"
ng-model="filter.agencyModeFk">
</vn-autocomplete>
<vn-autocomplete vn-one
url="Agencies"
label="Agency Agreement"
show-field="name"
value-field="id"
ng-model="filter.agencyFk">
</vn-autocomplete>
</vn-horizontal>
<section class="vn-px-md">
<vn-horizontal class="manifold-panel vn-pa-md">
<vn-date-picker
vn-one
label="From"
ng-model="filter.from"
on-change="$ctrl.from = value">
</vn-date-picker>
<vn-date-picker
vn-one
label="To"
ng-model="filter.to"
on-change="$ctrl.to = value">
</vn-date-picker>
</vn-horizontal>
</section>
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
<vn-submit label="Search"></vn-submit>
</vn-horizontal>
</form>
</div>

View File

@ -0,0 +1,17 @@
import ngModule from '../module';
import SearchPanel from 'core/components/searchbar/search-panel';
class Controller extends SearchPanel {
get filter() {
return this.$.filter;
}
set filter(value = {}) {
this.$.filter = value;
}
}
ngModule.vnComponent('vnAgencyTermSearchPanel', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,2 @@
Search by invoiceIn id or autonomous name: Buscar por id de recibida o por nombre de autónomo
Search autonomous: Buscar autónomos

View File

@ -1,10 +1,19 @@
<vn-crud-model <vn-crud-model
vn-id="model" vn-id="model"
url="AgencyTerms/filter" url="AgencyTerms/filter"
filter="::$ctrl.filter"
data="agencyTerms" data="agencyTerms"
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-portal slot="topbar">
<vn-searchbar
auto-state="false"
panel="vn-agency-term-search-panel"
info="Search by invoiceIn id or autonomous name"
placeholder="Search autonomous"
filter="{}"
model="model">
</vn-searchbar>
</vn-portal>
<vn-card> <vn-card>
<smart-table <smart-table
model="model" model="model"
@ -36,10 +45,10 @@
<th field="created"> <th field="created">
<span translate>Date</span> <span translate>Date</span>
</th> </th>
<th field="agencyFk"> <th field="agencyModeFk">
<span translate>Agency route</span> <span translate>Agency route</span>
</th> </th>
<th field="agencyAgreement"> <th field="agencyFk">
<span translate>Agency Agreement</span> <span translate>Agency Agreement</span>
</th> </th>
<th field="packages"> <th field="packages">

View File

@ -12,19 +12,19 @@ class Controller extends Section {
}, },
columns: [ columns: [
{ {
field: 'agencyFk', field: 'agencyModeFk',
autocomplete: { autocomplete: {
url: 'AgencyModes', url: 'AgencyModes',
showField: 'name', showField: 'name',
valueField: 'name' valueField: 'id'
} }
}, },
{ {
field: 'agencyAgreement', field: 'agencyFk',
autocomplete: { autocomplete: {
url: 'Agencies', url: 'Agencies',
showField: 'name', showField: 'name',
valueField: 'name' valueField: 'id'
} }
}, },
{ {
@ -41,14 +41,14 @@ class Controller extends Section {
exprBuilder(param, value) { exprBuilder(param, value) {
switch (param) { switch (param) {
case 'agencyFk': case 'agencyModeFk':
return {'a.agencyModeName': value}; return {'a.agencyModeFk': value};
case 'supplierFk': case 'supplierFk':
return {'a.supplierName': value}; return {'a.supplierName': value};
case 'routeFk': case 'routeFk':
return {'a.routeFk': value}; return {'a.routeFk': value};
case 'created': case 'created':
case 'agencyAgreement': case 'agencyFk':
case 'packages': case 'packages':
case 'm3': case 'm3':
case 'kmTotal': case 'kmTotal':

View File

@ -13,4 +13,5 @@ import './log';
import './tickets'; import './tickets';
import './agency-term/index'; import './agency-term/index';
import './agency-term/createInvoiceIn'; import './agency-term/createInvoiceIn';
import './agency-term-search-panel';
import './ticket-popup'; import './ticket-popup';