This commit is contained in:
Juan Ferrer 2018-12-20 14:37:34 +01:00
commit b84d94e3a4
28 changed files with 156 additions and 125 deletions

View File

@ -189,7 +189,7 @@
"url": "/index", "url": "/index",
"state": "client.card.risk.index", "state": "client.card.risk.index",
"component": "vn-client-risk-index", "component": "vn-client-risk-index",
"description": "Risk", "description": "Balance",
"params": { "params": {
"client": "$ctrl.client" "client": "$ctrl.client"
} }

View File

@ -16,12 +16,14 @@
url="/client/api/AddressObservations" url="/client/api/AddressObservations"
fields="['id', 'addressFk', 'observationTypeFk', 'description']" fields="['id', 'addressFk', 'observationTypeFk', 'description']"
link="{addressFk: $ctrl.$stateParams.addressId}" link="{addressFk: $ctrl.$stateParams.addressId}"
data="observations"> data="observations"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
url="/client/api/ObservationTypes" url="/client/api/ObservationTypes"
fields="['id', 'description']" fields="['id', 'description']"
data="types"> data="types"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<form name="form" ng-submit="$ctrl.submit()" compact> <form name="form" ng-submit="$ctrl.submit()" compact>
<vn-card pad-large> <vn-card pad-large>

View File

@ -3,7 +3,8 @@
url="/client/api/Addresses" url="/client/api/Addresses"
filter="::$ctrl.filter" filter="::$ctrl.filter"
link="{clientFk: $ctrl.$stateParams.id}" link="{clientFk: $ctrl.$stateParams.id}"
data="addresses"> data="addresses"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-vertical> <vn-vertical>

View File

@ -3,7 +3,8 @@
url="/client/api/ClientContacts" url="/client/api/ClientContacts"
fields="['id', 'name', 'phone', 'clientFk']" fields="['id', 'name', 'phone', 'clientFk']"
link="{clientFk: $ctrl.$stateParams.id}" link="{clientFk: $ctrl.$stateParams.id}"
data="contacts"> data="contacts"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"

View File

@ -3,7 +3,8 @@
url="/client/api/clientObservations" url="/client/api/clientObservations"
filter="{order: 'created DESC'}" filter="{order: 'created DESC'}"
link="{clientFk: $ctrl.$stateParams.id}" link="{clientFk: $ctrl.$stateParams.id}"
data="notes"> data="notes"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-vertical compact> <vn-vertical compact>

View File

@ -15,7 +15,7 @@
<vn-card pad-large> <vn-card pad-large>
<vn-horizontal> <vn-horizontal>
<vn-one> <vn-one>
<vn-title>Risk</vn-title> <vn-title>Balance</vn-title>
</vn-one> </vn-one>
<vn-one> <vn-one>
<vn-autocomplete vn-one <vn-autocomplete vn-one

View File

@ -61,7 +61,6 @@ export default class Autocomplete extends Input {
set url(value) { set url(value) {
this.dropDownAssign({url: value}); this.dropDownAssign({url: value});
this.refreshSelection();
} }
dropDownAssign(props) { dropDownAssign(props) {

View File

@ -47,14 +47,6 @@ describe('Component vnAutocomplete', () => {
expect(controller.selection).toEqual(data); expect(controller.selection).toEqual(data);
}); });
it(`should perform a query if the item id isn't present in the data property`, inject($httpBackend => {
$httpBackend.whenGET(/testUrl.*/).respond([data]);
controller.url = 'testUrl';
$httpBackend.flush();
expect(controller.selection).toEqual(data);
}));
it(`should set selection to null when can't find an existing item in the data property`, () => { it(`should set selection to null when can't find an existing item in the data property`, () => {
expect(controller.selection).toEqual(null); expect(controller.selection).toEqual(null);
}); });

View File

@ -13,7 +13,7 @@ export default class CrudModel extends ModelProxy {
this.$http = $http; this.$http = $http;
this.$q = $q; this.$q = $q;
this.primaryKey = 'id'; this.primaryKey = 'id';
this.autoLoad = true; this.autoLoad = false;
} }
$onInit() { $onInit() {

View File

@ -122,4 +122,22 @@ vn-table {
} }
} }
} }
vn-autocomplete {
div.mdl-textfield {
padding: 0px !important;
}
label.mdl-textfield__label:after {
bottom: 0;
}
div.icons {
display: none !important;
}
}
vn-textfield {
max-width: 100px;
float: right;
margin: 0!important;
}
} }

View File

@ -3,7 +3,8 @@
url="/item/api/ItemBarcodes" url="/item/api/ItemBarcodes"
fields="['id', 'itemFk', 'code']" fields="['id', 'itemFk', 'code']"
link="{itemFk: $ctrl.$stateParams.id}" link="{itemFk: $ctrl.$stateParams.id}"
data="barcodes"> data="barcodes"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"

View File

@ -3,7 +3,8 @@
url="/item/api/ItemNiches" url="/item/api/ItemNiches"
fields="['id', 'itemFk', 'warehouseFk', 'code']" fields="['id', 'itemFk', 'warehouseFk', 'code']"
link="{itemFk: $ctrl.$stateParams.id}" link="{itemFk: $ctrl.$stateParams.id}"
data="niches"> data="niches"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"

View File

@ -1,7 +1,7 @@
<vn-card class="summary" compact> <vn-card class="summary">
<vn-vertical pad-medium> <vn-vertical pad-medium>
<vn-horizontal> <vn-horizontal>
<vn-auto margin-medium> <vn-auto margin-medium>
<vn-vertical> <vn-vertical>
<vn-one> <vn-one>
<h5 text-center pad-small-v class="title">{{$ctrl.item.id}}</h5> <h5 text-center pad-small-v class="title">{{$ctrl.item.id}}</h5>

View File

@ -5,22 +5,25 @@
link="{itemFk: $ctrl.$stateParams.id}" link="{itemFk: $ctrl.$stateParams.id}"
include="$ctrl.include" include="$ctrl.include"
order="priority ASC" order="priority ASC"
data="itemTags"> on-row-change="$ctrl.getSourceTable(obj)"
data="$ctrl.itemTags"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
data="itemTags" data="$ctrl.itemTags"
form="form"> form="form">
</vn-watcher> </vn-watcher>
<vn-crud-model <vn-crud-model
url="/item/api/Tags" url="/item/api/Tags"
fields="['id','name','isFree', 'sourceTable']" fields="['id','name','isFree', 'sourceTable']"
data="tags"> data="tags"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<form name="form" ng-submit="$ctrl.onSubmit()" compact> <form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large> <vn-card pad-large>
<vn-title>Tags</vn-title> <vn-title>Tags</vn-title>
<vn-horizontal ng-repeat="itemTag in itemTags"> <vn-horizontal ng-repeat="itemTag in $ctrl.itemTags">
<vn-autocomplete <vn-autocomplete
vn-one vn-one
vn-id="tag" vn-id="tag"
@ -44,12 +47,12 @@
<vn-autocomplete <vn-autocomplete
ng-show="tag.selection.isFree === false" ng-show="tag.selection.isFree === false"
vn-three vn-three
url="{{$ctrl.getSourceTable(tag.selection)}}" url="{{$ctrl.sourceTables[itemTag.id].url}}"
search-function="{name: {regexp: $search}}" search-function="{name: {regexp: $search}}"
label="Value" label="Value"
field="itemTag.value" field="itemTag.value"
show-field="name" show-field="{{$ctrl.sourceTables[itemTag.id].field}}"
value-field="name" value-field="{{$ctrl.sourceTables[itemTag.id].field}}"
vn-acl="buyer"> vn-acl="buyer">
</vn-autocomplete> </vn-autocomplete>
<vn-textfield <vn-textfield

View File

@ -10,6 +10,40 @@ class Controller {
fields: ['id', 'name', 'isFree', 'sourceTable'] fields: ['id', 'name', 'isFree', 'sourceTable']
} }
}; };
this.sourceTables = {};
}
set itemTags(value) {
if (value) {
value.forEach(tag => {
this.getSourceTable(tag);
});
this._itemTags = value;
}
}
get itemTags() {
return this._itemTags;
}
getSourceTable(obj) {
let sourceTable;
this.sourceTables[obj.id] = {};
let tag = obj.tag;
if (!tag || !tag.sourceTable && (tag.isFree === true || tag.isFree === undefined))
sourceTable = null;
else if (tag.sourceTable) {
sourceTable = '/api/' + tag.sourceTable.charAt(0).toUpperCase() +
tag.sourceTable.substring(1) + 's';
this.sourceTables[obj.id].field = 'name';
} else {
sourceTable = `/api/ItemTags/filterItemTags/${tag.id}`;
this.sourceTables[obj.id].field = 'value';
}
this.sourceTables[obj.id].url = sourceTable;
} }
add() { add() {
@ -28,16 +62,6 @@ class Controller {
return max + 1; return max + 1;
} }
getSourceTable(selection) {
if (!selection || selection.isFree === true)
return null;
if (selection.sourceTable) {
return '/api/' + selection.sourceTable.charAt(0).toUpperCase() +
selection.sourceTable.substring(1) + 's';
} else if (selection.sourceTable == null)
return `/api/ItemTags/filterItemTags/${selection.id}`;
}
onSubmit() { onSubmit() {
this.$scope.watcher.check(); this.$scope.watcher.check();
this.$scope.model.save().then(() => { this.$scope.model.save().then(() => {

View File

@ -19,6 +19,46 @@ describe('Item', () => {
controller = $componentController('vnItemTags', {$scope}); controller = $componentController('vnItemTags', {$scope});
})); }));
describe('itemTags setter', () => {
it('should call getSourceTable one time for each element in the value array', () => {
spyOn(controller, 'getSourceTable');
let itemTags = [
{id: 1},
{id: 2},
{id: 3},
{id: 4}
];
controller.itemTags = itemTags;
expect(controller.getSourceTable.calls.count()).toEqual(4);
expect(controller.itemTags).toEqual(itemTags);
});
});
describe('getSourceTable', () => {
it('should return null when the property isFree equals true', () => {
let tag = {id: 1};
controller.getSourceTable(tag);
expect(controller.sourceTables[1].url).toBe(null);
});
it('should return the route of the model in loopback with the first char of the string uppercase and adding a s', () => {
let tag = {id: 1, tag: {sourceTable: 'ink'}};
controller.getSourceTable(tag);
expect(controller.sourceTables[1].url).toBe('/api/Inks');
});
it('should return the route filteritemtags with the id of the selection', () => {
let tag = {id: 1, tag: {id: 3, sourceTable: null, isFree: false}};
controller.getSourceTable(tag);
expect(controller.sourceTables[1].url).toBe('/api/ItemTags/filterItemTags/3');
});
});
describe('getHighestPriority', () => { describe('getHighestPriority', () => {
it('should return the highest priority value + 1 from the array', () => { it('should return the highest priority value + 1 from the array', () => {
let result = controller.getHighestPriority(); let result = controller.getHighestPriority();
@ -33,28 +73,5 @@ describe('Item', () => {
expect(result).toEqual(1); expect(result).toEqual(1);
}); });
}); });
describe('getSourceTable', () => {
it('should return null when the property isFree equals true', () => {
let selection = {isFree: true};
let result = controller.getSourceTable(selection);
expect(result).toBe(null);
});
it('should return the route of the model in loopback with the first char of the string uppercase and adding a s', () => {
let selection = {sourceTable: "ink"};
let result = controller.getSourceTable(selection);
expect(result).toBe("/api/Inks");
});
it('should return the route filteritemtags with the id of the selection', () => {
let selection = {id: 3, sourceTable: null, isFree: false};
let result = controller.getSourceTable(selection);
expect(result).toBe("/api/ItemTags/filterItemTags/3");
});
});
}); });
}); });

View File

@ -1,7 +1,8 @@
<vn-crud-model <vn-crud-model
url="/item/api/TaxClasses" url="/item/api/TaxClasses"
fields="['id', 'description', 'code']" fields="['id', 'description', 'code']"
data="classes"> data="classes"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<form name="form" ng-submit="$ctrl.submit()" compact> <form name="form" ng-submit="$ctrl.submit()" compact>
<vn-card pad-large> <vn-card pad-large>

View File

@ -3,7 +3,8 @@
url="/ticket/api/Sales" url="/ticket/api/Sales"
link="{ticketFk: $ctrl.$stateParams.id}" link="{ticketFk: $ctrl.$stateParams.id}"
filter="::$ctrl.filter" filter="::$ctrl.filter"
data="components"> data="components"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-vertical> <vn-vertical>
<vn-card pad-large> <vn-card pad-large>

View File

@ -3,11 +3,13 @@
url="/ticket/api/TicketObservations" url="/ticket/api/TicketObservations"
fields="['id', 'ticketFk', 'observationTypeFk', 'description']" fields="['id', 'ticketFk', 'observationTypeFk', 'description']"
link="{ticketFk: $ctrl.$stateParams.id}" link="{ticketFk: $ctrl.$stateParams.id}"
data="observations"> data="observations"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
url="/ticket/api/ObservationTypes" url="/ticket/api/ObservationTypes"
data="observationTypes"> data="observationTypes"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"

View File

@ -3,7 +3,8 @@
url="/ticket/api/TicketPackagings" url="/ticket/api/TicketPackagings"
fields="['id', 'ticketFk', 'packagingFk', 'quantity', 'created']" fields="['id', 'ticketFk', 'packagingFk', 'quantity', 'created']"
link="{ticketFk: $ctrl.$stateParams.id}" link="{ticketFk: $ctrl.$stateParams.id}"
data="packages" on-data-change="$ctrl.onDataChange()"> data="packages" on-data-change="$ctrl.onDataChange()"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"

View File

@ -4,7 +4,8 @@
link="{ticketFk: $ctrl.$stateParams.id}" link="{ticketFk: $ctrl.$stateParams.id}"
filter="::$ctrl.filter" filter="::$ctrl.filter"
limit="20" limit="20"
data="sales"> data="sales"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-vertical> <vn-vertical>

View File

@ -1,5 +1,4 @@
import ngModule from '../../module'; import ngModule from '../../module';
import './style.scss';
class Controller { class Controller {
constructor($stateParams, $scope) { constructor($stateParams, $scope) {

View File

@ -1,23 +0,0 @@
vn-ticket-request-index {
vn-textfield {
margin: 0!important;
max-width: 150px;
}
vn-autocomplete {
div.mdl-textfield {
padding: 0px !important;
}
label.mdl-textfield__label:after {
bottom: 0;
}
div.icons {
display: none !important;
}
vn-drop-down {
vn-textfield {
max-width: initial !important
}
}
}
}

View File

@ -80,14 +80,6 @@ vn-ticket-sale {
} }
vn-table { vn-table {
vn-textfield {
max-width: 100px;
float: right;
margin: 0!important;
input {
text-align: right;
}
}
img { img {
border-radius: 50%; border-radius: 50%;
max-width: 50px; max-width: 50px;
@ -102,12 +94,4 @@ vn-ticket-sale {
margin-top: 1em; margin-top: 1em;
} }
} }
vn-textfield {
span.filter {
padding-top: 3px;
padding-right: 3px;
color: $main-font-color
}
}
} }

View File

@ -2,7 +2,8 @@
vn-id="model" vn-id="model"
url="/ticket/api/TicketServices" url="/ticket/api/TicketServices"
link="{ticketFk: $ctrl.$stateParams.id}" link="{ticketFk: $ctrl.$stateParams.id}"
data="services" on-data-change="$ctrl.onDataChange()"> data="services"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"

View File

@ -3,15 +3,4 @@ vn-ticket-weekly {
margin: auto; margin: auto;
max-width: 880px; max-width: 880px;
} }
vn-autocomplete {
div.mdl-textfield {
padding: 0px !important;
}
label.mdl-textfield__label:after {
bottom: 0;
}
div.icons {
display: none !important;
}
}
} }

View File

@ -1,3 +1,6 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const mergeFilters = require('../../filter.js').mergeFilters;
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('filterItemTags', { Self.remoteMethod('filterItemTags', {
description: 'Returns the distinct values of a tag property', description: 'Returns the distinct values of a tag property',
@ -8,6 +11,10 @@ module.exports = Self => {
required: true, required: true,
description: 'The foreign key from tag table', description: 'The foreign key from tag table',
http: {source: 'path'} http: {source: 'path'}
}, {
arg: 'filter',
type: 'Object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}], }],
returns: { returns: {
root: true, root: true,
@ -19,8 +26,16 @@ module.exports = Self => {
} }
}); });
Self.filterItemTags = async tagFk => { Self.filterItemTags = async (tagFk, filter) => {
let query = `SELECT DISTINCT(value) AS name FROM vn.itemTag WHERE tagFk = ?`; let conn = Self.dataSource.connector;
return await Self.rawSql(query, [tagFk]); let where = {tagFk: tagFk};
myFilter = mergeFilters(filter, {where});
stmt = new ParameterizedSQL(
`SELECT DISTINCT(value)
FROM itemTag`);
stmt.merge(conn.makeSuffix(myFilter));
return await conn.executeStmt(stmt);
}; };
}; };

View File

@ -1,9 +1,9 @@
const app = require(`${servicesDir}/item/server/server`); const app = require(`${servicesDir}/item/server/server`);
describe('item filterItemTags()', () => { describe('item filterItemTags()', () => {
it('should call the filterItemTags method', async() => { it('should filter ItemTags table', async () => {
let [result] = await app.models.ItemTag.filterItemTags(1); let [result] = await app.models.ItemTag.filterItemTags(1, {});
expect(result.name).toEqual('Blue'); expect(result.value).toEqual('Blue');
}); });
}); });