Merge branch 'dev' of https://git.verdnatura.es/salix into dev
This commit is contained in:
commit
1b4c97fa6a
|
@ -75,20 +75,20 @@
|
|||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
margin-large-right
|
||||
label="Description"
|
||||
model="observation.description"
|
||||
rule="addressObservation.description">
|
||||
</vn-textfield>
|
||||
<vn-auto pad-medium-top>
|
||||
<vn-icon
|
||||
pointer
|
||||
<vn-none>
|
||||
<vn-icon-button
|
||||
medium-grey
|
||||
margin-medium-v
|
||||
vn-tooltip="Remove note"
|
||||
icon="remove_circle_outline"
|
||||
ng-click="$ctrl.removeObservation($index)">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
ng-click="$ctrl.removeObservation($index)"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
</div>
|
||||
<vn-icon-button
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<vn-title vn-one>Addresses</vn-title>
|
||||
<vn-horizontal ng-repeat="address in index.model.items track by address.id" class="pad-medium-top" style="align-items: center;">
|
||||
<vn-one border-radius class="pad-small border-solid"
|
||||
ng-class="{'bg-dark-item': address.isDefaultAddress,'bg-opacity-item': !address.isActive && !address.isDefaultAddress}">
|
||||
ng-class="{'bg-main': address.isDefaultAddress,'bg-opacity-item': !address.isActive && !address.isDefaultAddress}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none pad-medium-h>
|
||||
<i class="material-icons"
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<vn-card pad-large>
|
||||
<vn-title vn-one>Contract credit insurance</vn-title>
|
||||
<vn-horizontal ng-repeat="classification in $ctrl.classifications track by classification.id" class="pad-medium-top" style="align-items: center;">
|
||||
<vn-one border-radius class="pad-small border-solid" ng-class="{'bg-dark-item': !classification.finished,'bg-opacity-item': classification.finished}">
|
||||
<vn-one border-radius class="pad-small border-solid" ng-class="{'bg-main': !classification.finished,'bg-opacity-item': classification.finished}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none pad-medium-h style="color:#FFA410;">
|
||||
<vn-none pad-medium-h orange>
|
||||
<i class="material-icons pointer"
|
||||
ng-if="!classification.finished"
|
||||
vn-tooltip="Close contract"
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
<mg-ajax path="/client/api/Clients/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/item/api/Clients"
|
||||
filter="::$ctrl.filter"
|
||||
limit="8"
|
||||
data="clients"
|
||||
auto-load="false">
|
||||
</vn-crud-model>
|
||||
<div margin-medium>
|
||||
<div class="vn-list">
|
||||
<vn-card>
|
||||
<vn-horizontal>
|
||||
<vn-searchbar vn-one
|
||||
index="index"
|
||||
on-search="$ctrl.search(index)"
|
||||
advanced="true"
|
||||
popover="vn-client-search-panel"
|
||||
ignore-keys = "['page', 'size', 'search']">
|
||||
</vn-searchbar>
|
||||
</vn-horizontal>
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-client-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-card margin-medium-top>
|
||||
<vn-card margin-medium-v>
|
||||
<vn-item-client
|
||||
ng-repeat="client in index.model.instances track by client.id"
|
||||
client="client">
|
||||
ng-repeat="client in clients track by client.id"
|
||||
client="::client">
|
||||
</vn-item-client>
|
||||
</vn-card>
|
||||
<vn-paging index="index" total="index.model.count"></vn-paging>
|
||||
<!-- <vn-auto-paging index="index" total="index.model.count" items="$ctrl.clients"></vn-auto-paging> -->
|
||||
<vn-pagination
|
||||
model="model"
|
||||
scroll-selector="ui-view">
|
||||
</vn-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<a ui-sref="client.create" vn-bind="+" fixed-bottom-right>
|
||||
|
@ -30,4 +35,4 @@
|
|||
<tpl-body>
|
||||
<vn-client-summary client="$ctrl.clientSelected"></vn-client-summary>
|
||||
</tpl-body>
|
||||
</vn-dialog>
|
||||
</vn-dialog>
|
|
@ -2,23 +2,42 @@ import ngModule from '../module';
|
|||
import './item-client';
|
||||
|
||||
export default class Controller {
|
||||
|
||||
constructor($scope) {
|
||||
this.$scope = $scope;
|
||||
this.$ = $scope;
|
||||
this.clientSelected = null;
|
||||
}
|
||||
|
||||
search(index) {
|
||||
index.accept();
|
||||
/* this.clients = [];
|
||||
index.accept().then(res => {
|
||||
this.clients = res.instances;
|
||||
}); */
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {
|
||||
or: [
|
||||
{id: value},
|
||||
{name: {regexp: value}}
|
||||
]
|
||||
};
|
||||
case 'phone':
|
||||
return {
|
||||
or: [
|
||||
{phone: value},
|
||||
{mobile: value}
|
||||
]
|
||||
};
|
||||
case 'name':
|
||||
case 'socialName':
|
||||
case 'city':
|
||||
return {[param]: {regexp: value}};
|
||||
case 'id':
|
||||
case 'fi':
|
||||
case 'postcode':
|
||||
case 'email':
|
||||
return {[param]: value};
|
||||
}
|
||||
}
|
||||
|
||||
openSummary(client) {
|
||||
this.clientSelected = client;
|
||||
this.$scope.dialogSummaryClient.show();
|
||||
this.$.dialogSummaryClient.show();
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope'];
|
||||
|
|
|
@ -2,4 +2,5 @@ Client id: Id cliente
|
|||
Phone: Teléfono
|
||||
Town/City: Ciudad
|
||||
Email: Correo electrónico
|
||||
Create client: Crear cliente
|
||||
Create client: Crear cliente
|
||||
View client: Ver cliente
|
|
@ -1,22 +1,22 @@
|
|||
<div pad-large style="min-width: 30em">
|
||||
<form ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Client id" model="$ctrl.filter.id" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Tax number" model="$ctrl.filter.fi"></vn-textfield>
|
||||
<vn-textfield vn-one label="Client id" model="filter.id" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Tax number" model="filter.fi"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Name" model="$ctrl.filter.name"></vn-textfield>
|
||||
<vn-textfield vn-one label="Name" model="filter.name"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Social name" model="$ctrl.filter.socialName"></vn-textfield>
|
||||
<vn-textfield vn-one label="Social name" model="filter.socialName"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Town/City" model="$ctrl.filter.city"></vn-textfield>
|
||||
<vn-textfield vn-one label="Postcode" model="$ctrl.filter.postcode"></vn-textfield>
|
||||
<vn-textfield vn-one label="Town/City" model="filter.city"></vn-textfield>
|
||||
<vn-textfield vn-one label="Postcode" model="filter.postcode"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Email" model="$ctrl.filter.email"></vn-textfield>
|
||||
<vn-textfield vn-one label="Phone" model="$ctrl.filter.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Email" model="filter.email"></vn-textfield>
|
||||
<vn-textfield vn-one label="Phone" model="filter.phone"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-large-top>
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor() {
|
||||
// onSubmit() is defined by @vnSearchbar
|
||||
this.onSubmit = () => {};
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
this.onSubmit(this.filter);
|
||||
}
|
||||
}
|
||||
Controller.$inject = [];
|
||||
import SearchPanel from 'core/src/components/searchbar/search-panel';
|
||||
|
||||
ngModule.component('vnClientSearchPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
controller: SearchPanel
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import "colors";
|
||||
|
||||
vn-grid-header {
|
||||
border-bottom: 3px solid $main-header;
|
||||
border-bottom: 3px solid $lines;
|
||||
font-weight: bold;
|
||||
.orderly{
|
||||
text-align: center;
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
}
|
||||
}
|
||||
& > thead, & > tbody {
|
||||
border-bottom: 3px solid $main-header;
|
||||
border-bottom: 3px solid $lines;
|
||||
}
|
||||
& > tbody > tr {
|
||||
border-bottom: 1px solid $main-header;
|
||||
border-bottom: 1px solid $lines;
|
||||
transition: background-color 200ms ease-in-out;
|
||||
|
||||
&.clickable {
|
||||
|
|
|
@ -3,7 +3,8 @@ import './style.scss';
|
|||
|
||||
export default class IconButton {
|
||||
constructor($element) {
|
||||
$element[0].tabIndex = 0;
|
||||
if ($element[0].getAttribute('tabindex') == null)
|
||||
$element[0].tabIndex = 0;
|
||||
$element.on("keyup", event => this.onKeyDown(event, $element));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,32 +2,16 @@
|
|||
|
||||
vn-icon-button {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: rgba($main-01, 0.7);
|
||||
font-size: 18pt;
|
||||
transition: color 200ms ease-in-out;
|
||||
cursor: pointer;
|
||||
|
||||
&.button {
|
||||
background-color: $main-01;
|
||||
color: white;
|
||||
width: 64px;
|
||||
height: 36px;
|
||||
box-shadow: rgba(0, 0, 0, 0.14) 0px 2px 2px 0px, rgba(0, 0, 0, 0.2) 0px 3px 1px -2px, rgba(0, 0, 0, 0.12) 0px 1px 5px 0px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&.button:focus {
|
||||
will-change: box-shadow;
|
||||
box-shadow: 0 0 8px rgba(0,0,0,.18),0 8px 16px rgba(0,0,0,.36);
|
||||
transition: box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);
|
||||
}
|
||||
&.button i {
|
||||
margin-top: 6px;
|
||||
}
|
||||
& > i,
|
||||
& > i.material-icons {
|
||||
& > vn-icon {
|
||||
display: block;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
margin: 0 auto;
|
||||
}
|
||||
&:not(.button):hover {
|
||||
color: $main-01;
|
||||
|
|
|
@ -3,7 +3,6 @@ import './rest-model/crud-model';
|
|||
import './rest-model/rest-model';
|
||||
import './watcher/watcher';
|
||||
import './textfield/textfield';
|
||||
import './paging/paging';
|
||||
import './icon/icon';
|
||||
import './dialog/dialog';
|
||||
import './confirm/confirm';
|
||||
|
@ -34,4 +33,7 @@ import './switch/switch';
|
|||
import './float-button/float-button';
|
||||
import './step-control/step-control';
|
||||
import './label-value/label-value';
|
||||
import './paging/paging';
|
||||
import './auto-paging/auto-paging';
|
||||
import './pagination/pagination';
|
||||
import './searchbar/searchbar';
|
||||
|
|
|
@ -2,7 +2,7 @@ import ngModule from '../../module';
|
|||
import './style.scss';
|
||||
|
||||
ngModule.component('vnLabelValue', {
|
||||
template: require('../label-value/label-value.html'),
|
||||
template: require('./label-value.html'),
|
||||
replace: true,
|
||||
transclude: true,
|
||||
bindings: {
|
||||
|
|
|
@ -12,13 +12,17 @@ export default class ModelProxy {
|
|||
|
||||
set orgData(value) {
|
||||
this._orgData = value;
|
||||
this._data = [];
|
||||
// this._data.splice(0, this._data.length);
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
let row = new this.Row(value[i], i);
|
||||
this._data.push(row);
|
||||
}
|
||||
if (this.Row) {
|
||||
this._data = [];
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
let row = new this.Row(value[i], i);
|
||||
this._data.push(row);
|
||||
}
|
||||
} else
|
||||
this._data = value;
|
||||
|
||||
this.resetChanges();
|
||||
}
|
||||
|
@ -112,6 +116,11 @@ export default class ModelProxy {
|
|||
|
||||
this.resetChanges();
|
||||
}
|
||||
|
||||
dataChanged() {
|
||||
if (this.onDataChange)
|
||||
this.onDataChange();
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnModelProxy', {
|
||||
|
@ -120,6 +129,7 @@ ngModule.component('vnModelProxy', {
|
|||
orgData: '<?',
|
||||
data: '=?',
|
||||
fields: '<?',
|
||||
link: '<?'
|
||||
link: '<?',
|
||||
onDataChange: '&?'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<div
|
||||
ng-if="$ctrl.model.moreRows">
|
||||
<vn-icon-button
|
||||
ng-if="!$ctrl.model.isLoading"
|
||||
icon="more_horiz"
|
||||
vn-tooltip="Load more"
|
||||
ng-click="$ctrl.model.loadMore()">
|
||||
</vn-icon-button>
|
||||
<vn-spinner
|
||||
ng-if="$ctrl.model.isLoading"
|
||||
enable="$ctrl.model.isLoading">
|
||||
</vn-spinner>
|
||||
</div>
|
|
@ -0,0 +1,75 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* Pagination component that automatically loads more rows when
|
||||
* the user scrolls down an element.
|
||||
*
|
||||
* @property {CrudModel} model The model used for pagination
|
||||
* @property {String} scrollSelector The the scrollable element selector
|
||||
* @property {HTMLElement} scrollElement The scrollable element
|
||||
* @property {Number} scrollOffset The distance, in pixels, until the end that activates the loading of the next rows
|
||||
*/
|
||||
class Pagination extends Component {
|
||||
constructor($element, $scope) {
|
||||
super($element, $scope);
|
||||
this.scrollOffset = 20;
|
||||
this.scrollHandler = e => this.onScroll(e);
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (!this._scrollElement)
|
||||
this.scrollElement = document.body;
|
||||
}
|
||||
|
||||
set scrollSelector(value) {
|
||||
this._scrollSelector = value;
|
||||
this.scrollElement = document.querySelector(value);
|
||||
}
|
||||
|
||||
get scrollSelector() {
|
||||
return this._scrollSelector;
|
||||
}
|
||||
|
||||
set scrollElement(value) {
|
||||
if (this._scrollElement)
|
||||
this._scrollElement.removeEventListener('scroll', this.scrollHandler);
|
||||
|
||||
this._scrollElement = value;
|
||||
|
||||
if (value)
|
||||
this._scrollElement.addEventListener('scroll', this.scrollHandler);
|
||||
}
|
||||
|
||||
get scrollElement() {
|
||||
return this._scrollElement;
|
||||
}
|
||||
|
||||
onScroll() {
|
||||
let scrollElement = this.scrollElement;
|
||||
let shouldLoad =
|
||||
scrollElement.scrollTop + scrollElement.clientHeight >= (scrollElement.scrollHeight - this.scrollOffset)
|
||||
&& !this.model.isLoading;
|
||||
|
||||
if (shouldLoad) {
|
||||
this.model.loadMore();
|
||||
this.$.$apply();
|
||||
}
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.scrollElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnPagination', {
|
||||
template: require('./pagination.html'),
|
||||
bindings: {
|
||||
model: '<',
|
||||
scrollSelector: '@?',
|
||||
scrollElement: '<?',
|
||||
scrollOffset: '<?'
|
||||
},
|
||||
controller: Pagination
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
vn-pagination {
|
||||
display: block;
|
||||
text-align: center;
|
||||
|
||||
& > div > vn-icon-button {
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
|
@ -10,32 +10,80 @@ export default class CrudModel extends ModelProxy {
|
|||
this.autoLoad = true;
|
||||
}
|
||||
|
||||
get isLoading() {
|
||||
return this.canceler != null;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.autoLoad)
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
refresh(usFilter, usData) {
|
||||
if (!this.url) return;
|
||||
|
||||
let myFilter = {
|
||||
fields: this.fields,
|
||||
where: mergeWhere(this.link, this.where),
|
||||
include: this.include,
|
||||
order: this.order,
|
||||
limit: this.limit,
|
||||
userData: this.userData
|
||||
};
|
||||
|
||||
let filter = this.filter;
|
||||
filter = mergeFilters(myFilter, filter);
|
||||
filter = mergeFilters(usFilter, filter);
|
||||
return this.sendRequest(filter);
|
||||
}
|
||||
|
||||
if (!filter) {
|
||||
let where = Object.assign({}, this.link, this.where);
|
||||
filter = {
|
||||
fields: this.fields,
|
||||
where: where,
|
||||
include: this.include,
|
||||
order: this.order,
|
||||
limit: this.limit
|
||||
};
|
||||
cancelRequest() {
|
||||
if (this.canceler) {
|
||||
this.canceler.resolve();
|
||||
this.canceler = null;
|
||||
}
|
||||
}
|
||||
|
||||
let urlFilter = encodeURIComponent(JSON.stringify(filter));
|
||||
sendRequest(filter, append) {
|
||||
this.cancelRequest();
|
||||
this.canceler = this.$q.defer();
|
||||
let options = {timeout: this.canceler.promise};
|
||||
let json = encodeURIComponent(JSON.stringify(filter));
|
||||
return this.$http.get(`${this.url}?filter=${json}`, options).then(
|
||||
json => this.onRemoteDone(json, filter, append),
|
||||
json => this.onRemoteError(json)
|
||||
);
|
||||
}
|
||||
|
||||
return this.$http.get(`${this.url}?filter=${urlFilter}`).then(res => {
|
||||
this.orgData = res.data;
|
||||
});
|
||||
onRemoteDone(json, filter, append) {
|
||||
let data = json.data;
|
||||
|
||||
if (append)
|
||||
this.orgData = this.orgData.concat(data);
|
||||
else
|
||||
this.orgData = data;
|
||||
|
||||
this.currentFilter = filter;
|
||||
this.moreRows = filter.limit && data.length == filter.limit;
|
||||
this.onRequestEnd();
|
||||
this.dataChanged();
|
||||
}
|
||||
|
||||
onRemoteError(err) {
|
||||
this.onRequestEnd();
|
||||
throw err;
|
||||
}
|
||||
|
||||
onRequestEnd() {
|
||||
this.canceler = null;
|
||||
}
|
||||
|
||||
loadMore() {
|
||||
if (this.moreRows) {
|
||||
let filter = Object.assign({}, this.currentFilter);
|
||||
filter.skip = (filter.skip || 0) + filter.limit;
|
||||
this.sendRequest(filter, true);
|
||||
}
|
||||
}
|
||||
|
||||
getChanges() {
|
||||
|
@ -97,7 +145,87 @@ ngModule.component('vnCrudModel', {
|
|||
order: '@?',
|
||||
limit: '<?',
|
||||
filter: '<?',
|
||||
userData: '<?',
|
||||
primaryKey: '@?',
|
||||
autoLoad: '<?'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Passes a loopback fields filter to an object.
|
||||
*
|
||||
* @param {Object} fields The fields object or array
|
||||
* @return {Object} The fields as object
|
||||
*/
|
||||
function fieldsToObject(fields) {
|
||||
let fieldsObj = {};
|
||||
|
||||
if (Array.isArray(fields))
|
||||
for (let field of fields)
|
||||
fieldsObj[field] = true;
|
||||
else if (typeof fields == 'object')
|
||||
for (let field in fields)
|
||||
if (fields[field])
|
||||
fieldsObj[field] = true;
|
||||
|
||||
return fieldsObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two loopback fields filters.
|
||||
*
|
||||
* @param {Object|Array} src The source fields
|
||||
* @param {Object|Array} dst The destination fields
|
||||
* @return {Array} The merged fields as an array
|
||||
*/
|
||||
function mergeFields(src, dst) {
|
||||
let fields = {};
|
||||
Object.assign(fields,
|
||||
fieldsToObject(src),
|
||||
fieldsToObject(dst)
|
||||
);
|
||||
return Object.keys(fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two loopback where filters.
|
||||
*
|
||||
* @param {Object|Array} src The source where
|
||||
* @param {Object|Array} dst The destination where
|
||||
* @return {Array} The merged wheres
|
||||
*/
|
||||
function mergeWhere(src, dst) {
|
||||
let and = [];
|
||||
if (src) and.push(src);
|
||||
if (dst) and.push(dst);
|
||||
return and.length > 1 ? {and} : and[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two loopback filters returning the merged filter.
|
||||
*
|
||||
* @param {Object} src The source filter
|
||||
* @param {Object} dst The destination filter
|
||||
* @return {Object} The result filter
|
||||
*/
|
||||
function mergeFilters(src, dst) {
|
||||
let res = Object.assign({}, dst);
|
||||
|
||||
if (!src)
|
||||
return res;
|
||||
|
||||
if (src.fields)
|
||||
res.fields = mergeFields(src.fields, res.fields);
|
||||
if (src.where)
|
||||
res.where = mergeWhere(res.where, src.where);
|
||||
if (src.include)
|
||||
res.include = src.include;
|
||||
if (src.order)
|
||||
res.order = src.order;
|
||||
if (src.limit)
|
||||
res.limit = src.limit;
|
||||
if (src.userData)
|
||||
res.userData = src.userData;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import Component from '../../lib/component';
|
||||
|
||||
export default class extends Component {
|
||||
set filter(value) {
|
||||
this.$.filter = value;
|
||||
}
|
||||
|
||||
get filter() {
|
||||
return this.$.filter;
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
if (!this.onSubmit)
|
||||
throw new Error('SearchPanel::onSubmit() method not defined');
|
||||
|
||||
this.onSubmit(this.filter);
|
||||
}
|
||||
}
|
|
@ -5,11 +5,11 @@
|
|||
ng-click="$ctrl.clearFilter(); $ctrl.onSubmit()"
|
||||
style="cursor: pointer; padding-top: 23px">
|
||||
</vn-icon-button>
|
||||
<vn-textfield vn-one label="Search" model="$ctrl.stringSearch"></vn-textfield>
|
||||
<vn-textfield vn-one label="Search" model="$ctrl.searchString"></vn-textfield>
|
||||
<vn-icon
|
||||
pad-medium-top
|
||||
ng-if="$ctrl.advanced"
|
||||
ng-click="$ctrl.onpenFilters($event)"
|
||||
ng-if="$ctrl.panel"
|
||||
ng-click="$ctrl.openPanel($event)"
|
||||
icon="keyboard_arrow_down"
|
||||
style="cursor: pointer; color: #aaa">
|
||||
</vn-icon>
|
|
@ -0,0 +1,200 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* An input specialized to perform searches, it allows to use a panel
|
||||
* for advanced searches when the panel property is defined.
|
||||
* When model and exprBuilder properties are used, the model is updated
|
||||
* automatically with an and-filter exprexion in which each operand is built
|
||||
* by calling the exprBuilder function for each non-null parameter.
|
||||
*
|
||||
* @property {Object} filter A key-value object with filter parameters
|
||||
* @property {Function} onSearch Function to call when search is submited
|
||||
* @property {SearchPanel} panel The panel used for advanced searches
|
||||
* @property {CrudModel} model The model used for searching
|
||||
* @property {Function} exprBuilder If defined, is used to build each non-null param expresion
|
||||
*/
|
||||
export default class Controller extends Component {
|
||||
constructor($element, $scope, $compile, $state, $transitions) {
|
||||
super($element, $scope);
|
||||
this.$compile = $compile;
|
||||
this.$state = $state;
|
||||
this.deregisterCallback = $transitions.onStart({},
|
||||
transition => this.changeState(transition));
|
||||
|
||||
this.filter = {};
|
||||
this.searchString = '';
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.$state.params.q)
|
||||
this.filter = JSON.parse(decodeURIComponent(this.$state.params.q));
|
||||
|
||||
this.refreshString();
|
||||
this.doSearch();
|
||||
}
|
||||
|
||||
changeState(transition) {
|
||||
return transition._targetState._identifier.name !== this.$state.current.name;
|
||||
}
|
||||
|
||||
openPanel(event) {
|
||||
if (event.defaultPrevented) return;
|
||||
event.preventDefault();
|
||||
|
||||
this.$panel = this.$compile(`<${this.panel}/>`)(this.$.$new());
|
||||
let panel = this.$panel.isolateScope().$ctrl;
|
||||
panel.filter = this.filter;
|
||||
panel.onSubmit = filter => this.onPanelSubmit(filter);
|
||||
|
||||
this.$.popover.parent = this.element;
|
||||
this.$.popover.child = this.$panel[0];
|
||||
this.$.popover.show();
|
||||
}
|
||||
|
||||
onPopoverClose() {
|
||||
this.$panel.scope().$destroy();
|
||||
this.$panel.remove();
|
||||
this.$panel = null;
|
||||
}
|
||||
|
||||
onPanelSubmit(filter) {
|
||||
this.$.popover.hide();
|
||||
|
||||
for (let param in filter)
|
||||
if (filter[param] == null)
|
||||
delete filter[param];
|
||||
|
||||
this.filter = filter;
|
||||
this.refreshString();
|
||||
this.doSearch();
|
||||
}
|
||||
|
||||
refreshString() {
|
||||
this.searchString = this.getStringFromObject(this.filter);
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.filter = this.getObjectFromString(this.searchString);
|
||||
this.doSearch();
|
||||
}
|
||||
|
||||
doSearch() {
|
||||
this.pushFilterToState(this.filter);
|
||||
|
||||
if (this.onSearch)
|
||||
this.onSearch({filter: this.filter});
|
||||
|
||||
if (this.model) {
|
||||
if (!this.exprBuilder)
|
||||
throw new Error('exprBuilder property should be defined when model is assigned');
|
||||
|
||||
let and = [];
|
||||
|
||||
for (let param in this.filter) {
|
||||
let value = this.filter[param];
|
||||
if (value == null) continue;
|
||||
let expr = this.exprBuilder({param, value});
|
||||
if (expr) and.push(expr);
|
||||
}
|
||||
|
||||
let lbFilter = and.length > 0 ? {where: {and}} : null;
|
||||
this.model.refresh(lbFilter);
|
||||
}
|
||||
}
|
||||
|
||||
pushFilterToState(filter) {
|
||||
let history = window.history || {pushState: () => {
|
||||
console.error('Error in history.pushState(): Browser incompatibility error');
|
||||
}};
|
||||
let aux = window.location.hash.split('?q=');
|
||||
if (Object.keys(filter).length)
|
||||
history.pushState({}, null, `${aux[0]}?q=${encodeURIComponent(JSON.stringify(filter))}`);
|
||||
else
|
||||
history.pushState({}, null, aux[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds pattern key:value or key:(extra value) and passes it to object.
|
||||
*
|
||||
* @param {String} searchString The search string
|
||||
* @return {Object} The parsed object
|
||||
*/
|
||||
getObjectFromString(searchString) {
|
||||
let result = {};
|
||||
if (searchString) {
|
||||
let regex = /((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi;
|
||||
let findPattern = searchString.match(regex);
|
||||
let remnantString = searchString.replace(regex, '').trim();
|
||||
if (findPattern) {
|
||||
for (let i = 0; i < findPattern.length; i++) {
|
||||
let aux = findPattern[i].split(':');
|
||||
let property = aux[0];
|
||||
let value = aux[1].replace(/\(|\)/g, '');
|
||||
result[property] = value.trim();
|
||||
}
|
||||
}
|
||||
if (remnantString)
|
||||
result.search = remnantString;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes an object to pattern key:value or key:(extra value).
|
||||
*
|
||||
* @param {Object} searchObject The search object
|
||||
* @return {String} The passed string
|
||||
*/
|
||||
getStringFromObject(searchObject) {
|
||||
let search = [];
|
||||
|
||||
if (searchObject) {
|
||||
let keys = Object.keys(searchObject);
|
||||
keys.forEach(key => {
|
||||
if (key == 'search') return;
|
||||
|
||||
let value = searchObject[key];
|
||||
let valueString;
|
||||
|
||||
if (typeof value === 'string' && value.indexOf(' ') !== -1)
|
||||
valueString = `(${value})`;
|
||||
else if (value instanceof Date)
|
||||
valueString = value.toJSON();
|
||||
else
|
||||
switch (typeof value) {
|
||||
case 'number':
|
||||
case 'string':
|
||||
case 'boolean':
|
||||
valueString = `${value}`;
|
||||
}
|
||||
|
||||
if (valueString)
|
||||
search.push(`${key}:${valueString}`);
|
||||
});
|
||||
|
||||
if (searchObject.search)
|
||||
search.unshift(searchObject.search);
|
||||
}
|
||||
|
||||
return search.length ? search.join(' ') : '';
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.deregisterCallback();
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$element', '$scope', '$compile', '$state', '$transitions'];
|
||||
|
||||
ngModule.component('vnSearchbar', {
|
||||
template: require('./searchbar.html'),
|
||||
bindings: {
|
||||
filter: '<?',
|
||||
onSearch: '&',
|
||||
panel: '@',
|
||||
model: '<?',
|
||||
exprBuilder: '&?'
|
||||
},
|
||||
controller: Controller
|
||||
});
|
|
@ -1,7 +1,6 @@
|
|||
vn-searchbar {
|
||||
padding-top: 6px;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
display: block;
|
||||
|
||||
& > form > vn-horizontal > vn-icon-button {
|
||||
color: black;
|
|
@ -11,4 +11,5 @@ Hide: Hide
|
|||
Next: Next
|
||||
Finalize: Finalize
|
||||
Previous: Back
|
||||
Load more: Load more
|
||||
Auto-scroll interrupted, please adjust the search: Auto-scroll interrupted, please adjust the search
|
|
@ -11,4 +11,5 @@ Hide: Ocultar
|
|||
Next: Siguiente
|
||||
Finalize: Finalizar
|
||||
Previous: Anterior
|
||||
Load more: Cargar más
|
||||
Auto-scroll interrupted, please adjust the search: Auto-scroll interrumpido, por favor ajusta la búsqueda
|
|
@ -20,5 +20,5 @@
|
|||
.icon-ticket:before { content: '\e821'; } /* '' */
|
||||
.icon-tax:before { content: '\e822'; } /* '' */
|
||||
.icon-no036:before { content: '\e823'; } /* '' */
|
||||
.icon-mana:before { content: '\e824'; } /* '' */
|
||||
.icon-transaction:before { content: '\e826'; } /* '' */
|
||||
.icon-solunion:before { content: '\e827'; } /* '' */
|
Binary file not shown.
|
@ -2,4 +2,4 @@ import './mdl-override.scss';
|
|||
import './mdi-override.css';
|
||||
import './zoom-image.scss';
|
||||
import './fontello-head.css';
|
||||
import './fontello-icons.css';
|
||||
import './fontello-codes.css';
|
||||
|
|
|
@ -109,6 +109,18 @@
|
|||
"params": {
|
||||
"item": "$ctrl.item"
|
||||
}
|
||||
}, {
|
||||
"url" : "/diary",
|
||||
"state": "item.card.diary",
|
||||
"component": "vn-item-diary",
|
||||
"params": {
|
||||
"item": "$ctrl.item"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Diary",
|
||||
"icon": "icon-transaction"
|
||||
},
|
||||
"acl": ["employee"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -25,8 +25,8 @@
|
|||
<vn-auto pad-medium>
|
||||
<h5>{{$ctrl.item.id}}</h5>
|
||||
<vn-label-value label="Name"
|
||||
value="{{$ctrl.item.name}}">
|
||||
</vn-label-value>
|
||||
value="{{$ctrl.item.name}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Buyer"
|
||||
value="{{$ctrl.item.itemType.worker.firstName}} {{$ctrl.item.itemType.worker.name}}">
|
||||
</vn-label-value>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Item diary</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-focus
|
||||
url="/item/api/Warehouses"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
initial-data="$ctrl.warehouseFk"
|
||||
field="$ctrl.warehouseFk"
|
||||
label="Select warehouse">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<table class="vn-grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th number translate>Date</th>
|
||||
<th number translate>State</th>
|
||||
<th number translate>Origin</th>
|
||||
<th number translate>Reference</th>
|
||||
<th style="text-align: center" translate>Name</th>
|
||||
<th number translate>In</th>
|
||||
<th number translate>Out</th>
|
||||
<th number translate>Balance</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="diary in $ctrl.diary">
|
||||
<td number>{{diary.date | date:'dd/MM/yyyy HH:mm' }}</td>
|
||||
<td number>{{diary.alertLevel | dashIfEmpty}}</td>
|
||||
<td number>{{diary.origin | dashIfEmpty}}</td>
|
||||
<td number>{{diary.reference | dashIfEmpty}}</td>
|
||||
<td style="text-align: center">{{diary.name | dashIfEmpty}}</td>
|
||||
<td number>{{diary.in | dashIfEmpty}}</td>
|
||||
<td number>{{diary.out | dashIfEmpty}}</td>
|
||||
<td number>{{diary.balance | dashIfEmpty}}</td>
|
||||
</tr>
|
||||
<tr ng-if="$ctrl.diary.length === 0" class="list list-element">
|
||||
<td colspan="8" style="text-align: center" translate>No results</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-paging margin-large-top vn-one index="$ctrl.diary" total="$ctrl.diary.count"></vn-paging>
|
||||
<!-- <vn-auto-paging margin-large-top vn-one index="index" total="index.model.count" items="$ctrl.instances"></vn-auto-paging> -->
|
||||
</vn-vertical>
|
|
@ -0,0 +1,38 @@
|
|||
import ngModule from '../module';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
constructor($scope, $http) {
|
||||
this.$ = $scope;
|
||||
this.$http = $http;
|
||||
this.diary = [];
|
||||
}
|
||||
|
||||
set warehouseFk(value) {
|
||||
this._getItemDiary(value);
|
||||
this._warehouseFk = value;
|
||||
}
|
||||
|
||||
get warehouseFk() {
|
||||
return this._warehouseFk;
|
||||
}
|
||||
|
||||
_getItemDiary(warehouse) {
|
||||
if (warehouse == null)
|
||||
return;
|
||||
let params = {itemFk: this.item.id, warehouseFk: warehouse};
|
||||
this.$http.get(`/item/api/Items/getDiary?params=${JSON.stringify(params)}`).then(res => {
|
||||
this.diary = res.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$http'];
|
||||
|
||||
ngModule.component('vnItemDiary', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
item: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,43 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Item', () => {
|
||||
describe('Component vnItemDiary', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('item');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnItemDiary', {$scope: $scope});
|
||||
controller.item = {id: 3};
|
||||
}));
|
||||
|
||||
describe('set warehouseFk()', () => {
|
||||
it(`should call _getItemDiary() with 2 and set warehouseFk`, () => {
|
||||
spyOn(controller, '_getItemDiary');
|
||||
controller.warehouseFk = 2;
|
||||
|
||||
expect(controller._getItemDiary).toHaveBeenCalledWith(2);
|
||||
expect(controller.warehouseFk).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_getItemDiary()', () => {
|
||||
it(`should make a request to get the diary hwen is called with a number`, () => {
|
||||
$httpBackend.whenGET('/item/api/Items/getDiary?params={"itemFk":3,"warehouseFk":2}').respond({data: 'item'});
|
||||
$httpBackend.expectGET('/item/api/Items/getDiary?params={"itemFk":3,"warehouseFk":2}');
|
||||
controller._getItemDiary(2);
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
vn-item-diary {
|
||||
& vn-horizontal {
|
||||
justify-content: center;
|
||||
}
|
||||
& vn-autocomplete > div{
|
||||
width: 400px;
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
<div pad-large style="min-width: 30em">
|
||||
<form ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Id"
|
||||
model="$ctrl.filter.id"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
model="$ctrl.filter.name"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Description"
|
||||
model="$ctrl.filter.description">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
url="/item/api/ItemTypes"
|
||||
label="Type"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.filter.typeFk">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
url="/item/api/Producers"
|
||||
label="Producer"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.filter.producerFk">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
url="/item/api/Origins"
|
||||
label="Origin"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.filter.originFk">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
url="/item/api/Inks"
|
||||
label="Ink"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.filter.inkFk">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Category"
|
||||
model="$ctrl.filter.category">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Size"
|
||||
type="number"
|
||||
model="$ctrl.filter.itemSize">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-large-top>
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
</div>
|
|
@ -1,16 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor() {
|
||||
this.onSubmit = () => {};
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
this.onSubmit(this.filter);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnItemFilterPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,26 +1,30 @@
|
|||
<mg-ajax path="/item/api/Items/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/item/api/Items"
|
||||
filter="::$ctrl.filter"
|
||||
limit="8"
|
||||
data="items"
|
||||
auto-load="false">
|
||||
</vn-crud-model>
|
||||
<div margin-medium>
|
||||
<div class="vn-list">
|
||||
<vn-card>
|
||||
<vn-horizontal>
|
||||
<vn-searchbar
|
||||
vn-one
|
||||
index="index"
|
||||
on-search="$ctrl.search(index)"
|
||||
advanced="true"
|
||||
popover="vn-item-filter-panel"
|
||||
ignore-keys = "['page', 'size', 'search']">
|
||||
</vn-searchbar>
|
||||
</vn-horizontal>
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-item-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-card margin-medium-top>
|
||||
<vn-card margin-medium-v>
|
||||
<vn-item-product
|
||||
ng-repeat="item in index.model.instances track by item.id"
|
||||
item="item">
|
||||
ng-repeat="item in items track by item.id"
|
||||
item="::item">
|
||||
</vn-item-product>
|
||||
</vn-card>
|
||||
<vn-paging index="index" total="index.model.count"></vn-paging>
|
||||
<!-- <vn-auto-paging index="index" total="index.model.count" items="$ctrl.items"></vn-auto-paging> -->
|
||||
<vn-pagination
|
||||
model="model"
|
||||
scroll-selector="ui-view">
|
||||
</vn-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<a ui-sref="item.create" vn-bind="+" fixed-bottom-right>
|
||||
|
|
|
@ -3,46 +3,68 @@ import './product';
|
|||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
|
||||
constructor($http, $state, $scope) {
|
||||
this.$http = $http;
|
||||
this.$state = $state;
|
||||
this.$scope = $scope;
|
||||
this.model = {};
|
||||
this.$ = $scope;
|
||||
this.itemSelected = null;
|
||||
this.items = [];
|
||||
|
||||
this.filter = {
|
||||
include: [
|
||||
{relation: 'itemType',
|
||||
scope: {
|
||||
fields: ['name', 'workerFk'],
|
||||
include: {
|
||||
relation: 'worker',
|
||||
fields: ['firstName', 'name']
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
order: 'name ASC'
|
||||
};
|
||||
}
|
||||
|
||||
search(index) {
|
||||
index.accept();
|
||||
/* this.items = [];
|
||||
index.accept().then(res => {
|
||||
this.items = res.instances;
|
||||
}); */
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {
|
||||
or: [
|
||||
{id: value},
|
||||
{name: {regexp: value}}
|
||||
]
|
||||
};
|
||||
case 'name':
|
||||
case 'description':
|
||||
return {[param]: {regexp: value}};
|
||||
case 'id':
|
||||
case 'typeFk':
|
||||
return {[param]: value};
|
||||
}
|
||||
}
|
||||
|
||||
cloneItem(item) {
|
||||
this.itemSelected = item;
|
||||
this.$scope.clone.show();
|
||||
this.$.clone.show();
|
||||
}
|
||||
|
||||
onCloneAccept(response) {
|
||||
if (response == 'ACCEPT' && this.itemSelected) {
|
||||
this.$http.post(`/item/api/Items/${this.itemSelected.id}/clone`).then(res => {
|
||||
if (res && res.data && res.data.id) {
|
||||
this.$state.go('item.card.tags', {id: res.data.id});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!(response == 'ACCEPT' && this.itemSelected))
|
||||
return;
|
||||
|
||||
this.$http.post(`/item/api/Items/${this.itemSelected.id}/clone`).then(res => {
|
||||
if (res && res.data && res.data.id)
|
||||
this.$state.go('item.card.tags', {id: res.data.id});
|
||||
});
|
||||
|
||||
this.itemSelected = null;
|
||||
}
|
||||
|
||||
|
||||
showItemPreview(item) {
|
||||
this.itemSelected = item;
|
||||
this.$scope.preview.show();
|
||||
this.$.preview.show();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', '$state', '$scope'];
|
||||
|
||||
ngModule.component('vnItemIndex', {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@import "./colors";
|
||||
|
||||
vn-item-product {
|
||||
display: block;
|
||||
|
@ -12,4 +13,4 @@ vn-item-product {
|
|||
border-radius: .2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ export * from './module';
|
|||
|
||||
import './index';
|
||||
import './filter-item-list';
|
||||
import './filter-panel';
|
||||
import './search-panel';
|
||||
import './diary';
|
||||
import './create';
|
||||
import './card';
|
||||
import './descriptor';
|
||||
|
|
|
@ -29,10 +29,16 @@ Value: Valor
|
|||
Priority: Prioridad
|
||||
Item tax: Tasas del artículo
|
||||
Country: País
|
||||
Select warehouse: Selecione almacén
|
||||
Class: Clase
|
||||
Item niches: Nichos del artículo
|
||||
Item diary: Registro de compra-venta
|
||||
Diary: Registro
|
||||
Warehouse: Almacén
|
||||
Code: Código
|
||||
State: Estado
|
||||
In: Entrada
|
||||
Out: Salida
|
||||
Botanical: Botánico
|
||||
Species: Especie
|
||||
Add tag: Añadir etiqueta
|
||||
|
@ -42,4 +48,5 @@ Remove niche: Quitar nicho
|
|||
Add barcode: Añadir código de barras
|
||||
Remove barcode: Quitar código de barras
|
||||
Buyer: Comprador
|
||||
No results: Sin resultados
|
||||
No results: Sin resultados
|
||||
Tag: Etiqueta
|
|
@ -0,0 +1,84 @@
|
|||
<mg-ajax path="/item/api/Tags" options="mgIndex as tags"></mg-ajax>
|
||||
<div style="min-width: 30em; max-height: 540px; overflow: auto;">
|
||||
<form pad-large ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Id"
|
||||
model="filter.id"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
model="filter.name">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
vn-focus
|
||||
url="/item/api/ItemTypes"
|
||||
label="Type"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="filter.typeFk">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Description"
|
||||
model="filter.description">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<!--
|
||||
<vn-horizontal ng-repeat="itemTag in filter.tags">
|
||||
<vn-autocomplete
|
||||
vn-id="tag"
|
||||
vn-one
|
||||
field="itemTag.tagFk"
|
||||
data="tags.model"
|
||||
show-field="name"
|
||||
label="Tag"
|
||||
on-change="itemTag.value = null">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
ng-show="tag.selection.isFree !== false"
|
||||
vn-id="text"
|
||||
label="Value"
|
||||
model="itemTag.value">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
vn-two
|
||||
ng-show="tag.selection.isFree === false"
|
||||
url="{{$ctrl.getSourceTable(tag.selection)}}"
|
||||
label="Value"
|
||||
field="itemTag.value"
|
||||
show-field="name"
|
||||
value-field="name">
|
||||
</vn-autocomplete>
|
||||
<vn-none>
|
||||
<vn-icon-button
|
||||
medium-grey
|
||||
margin-medium-v
|
||||
vn-tooltip="Remove tag"
|
||||
icon="remove_circle_outline"
|
||||
ng-click="filter.tags.splice($index, 1)"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-icon-button
|
||||
vn-bind="+"
|
||||
vn-tooltip="Add tag"
|
||||
icon="add_circle"
|
||||
ng-click="filter.tags.push({})">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
-->
|
||||
<vn-horizontal margin-large-top>
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,32 @@
|
|||
import ngModule from '../module';
|
||||
import SearchPanel from 'core/src/components/searchbar/search-panel';
|
||||
|
||||
class Controller extends SearchPanel {
|
||||
set filter(value) {
|
||||
if (!value.tags)
|
||||
value.tags = [{}];
|
||||
|
||||
this.$.filter = value;
|
||||
}
|
||||
|
||||
get filter() {
|
||||
return this.$.filter;
|
||||
}
|
||||
|
||||
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}`;
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnItemSearchPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -48,14 +48,16 @@
|
|||
rule="itemTag.priority"
|
||||
vn-acl="buyer">
|
||||
</vn-textfield>
|
||||
<vn-icon
|
||||
pad-medium-top
|
||||
pointer
|
||||
<vn-none>
|
||||
<vn-icon-button
|
||||
medium-grey
|
||||
margin-medium-v
|
||||
vn-tooltip="Remove tag"
|
||||
icon="remove_circle_outline"
|
||||
ng-click="$ctrl.removeTag($index)">
|
||||
</vn-icon>
|
||||
ng-click="$ctrl.removeTag($index)"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-icon-button
|
||||
|
|
|
@ -16,14 +16,14 @@ class Controller {
|
|||
getTags() {
|
||||
let filter = {
|
||||
where: {itemFk: this.params.id},
|
||||
order: "priority ASC",
|
||||
include: {relation: "tag"}
|
||||
order: 'priority ASC',
|
||||
include: {relation: 'tag'}
|
||||
};
|
||||
this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => {
|
||||
this.removedTags = [];
|
||||
|
||||
this.itemTags = JSON.parse(JSON.stringify(this.tags));
|
||||
this.tags = response.data;
|
||||
this.itemTags = JSON.parse(JSON.stringify(this.tags));
|
||||
this.orgTags = {};
|
||||
this.tags.forEach(tag => {
|
||||
this.orgTags[tag.id] = Object.assign({}, tag);
|
||||
|
@ -63,7 +63,7 @@ class Controller {
|
|||
return null;
|
||||
|
||||
if (selection.sourceTable) {
|
||||
return "/api/" + selection.sourceTable.charAt(0).toUpperCase() +
|
||||
return '/api/' + selection.sourceTable.charAt(0).toUpperCase() +
|
||||
selection.sourceTable.substring(1) + 's';
|
||||
} else if (selection.sourceTable == null) {
|
||||
return `/api/ItemTags/filterItemTags/${selection.id}`;
|
||||
|
@ -107,7 +107,6 @@ ngModule.component('vnItemTags', {
|
|||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
itemTags: '=',
|
||||
selection: '<?'
|
||||
itemTags: '='
|
||||
}
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.filter.warehouseFk"
|
||||
url="/production/api/Warehouses/production"
|
||||
url="/production/api/Warehouses"
|
||||
on-change = "$ctrl.onChangeWareHouse(item)"
|
||||
label="Store">
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.filter.warehouseFk"
|
||||
url="/production/api/Warehouses/production"
|
||||
url="/production/api/Warehouses"
|
||||
on-change = "$ctrl.onChangeWareHouse(item)"
|
||||
label="Store">
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -4,4 +4,3 @@ import './main-menu/main-menu';
|
|||
import './left-menu/left-menu';
|
||||
import './left-menu/menu-item';
|
||||
import './topbar/topbar';
|
||||
import './searchbar/searchbar';
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller {
|
||||
constructor($element, $scope, $compile, $timeout, $state, $transitions) {
|
||||
this.element = $element[0];
|
||||
this.$ = $scope;
|
||||
this.$compile = $compile;
|
||||
this.$timeout = $timeout;
|
||||
this.stringSearch = '';
|
||||
this.$state = $state;
|
||||
this.deregisterCallback = $transitions.onStart({},
|
||||
transition => this.changeState(transition));
|
||||
}
|
||||
|
||||
clearFilter() {
|
||||
this.index.filter = {
|
||||
page: 1,
|
||||
size: 20
|
||||
};
|
||||
}
|
||||
|
||||
setFilter(filterObject) {
|
||||
this.clearFilter();
|
||||
Object.assign(this.index.filter, filterObject);
|
||||
}
|
||||
|
||||
getFiltersFromString(stringSearch) {
|
||||
let result = {};
|
||||
if (stringSearch) {
|
||||
// find pattern key:value or key:(extra value) and returns array
|
||||
let findPattern = stringSearch.match(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi);
|
||||
let remnantString = (stringSearch.replace(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi, '')).trim();
|
||||
if (findPattern) {
|
||||
for (let i = 0; i < findPattern.length; i++) {
|
||||
let aux = findPattern[i].split(':');
|
||||
let property = aux[0];
|
||||
let value = aux[1].replace(/\(|\)/g, '');
|
||||
result[property] = value.trim();
|
||||
}
|
||||
}
|
||||
if (remnantString) {
|
||||
result.search = remnantString;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
createStringFromObject(filterObject) {
|
||||
let search = [];
|
||||
let keys = Object.keys(filterObject);
|
||||
if (keys.length) {
|
||||
keys.forEach(k => {
|
||||
let ignore = (this.ignoreKeys && this.ignoreKeys instanceof Array && this.ignoreKeys.indexOf(k) !== -1);
|
||||
if (!ignore) {
|
||||
let value = filterObject[k];
|
||||
|
||||
if (typeof value === 'string' && value.indexOf(' ') !== -1) {
|
||||
search.push(`${k}:(${value})`);
|
||||
} else if (typeof value !== 'object') {
|
||||
search.push(`${k}:${value}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (filterObject.search)
|
||||
search.unshift(filterObject.search);
|
||||
}
|
||||
return (search.length) ? search.join(' ') : '';
|
||||
}
|
||||
|
||||
changeState(transition) {
|
||||
return !(transition._targetState._identifier.name === this.$state.current.name);
|
||||
}
|
||||
|
||||
pushFiltersToState(filters) {
|
||||
let history = window.history || {pushState: () => {
|
||||
console.error('Error in history.pushState(): Browser incompatibility error');
|
||||
}};
|
||||
let aux = window.location.hash.split('?q=');
|
||||
if (Object.keys(filters).length)
|
||||
history.pushState({}, null, `${aux[0]}?q=${encodeURIComponent(JSON.stringify(filters))}`);
|
||||
else
|
||||
history.pushState({}, null, aux[0]);
|
||||
}
|
||||
|
||||
onpenFilters(event) {
|
||||
let filter = {};
|
||||
if (this.stringSearch) {
|
||||
filter = this.getFiltersFromString(this.stringSearch);
|
||||
}
|
||||
|
||||
this.$child = this.$compile(`<${this.popover}/>`)(this.$.$new());
|
||||
|
||||
var childCtrl = this.$child.isolateScope().$ctrl;
|
||||
childCtrl.filter = Object.assign({}, filter);
|
||||
childCtrl.onSubmit = filter => this.onChildSubmit(filter);
|
||||
if (this.data)
|
||||
childCtrl.data = Object.assign({}, this.data);
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
this.$.popover.parent = this.element;
|
||||
this.$.popover.child = this.$child[0];
|
||||
this.$.popover.show();
|
||||
}
|
||||
|
||||
onPopoverClose() {
|
||||
this.$child.scope().$destroy();
|
||||
this.$child.remove();
|
||||
this.$child = null;
|
||||
}
|
||||
|
||||
onChildSubmit(filter) {
|
||||
this.$.popover.hide();
|
||||
this.stringSearch = this.createStringFromObject(filter);
|
||||
this.clearFilter();
|
||||
this.$timeout(() => this.onSubmit());
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
let filter = {};
|
||||
if (this.stringSearch) {
|
||||
filter = this.getFiltersFromString(this.stringSearch);
|
||||
}
|
||||
this.setFilter(filter);
|
||||
|
||||
if (this.onSearch)
|
||||
this.onSearch();
|
||||
|
||||
this.pushFiltersToState(filter);
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.clearFilter();
|
||||
this.deregisterCallback();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.$state.params.q) {
|
||||
let filter = JSON.parse(decodeURIComponent(this.$state.params.q));
|
||||
this.stringSearch = this.createStringFromObject(filter);
|
||||
}
|
||||
this.$timeout(() => this.onSubmit());
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$element', '$scope', '$compile', '$timeout', '$state', '$transitions'];
|
||||
|
||||
ngModule.component('vnSearchbar', {
|
||||
template: require('./searchbar.html'),
|
||||
bindings: {
|
||||
index: '<',
|
||||
onSearch: '&',
|
||||
advanced: '=',
|
||||
popover: '@',
|
||||
ignoreKeys: '<?',
|
||||
data: '<?'
|
||||
},
|
||||
controller: Controller
|
||||
});
|
|
@ -10,6 +10,7 @@ $main-01-03: rgba($main-01, 0.3);
|
|||
$main-02: #a3d131;
|
||||
$main-02-05: rgba($main-02, 0.5);
|
||||
$main-02-03: rgba($main-02, 0.3);
|
||||
$lines: #9b9b9b;
|
||||
|
||||
$color-green: #a3d131;
|
||||
$color-orange: #f7931e;
|
||||
|
|
|
@ -64,7 +64,6 @@ html [vn-auto], vn-auto, .vn-auto {
|
|||
flex-basis: auto;
|
||||
}
|
||||
html [vn-none], vn-none, .vn-none {
|
||||
flex: 1;
|
||||
flex: none;
|
||||
}
|
||||
html [vn-one], vn-one, .vn-one {
|
||||
|
|
|
@ -64,7 +64,7 @@ html [vn-center], .vn-center{
|
|||
|
||||
.list-element{
|
||||
padding: 8px 0 0 0;
|
||||
border-bottom: 1px solid $main-header;
|
||||
border-bottom: 1px solid $lines;
|
||||
i {
|
||||
color: $main-01;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ html [vn-center], .vn-center{
|
|||
}
|
||||
.list-footer{
|
||||
font-family: vn-font-bold;
|
||||
border-top: 3px solid $main-header;
|
||||
border-top: 3px solid $lines;
|
||||
}
|
||||
.list-element.warning{
|
||||
background-color: $color-medium-orange;
|
||||
|
|
|
@ -1,70 +1,69 @@
|
|||
<mg-ajax path="/ticket/api/Tickets/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<div margin-large>
|
||||
<div>
|
||||
<vn-card pad-medium>
|
||||
<vn-title>TICKETS</vn-title>
|
||||
<vn-horizontal class="vn-list">
|
||||
<vn-searchbar vn-one
|
||||
index="index"
|
||||
on-search="$ctrl.search(index)"
|
||||
ignore-keys = "['page', 'size', 'search']">
|
||||
</vn-searchbar>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<table class="vn-grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th number translate>ID Ticket</th>
|
||||
<th translate>Comercial</th>
|
||||
<th translate>Date</th>
|
||||
<th translate>Hora</th>
|
||||
<th translate>Alias</th>
|
||||
<th translate>Provincia</th>
|
||||
<th translate>Estado</th>
|
||||
<th translate>Agencia</th>
|
||||
<th translate>Almacen</th>
|
||||
<th number translate>Factura</th>
|
||||
<th number translate>Ruta</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="ticket in index.model.instances track by ticket.id"
|
||||
class="{{::$ctrl.compareDate(ticket.shipped)}} clickable"
|
||||
ui-sref="ticket.card.summary({id: {{::ticket.id}}})">
|
||||
<td>
|
||||
<!-- <i pointer
|
||||
class="material-icons"
|
||||
vn-tooltip="delete expedition"
|
||||
ng-click="$ctrl.deleteExpedition(expedition)">warning</i> -->
|
||||
</td>
|
||||
<th number>{{::ticket.id}}</th>
|
||||
<td translate>{{::ticket.client.salesPerson.name | dashIfEmpty}}</td>
|
||||
<td translate>{{::ticket.shipped | date:'dd/MM/yyyy'}}</td>
|
||||
<td translate>{{::ticket.shipped | date:'HH:MM'}}</td>
|
||||
<td translate>{{::ticket.nickname}}</td>
|
||||
<td translate>{{::ticket.address.province.name}}</td>
|
||||
<td translate>{{::ticket.tracking.state.name}}</td>
|
||||
<td translate>{{::ticket.agencyMode.name}}</td>
|
||||
<td translate>{{::ticket.warehouse.name}}</td>
|
||||
<td number translate>{{::ticket.refFk | dashIfEmpty}}</td>
|
||||
<td number translate>{{::ticket.routeFk | dashIfEmpty}}</td>
|
||||
<td>
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.preview($event, ticket)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon-button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</vn-horizontal>
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/ticket/api/Tickets"
|
||||
filter="::$ctrl.filter"
|
||||
limit="20"
|
||||
data="tickets"
|
||||
auto-load="false">
|
||||
</vn-crud-model>
|
||||
<div margin-medium>
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-ticket-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-paging vn-one index="index" total="index.model.count"></vn-paging>
|
||||
<!-- <vn-auto-paging vn-one index="index" total="index.model.count" items="$ctrl.tickets"></vn-auto-paging> -->
|
||||
</div>
|
||||
<vn-card margin-medium-v pad-medium>
|
||||
<table class="vn-grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate number>Id</th>
|
||||
<th translate>Salesperson</th>
|
||||
<th translate>Date</th>
|
||||
<th translate>Hour</th>
|
||||
<th translate>Alias</th>
|
||||
<th translate>Province</th>
|
||||
<th translate>State</th>
|
||||
<th translate>Agency</th>
|
||||
<th translate>Warehouse</th>
|
||||
<th translate number>Invoice</th>
|
||||
<th translate number>Route</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="ticket in tickets"
|
||||
class="{{::$ctrl.compareDate(ticket.shipped)}} clickable"
|
||||
ui-sref="ticket.card.summary({id: {{::ticket.id}}})">
|
||||
<th number>{{::ticket.id}}</th>
|
||||
<td >{{::ticket.client.salesPerson.name | dashIfEmpty}}</td>
|
||||
<td >{{::ticket.shipped | date:'dd/MM/yyyy'}}</td>
|
||||
<td >{{::ticket.shipped | date:'HH:MM'}}</td>
|
||||
<td >{{::ticket.nickname}}</td>
|
||||
<td >{{::ticket.address.province.name}}</td>
|
||||
<td >{{::ticket.tracking.state.name}}</td>
|
||||
<td >{{::ticket.agencyMode.name}}</td>
|
||||
<td >{{::ticket.warehouse.name}}</td>
|
||||
<td number >{{::ticket.refFk | dashIfEmpty}}</td>
|
||||
<td number >{{::ticket.routeFk | dashIfEmpty}}</td>
|
||||
<td>
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.preview($event, ticket)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon-button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</vn-card>
|
||||
<vn-pagination
|
||||
model="model"
|
||||
scroll-selector="ui-view">
|
||||
</vn-pagination>
|
||||
</div>
|
||||
<a ui-sref="ticket.create" vn-bind="+" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
|
|
|
@ -1,11 +1,82 @@
|
|||
import ngModule from '../module';
|
||||
import './ticket-item';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller {
|
||||
constructor($scope) {
|
||||
this.$scope = $scope;
|
||||
this.$ = $scope;
|
||||
this.ticketSelected = null;
|
||||
|
||||
this.filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'address',
|
||||
scope: {
|
||||
fields: ['provinceFk'],
|
||||
include: {
|
||||
relation: 'province',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
relation: 'warehouse',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}, {
|
||||
relation: 'agencyMode',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}, {
|
||||
relation: 'tracking',
|
||||
scope: {
|
||||
fields: ['stateFk'],
|
||||
include: {
|
||||
relation: 'state',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['salesPersonFk'],
|
||||
include: {
|
||||
relation: 'salesPerson',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
order: 'shipped DESC'
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {
|
||||
or: [
|
||||
{id: value},
|
||||
{nickname: {regexp: value}}
|
||||
]
|
||||
};
|
||||
case 'from':
|
||||
return {shipped: {gte: value}};
|
||||
case 'to':
|
||||
return {shipped: {lte: value}};
|
||||
case 'nickname':
|
||||
return {[param]: {regexp: value}};
|
||||
case 'id':
|
||||
case 'clientFk':
|
||||
case 'agencyModeFk':
|
||||
case 'warehouseFk':
|
||||
return {[param]: value};
|
||||
}
|
||||
}
|
||||
|
||||
compareDate(date) {
|
||||
|
@ -26,17 +97,9 @@ export default class Controller {
|
|||
preview(event, ticket) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
this.$scope.dialogSummaryTicket.show();
|
||||
this.$.dialogSummaryTicket.show();
|
||||
this.ticketSelected = ticket;
|
||||
}
|
||||
|
||||
search(index) {
|
||||
index.accept();
|
||||
/* this.tickets = [];
|
||||
index.accept().then(res => {
|
||||
this.tickets = res.instances;
|
||||
}); */
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope'];
|
||||
|
|
|
@ -34,14 +34,14 @@ describe('ticket', () => {
|
|||
it('should call preventDefault and stopImmediatePropagation from event and show', () => {
|
||||
let event = jasmine.createSpyObj('event', ['preventDefault', 'stopImmediatePropagation']);
|
||||
|
||||
controller.$scope = {dialogSummaryTicket: {show: () => {}}};
|
||||
spyOn(controller.$scope.dialogSummaryTicket, 'show');
|
||||
controller.$ = {dialogSummaryTicket: {show: () => {}}};
|
||||
spyOn(controller.$.dialogSummaryTicket, 'show');
|
||||
let ticket = {};
|
||||
controller.preview(event, ticket);
|
||||
|
||||
expect(event.preventDefault).toHaveBeenCalledWith();
|
||||
expect(event.stopImmediatePropagation).toHaveBeenCalledWith();
|
||||
expect(controller.$scope.dialogSummaryTicket.show).toHaveBeenCalledWith();
|
||||
expect(controller.$.dialogSummaryTicket.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
vn-ticket-item {
|
||||
display: block;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<a
|
||||
ui-sref="ticket.card.summary({ id: {{::$ctrl.ticket.id}} })"
|
||||
translate-attr="{title: 'View ticket'}"
|
||||
class="vn-list-item">
|
||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
||||
<vn-one>
|
||||
<h6>{{::$ctrl.ticket.nickname}}</h6>
|
||||
<vn-label-value label="Id"
|
||||
value="{{::$ctrl.ticket.id}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon
|
||||
ng-click="$ctrl.preview($event)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon>
|
||||
</vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</a>
|
|
@ -1,24 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
onClick(event) {
|
||||
if (event.defaultPrevented)
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
preview(event) {
|
||||
event.preventDefault();
|
||||
this.index.openSummary(this.ticket);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnTicketItem', {
|
||||
controller: Controller,
|
||||
template: require('./ticket-item.html'),
|
||||
bindings: {
|
||||
ticket: '<'
|
||||
},
|
||||
require: {
|
||||
index: '^vnTicketIndex'
|
||||
}
|
||||
});
|
|
@ -5,31 +5,50 @@
|
|||
<vn-title>Sale</vn-title>
|
||||
<vn-tool-bar margin-medium-bottom>
|
||||
<vn-button
|
||||
disabled="$ctrl.ticket.tracking.state.alertLevel != 0"
|
||||
disabled="!$ctrl.isEditable"
|
||||
label="Ok"
|
||||
ng-click="$ctrl.onStateOkClick()">
|
||||
</vn-button>
|
||||
<vn-icon-menu
|
||||
disabled="$ctrl.ticket.tracking.state.alertLevel != 0"
|
||||
disabled="!$ctrl.isEditable"
|
||||
label="State"
|
||||
url="/ticket/api/States/alertLevelIs0"
|
||||
on-change="$ctrl.onStateChange(value)">
|
||||
</vn-icon-menu>
|
||||
<vn-icon-menu
|
||||
label="More"
|
||||
show-filter="false"
|
||||
value-field="callback"
|
||||
data="::$ctrl.moreOptions"
|
||||
translate-fields="['name']"
|
||||
on-change="$ctrl.onMoreChange(value)">
|
||||
</vn-icon-menu>
|
||||
<vn-button
|
||||
disabled="!$ctrl.isChecked"
|
||||
disabled="!$ctrl.isChecked || !$ctrl.isEditable"
|
||||
ng-click="$ctrl.onRemoveLinesClick()"
|
||||
vn-tooltip="Remove lines"
|
||||
vn-tooltip="Remove lines"
|
||||
tooltip-position="up"
|
||||
icon="delete">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
disabled="!$ctrl.isChecked || !$ctrl.isEditable"
|
||||
ng-click="$ctrl.showTransferPopover($event);"
|
||||
vn-tooltip="Transfer lines"
|
||||
tooltip-position="right"
|
||||
icon="call_split">
|
||||
</vn-button>
|
||||
</vn-tool-bar>
|
||||
<table class="vn-grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th number>
|
||||
<vn-multi-check data="index.model.instances"></vn-multi-check>
|
||||
<vn-multi-check
|
||||
data="index.model.instances"
|
||||
disabled="!$ctrl.isEditable">
|
||||
</vn-multi-check>
|
||||
</th>
|
||||
<th number translate>Item</th>
|
||||
<th translate>Description</th>
|
||||
<th translate style="text-align:center">Description</th>
|
||||
<th number translate>Quantity</th>
|
||||
<th number translate>Price</th>
|
||||
<th number translate>Discount</th>
|
||||
|
@ -39,7 +58,10 @@
|
|||
<tbody>
|
||||
<tr ng-repeat="sale in index.model.instances track by sale.id">
|
||||
<td number>
|
||||
<vn-check field="sale.checked"></vn-check>
|
||||
<vn-check
|
||||
field="sale.checked"
|
||||
disabled="!$ctrl.isEditable">
|
||||
</vn-check>
|
||||
</td>
|
||||
<td
|
||||
pointer
|
||||
|
@ -48,10 +70,27 @@
|
|||
{{::sale.itemFk}}
|
||||
</td>
|
||||
<td><vn-fetched-tags sale="sale"/></td>
|
||||
<td number>{{::sale.quantity}}</td>
|
||||
<td number>{{::sale.price | currency:'€':2}}</td>
|
||||
<td number>{{::sale.discount}} %</td>
|
||||
<td number>{{::sale.quantity * sale.price | currency:'€':2}}</td>
|
||||
<td number>{{sale.quantity}}</td>
|
||||
<!--<td ng-if="$ctrl.ticket.tracking.state.alertLevel == 0">
|
||||
<vn-textfield
|
||||
model="sale.quantity"
|
||||
type="number"
|
||||
ng-blur="updateLine()">
|
||||
</vn-textfield>
|
||||
</td>-->
|
||||
<td number>{{sale.price | currency:'€':2}}</td>
|
||||
<td number>{{sale.discount}} %</td>
|
||||
<td number>{{sale.quantity * sale.price | currency:'€':2}}</td>
|
||||
<!--<td number>
|
||||
<vn-icon-button
|
||||
ng-if="$ctrl.ticket.tracking.state.alertLevel == 0"
|
||||
pointer
|
||||
vn-tooltip="Add note"
|
||||
tooltip-position="left"
|
||||
icon="mode_edit"
|
||||
ng-click="$ctrl.showEditPopover($event, sale)">
|
||||
</vn-icon-button>
|
||||
</td>-->
|
||||
</tr>
|
||||
<tr ng-if="index.model.count === 0" class="list list-element">
|
||||
<td colspan="6" style="text-align: center" translate>No results</td>
|
||||
|
@ -61,6 +100,135 @@
|
|||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
|
||||
<!-- <vn-auto-paging vn-one margin-large-top index="index" total="index.model.count" items="index.model.instances"></vn-auto-paging> -->
|
||||
<vn-item-descriptor-popover vn-id="descriptor"></vn-item-descriptor-popover>
|
||||
<vn-item-descriptor-popover vn-id="descriptor">
|
||||
</vn-item-descriptor-popover>
|
||||
|
||||
<!-- Create Ticket Dialog -->
|
||||
<!-- <vn-ticket-create-dialog
|
||||
vn-id="newTicket"
|
||||
callback="$ctrl.moveLines(res)"
|
||||
ticket="$ctrl.ticket">
|
||||
</vn-ticket-create-dialog>
|
||||
-->
|
||||
<!-- Add Turn Dialog -->
|
||||
<vn-dialog class="dialog-summary"
|
||||
vn-id="addTurn">
|
||||
<tpl-body>
|
||||
<div>
|
||||
<h5 style="text-align: center">
|
||||
<span translate>In which day you want to add the ticket?</span>
|
||||
</h5>
|
||||
<vn-tool-bar margin-medium-top>
|
||||
<vn-button
|
||||
label="Monday"
|
||||
ng-click="$ctrl.addTurn(0)">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
label="Tuesday"
|
||||
ng-click="$ctrl.addTurn(1)">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
label="Wednesday"
|
||||
ng-click="$ctrl.addTurn(2)">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
label="Thursday"
|
||||
ng-click="$ctrl.addTurn(3)">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
label="Friday"
|
||||
ng-click="$ctrl.addTurn(4)">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
label="Saturday"
|
||||
ng-click="$ctrl.addTurn(5)">
|
||||
</vn-button>
|
||||
<vn-button
|
||||
label="Sunday"
|
||||
ng-click="$ctrl.addTurn(6)">
|
||||
</vn-button>
|
||||
</vn-tool-bar>
|
||||
</div>
|
||||
</tpl-body>
|
||||
</vn-dialog>
|
||||
|
||||
<!-- Edit Popover -->
|
||||
<vn-popover class="edit" vn-id="edit">
|
||||
<vn-horizontal pad-medium class="header">
|
||||
<h5>MANÁ: {{$ctrl.workerMana}}</h5>
|
||||
</vn-horizontal>
|
||||
<div pad-medium>
|
||||
<h5>{{$ctrl.client.name}}</h5>
|
||||
<vn-textfield
|
||||
label="Quantity"
|
||||
model="$ctrl.edit.quantity"
|
||||
type="number">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
label="Price"
|
||||
model="$ctrl.edit.price"
|
||||
type="number">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
label="Discount"
|
||||
model="$ctrl.edit.discount"
|
||||
type="number">
|
||||
</vn-textfield>
|
||||
<vn-button
|
||||
label="Save"
|
||||
ng-click="$ctrl.updateLine()">
|
||||
</vn-button>
|
||||
</div>
|
||||
</vn-popover>
|
||||
|
||||
<!-- Transfer Popover -->
|
||||
<vn-popover class="transfer" vn-id="transfer">
|
||||
<div pad-medium>
|
||||
<table class="vn-grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th number translate>ID</th>
|
||||
<th number translate>F. envio</th>
|
||||
<th number translate>Agencia</th>
|
||||
<th number translate>Almacen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="$ctrl.lastThreeTickets.length === 0" ><td colspan="4" style="text-align: center" translate>No results</td></tr>
|
||||
<tr
|
||||
class="clickable"
|
||||
ng-repeat="ticket in $ctrl.lastThreeTickets track by ticket.id"
|
||||
ng-click="$ctrl.moveLines(ticket.id)">
|
||||
<td number>{{::ticket.id}}</td>
|
||||
<td number>{{::ticket.shipped | date: 'dd/MM/yyyy HH:mm'}}</td>
|
||||
<td number>{{::ticket.agencyName}}</td>
|
||||
<td number>{{::ticket.warehouseName}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Move to ticket"
|
||||
model="$ctrl.moveToTicketFk"
|
||||
type="number">
|
||||
</vn-textfield>
|
||||
<vn-icon-button
|
||||
pointer
|
||||
icon="arrow_forward_ios"
|
||||
ng-click="$ctrl.moveLines($ctrl.moveToTicketFk)">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
<!-- <vn-button
|
||||
pointer
|
||||
label="New ticket"
|
||||
ng-click="$ctrl.showticketCreate()">
|
||||
</vn-button> -->
|
||||
</div>
|
||||
</vn-popover>
|
||||
</vn-vertical>
|
||||
<vn-confirm
|
||||
vn-id="deleteConfirmation"
|
||||
on-response="$ctrl.returnDeleteTicketDialog(response)"
|
||||
question="You are going to delete this ticket"
|
||||
message="Continue anyway?">
|
||||
</vn-confirm>
|
||||
|
|
|
@ -1,13 +1,29 @@
|
|||
import ngModule from '../module';
|
||||
import FilterTicketList from '../filter-ticket-list';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends FilterTicketList {
|
||||
constructor($scope, $timeout, $stateParams, $http) {
|
||||
constructor($scope, $timeout, $stateParams, $http, $state, vnApp) {
|
||||
super($scope, $timeout, $stateParams);
|
||||
this.$ = $scope;
|
||||
this.vnApp = vnApp;
|
||||
this.$timeout = $timeout;
|
||||
this.onOrder('itemFk', 'ASC');
|
||||
this.$state = $stateParams;
|
||||
this.$http = $http;
|
||||
this.deletable = false;
|
||||
this.moreOptions = [
|
||||
{callback: this.showAddTurnDialog, name: "Add turn"},
|
||||
{callback: this.showDeleteTicketDialog, name: "Delete ticket"}
|
||||
];
|
||||
}
|
||||
|
||||
get isEditable() {
|
||||
try {
|
||||
return !this.ticket.tracking.state.alertLevel;
|
||||
} catch (e) {}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
get isChecked() {
|
||||
|
@ -20,6 +36,22 @@ class Controller extends FilterTicketList {
|
|||
return false;
|
||||
}
|
||||
|
||||
getCheckedLines() {
|
||||
let lines = [];
|
||||
let data = this.$.index.model.instances;
|
||||
if (data)
|
||||
for (let i = 0; i < data.length; i++)
|
||||
if (data[i].checked)
|
||||
lines.push({id: data[i].id, instance: i});
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
onMoreChange(callback) {
|
||||
callback.call(this);
|
||||
}
|
||||
|
||||
// Change State
|
||||
onStateOkClick() {
|
||||
let filter = {where: {code: "OK"}, fields: ["id"]};
|
||||
let json = encodeURIComponent(JSON.stringify(filter));
|
||||
|
@ -30,41 +62,153 @@ class Controller extends FilterTicketList {
|
|||
|
||||
onStateChange(value) {
|
||||
let params = {ticketFk: this.$state.params.id, stateFk: value};
|
||||
this.$http.post(`/ticket/api/TicketTrackings`, params).then(() => {
|
||||
this.$http.post(`/ticket/api/TicketTrackings/changeState`, params).then(() => {
|
||||
this.card.reload();
|
||||
this.vnApp.showMessage(this.translate.instant('Data saved'));
|
||||
});
|
||||
}
|
||||
|
||||
onRemoveLinesClick() {
|
||||
let lines = {
|
||||
delete: []
|
||||
};
|
||||
let data = this.$.index.model.instances;
|
||||
if (data)
|
||||
for (let i = 0; i < data.length;) {
|
||||
if (data[i].checked) {
|
||||
lines.delete.push(data[i].id);
|
||||
data.splice(i, 1);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
let query = `/ticket/api/Sales/crudSale`;
|
||||
this.$http.post(query, lines);
|
||||
// Add Turn
|
||||
showAddTurnDialog() {
|
||||
this.$.addTurn.show();
|
||||
}
|
||||
|
||||
addTurn(day) {
|
||||
let params = {ticketFk: this.$state.params.id, weekDay: day};
|
||||
this.$http.patch(`/ticket/api/TicketWeeklies`, params).then(() => {
|
||||
this.$.addTurn.hide();
|
||||
});
|
||||
}
|
||||
|
||||
// Delete Ticket
|
||||
showDeleteTicketDialog() {
|
||||
this.$.deleteConfirmation.show();
|
||||
}
|
||||
|
||||
returnDeleteTicketDialog(response) {
|
||||
if (response === 'ACCEPT')
|
||||
this.deleteTicket();
|
||||
}
|
||||
|
||||
deleteTicket() {
|
||||
let params = {id: this.$state.params.id};
|
||||
this.$http.post(`/ticket/api/Tickets/deleted`, params).then(() => {
|
||||
this.$state.go('ticket.list');
|
||||
});
|
||||
}
|
||||
|
||||
// Remove Lines
|
||||
onRemoveLinesClick() {
|
||||
let sales = this.getCheckedLines();
|
||||
let params = {sales: sales, actualTicketFk: this.ticket.id};
|
||||
let query = `/ticket/api/Sales/removes`;
|
||||
this.$http.post(query, params).then(() => {
|
||||
this.removeInstances(sales);
|
||||
});
|
||||
}
|
||||
|
||||
// Move Lines
|
||||
showTransferPopover(event) {
|
||||
let filter = {clientFk: this.ticket.clientFk, ticketFk: this.ticket.id};
|
||||
let json = encodeURIComponent(JSON.stringify(filter));
|
||||
this.$http.get(`/ticket/api/Tickets/threeLastActive?filter=${json}`).then(res => {
|
||||
this.lastThreeTickets = res.data;
|
||||
});
|
||||
this.$.transfer.parent = event.target;
|
||||
this.$.transfer.show();
|
||||
}
|
||||
|
||||
moveLines(ticketID) {
|
||||
let sales = this.getCheckedLines();
|
||||
|
||||
let params = {sales: sales, newTicketFk: ticketID, actualTicketFk: this.ticket.id};
|
||||
this.$http.post(`/ticket/api/Sales/moveToTicket`, params).then(() => {
|
||||
this.goToTicket(ticketID);
|
||||
});
|
||||
}
|
||||
|
||||
/* newTicket() {
|
||||
let params = [this.ticket.clientFk, this.ticket.warehouseFk, this.ticket.companyFk, this.ticket.addressFk, this.ticket.agencyModeFk, null];
|
||||
this.$http.post(`/ticket/api/Tickets/create`, params).then(res => {
|
||||
console.log(res);
|
||||
});
|
||||
}*/
|
||||
|
||||
goToTicket(ticketID) {
|
||||
this.$state.go("ticket.card.sale", {id: ticketID});
|
||||
}
|
||||
|
||||
removeInstances(instances) {
|
||||
for (let i = instances.length - 1; i >= 0; i--) {
|
||||
this.$.index.model.instances.splice(instances[i].instance, 1);
|
||||
}
|
||||
}
|
||||
// Item Descriptor
|
||||
showDescriptor(event, itemFk) {
|
||||
this.$.descriptor.itemFk = itemFk;
|
||||
this.$.descriptor.parent = event.target;
|
||||
this.$.descriptor.show();
|
||||
}
|
||||
|
||||
onDescriptorLoad() {
|
||||
this.$.popover.relocate();
|
||||
}
|
||||
|
||||
// Ticket Create
|
||||
showticketCreate() {
|
||||
console.log(this);
|
||||
this.$.newTicket.show();
|
||||
}
|
||||
|
||||
onResponse(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
let newTicketID = this.$.newTicket.dialog.createTicket();
|
||||
console.log(newTicketID);
|
||||
}
|
||||
}
|
||||
// Edit Line
|
||||
_getworkerMana() {
|
||||
this.$http.get(`/api/WorkerManas/getCurrentWorkerMana`).then(res => {
|
||||
this.workerMana = res.data[0].mana;
|
||||
});
|
||||
}
|
||||
|
||||
showEditPopover(event, sale) {
|
||||
this.sale = sale;
|
||||
this.edit = {
|
||||
id: sale.id,
|
||||
quantity: sale.quantity,
|
||||
price: sale.price,
|
||||
discount: sale.discount
|
||||
};
|
||||
this.$.edit.parent = event.target;
|
||||
this._getworkerMana();
|
||||
this.$.edit.show();
|
||||
}
|
||||
|
||||
updateLine() {
|
||||
if (this.edit.quantity != this.sale.quantity) {
|
||||
this.$http.post(`/ticket/api/Sales/updateQuantity`, {id: this.edit.id, quantity: this.edit.quantity}).then(() => {
|
||||
this.sale.quantity = this.edit.quantity;
|
||||
});
|
||||
}
|
||||
|
||||
if (this.edit.price != this.sale.price) {
|
||||
this.$http.post(`/ticket/api/Sales/updatePrice`, {id: this.edit.id, price: this.edit.price}).then(() => {
|
||||
this.sale.price = this.edit.price;
|
||||
});
|
||||
}
|
||||
|
||||
if (this.edit.discount != this.sale.discount) {
|
||||
this.$http.post(`/ticket/api/Sales/updateDiscount`, {id: this.edit.id, discount: this.edit.discount}).then(() => {
|
||||
this.sale.discount = this.edit.discount;
|
||||
});
|
||||
}
|
||||
this.$.edit.hide();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$timeout', '$state', '$http'];
|
||||
Controller.$inject = ['$scope', '$timeout', '$state', '$http', 'vnApp'];
|
||||
|
||||
ngModule.component('vnTicketSale', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Ticket', () => {
|
||||
xdescribe('Ticket', () => {
|
||||
describe('Component vnTicketSale', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
|
@ -57,7 +57,7 @@ describe('Ticket', () => {
|
|||
|
||||
describe('onStateChange()', () => {
|
||||
it('should perform a post and then call a function', () => {
|
||||
$httpBackend.expectPOST(`/ticket/api/TicketTrackings`).respond();
|
||||
$httpBackend.expectPOST(`/ticket/api/TicketTrackings/changeState`).respond();
|
||||
controller.card = {reload: () => {}};
|
||||
controller.onStateChange(3);
|
||||
$httpBackend.flush();
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
@import "colors";
|
||||
|
||||
vn-popover.edit {
|
||||
|
||||
& div.popover{
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
& vn-horizontal.header{
|
||||
background-color: $main-01;
|
||||
text-align: center;
|
||||
|
||||
& h5{
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vn-ticket-sale{
|
||||
& tr .mdl-textfield{
|
||||
width: inherit;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
vn-popover.transfer{
|
||||
& table {
|
||||
min-width: 650px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
& i {
|
||||
padding-top: 0.2em;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
|
||||
vn-dialog.ticket-create{
|
||||
& vn-button[label=Cancel]{
|
||||
display: none;
|
||||
}
|
||||
& vn-card.vn-ticket-create{
|
||||
padding: 0!important;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<div pad-large style="min-width: 30em">
|
||||
<form ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Nickname"
|
||||
model="filter.nickname"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Ticket id"
|
||||
model="filter.id">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Client id"
|
||||
model="filter.clientFk">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="From"
|
||||
model="filter.from">
|
||||
</vn-date-picker>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="To"
|
||||
model="filter.to">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
label="Agency"
|
||||
field="filter.agencyModeFk"
|
||||
url="/api/AgencyModes"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
<tpl-item>{{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
label="Warehouse"
|
||||
field="filter.warehouseFk"
|
||||
url="/api/Warehouses"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-large-top>
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,7 @@
|
|||
import ngModule from '../module';
|
||||
import SearchPanel from 'core/src/components/searchbar/search-panel';
|
||||
|
||||
ngModule.component('vnTicketSearchPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: SearchPanel
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
Ticket id: Id ticket
|
||||
Client id: Id cliente
|
||||
Nickname: Alias
|
||||
From: Desde
|
||||
To: Hasta
|
||||
Agency: Agencia
|
||||
Warehouse: Almacén
|
|
@ -1,5 +1,6 @@
|
|||
export * from './module';
|
||||
|
||||
import './search-panel';
|
||||
import './index';
|
||||
import './create';
|
||||
import './card';
|
||||
|
|
|
@ -192,7 +192,7 @@ export default {
|
|||
itemTags: {
|
||||
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
||||
tagsButton: `vn-menu-item a[ui-sref="item.card.tags"]`,
|
||||
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) > vn-icon[icon="remove_circle_outline"]`,
|
||||
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) vn-icon-button[icon="remove_circle_outline"]`,
|
||||
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||
firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete > div > div > input`,
|
||||
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||
|
@ -218,7 +218,7 @@ export default {
|
|||
fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
||||
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`,
|
||||
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`,
|
||||
addItemTagButton: `vn-icon[icon="add_circle"]`,
|
||||
addItemTagButton: `vn-icon-button[icon="add_circle"]`,
|
||||
submitItemTagsButton: `${components.vnSubmit}`
|
||||
},
|
||||
itemTax: {
|
||||
|
|
|
@ -23,7 +23,7 @@ describe('Ticket', () => {
|
|||
it('should search for the ticket with id 1', () => {
|
||||
return nightmare
|
||||
.wait(selectors.ticketsIndex.searchTicketInput)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, '1')
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||
.click(selectors.ticketsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||
|
|
|
@ -23,7 +23,7 @@ describe('Ticket', () => {
|
|||
it('should search for the ticket with id 1', () => {
|
||||
return nightmare
|
||||
.wait(selectors.ticketsIndex.searchTicketInput)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, '1')
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||
.click(selectors.ticketsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||
|
|
|
@ -25,7 +25,7 @@ describe('Ticket', () => {
|
|||
it('should search for the ticket 1', () => {
|
||||
return nightmare
|
||||
.wait(selectors.ticketsIndex.searchResult)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 1)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||
.click(selectors.ticketsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// it('should search for the ticket 1', () => {
|
||||
// return nightmare
|
||||
// .wait(selectors.ticketsIndex.searchResult)
|
||||
// .type(selectors.ticketsIndex.searchTicketInput, 1)
|
||||
// .type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||
// .click(selectors.ticketsIndex.searchButton)
|
||||
// .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
// .countSearchResults(selectors.ticketsIndex.searchResult)
|
||||
|
|
|
@ -25,7 +25,7 @@ describe('Ticket', () => {
|
|||
it('should search for the ticket 1', () => {
|
||||
return nightmare
|
||||
.wait(selectors.ticketsIndex.searchResult)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 1)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||
.click(selectors.ticketsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"angular-translate-loader-partial": "^2.18.1",
|
||||
"flatpickr": "^4.4.6",
|
||||
"fs-extra": "^5.0.0",
|
||||
"js-yaml": "^3.10.0",
|
||||
"material-design-lite": "^1.3.0",
|
||||
"mg-crud": "^1.1.2",
|
||||
"npm": "^5.8.0",
|
||||
|
@ -55,7 +56,6 @@
|
|||
"html-loader": "^0.4.4",
|
||||
"jasmine": "^2.9.0",
|
||||
"jasmine-spec-reporter": "^4.2.1",
|
||||
"js-yaml": "^3.10.0",
|
||||
"karma": "^1.7.1",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
USE `vn`;
|
||||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `buy` AS
|
||||
SELECT
|
||||
`c`.`Id_Compra` AS `id`,
|
||||
`c`.`Id_Entrada` AS `entryFk`,
|
||||
`c`.`Id_Article` AS `itemFk`,
|
||||
`c`.`Costefijo` AS `buyingValue`,
|
||||
`c`.`Cantidad` AS `quantity`,
|
||||
`c`.`Id_Cubo` AS `packageFk`,
|
||||
`c`.`Etiquetas` AS `stickers`,
|
||||
`c`.`Portefijo` AS `freightValue`,
|
||||
`c`.`Embalajefijo` AS `packageValue`,
|
||||
`c`.`Comisionfija` AS `comissionValue`,
|
||||
`c`.`Packing` AS `packing`,
|
||||
`c`.`grouping` AS `grouping`,
|
||||
`c`.`caja` AS `groupingMode`,
|
||||
`c`.`Nicho` AS `location`,
|
||||
`c`.`Tarifa1` AS `price1`,
|
||||
`c`.`Tarifa2` AS `price2`,
|
||||
`c`.`Tarifa3` AS `price3`,
|
||||
`c`.`PVP` AS `minPrice`,
|
||||
`c`.`Productor` AS `producer`,
|
||||
`c`.`Vida` AS `printedStickers`,
|
||||
`c`.`punteo` AS `isChecked`,
|
||||
`c`.`buy_edi_id` AS `ektFk`,
|
||||
`c`.`Novincular` AS `isIgnored`
|
||||
FROM
|
||||
`vn2008`.`Compres` `c`;
|
|
@ -0,0 +1,45 @@
|
|||
USE `edi`;
|
||||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `edi`.`ekt` AS
|
||||
SELECT
|
||||
`vn2008`.`buy_edi`.`id` AS `id`,
|
||||
`vn2008`.`buy_edi`.`barcode` AS `barcode`,
|
||||
`vn2008`.`buy_edi`.`entry_year` AS `entry_year`,
|
||||
`vn2008`.`buy_edi`.`delivery_number` AS `delivery_number`,
|
||||
`vn2008`.`buy_edi`.`fec` AS `fec`,
|
||||
`vn2008`.`buy_edi`.`hor` AS `hor`,
|
||||
`vn2008`.`buy_edi`.`now` AS `now`,
|
||||
`vn2008`.`buy_edi`.`ptj` AS `ptj`,
|
||||
`vn2008`.`buy_edi`.`ref` AS `ref`,
|
||||
`vn2008`.`buy_edi`.`item` AS `item`,
|
||||
`vn2008`.`buy_edi`.`pac` AS `pac`,
|
||||
`vn2008`.`buy_edi`.`qty` AS `qty`,
|
||||
`vn2008`.`buy_edi`.`ori` AS `ori`,
|
||||
`vn2008`.`buy_edi`.`cat` AS `cat`,
|
||||
`vn2008`.`buy_edi`.`agj` AS `agj`,
|
||||
`vn2008`.`buy_edi`.`kop` AS `kop`,
|
||||
`vn2008`.`buy_edi`.`ptd` AS `ptd`,
|
||||
`vn2008`.`buy_edi`.`sub` AS `sub`,
|
||||
`vn2008`.`buy_edi`.`pro` AS `pro`,
|
||||
`vn2008`.`buy_edi`.`pri` AS `pri`,
|
||||
`vn2008`.`buy_edi`.`package` AS `package`,
|
||||
`vn2008`.`buy_edi`.`auction` AS `auction`,
|
||||
`vn2008`.`buy_edi`.`klo` AS `klo`,
|
||||
`vn2008`.`buy_edi`.`k01` AS `k01`,
|
||||
`vn2008`.`buy_edi`.`k02` AS `k02`,
|
||||
`vn2008`.`buy_edi`.`k03` AS `k03`,
|
||||
`vn2008`.`buy_edi`.`k04` AS `k04`,
|
||||
`vn2008`.`buy_edi`.`s1` AS `s1`,
|
||||
`vn2008`.`buy_edi`.`s2` AS `s2`,
|
||||
`vn2008`.`buy_edi`.`s3` AS `s3`,
|
||||
`vn2008`.`buy_edi`.`s4` AS `s4`,
|
||||
`vn2008`.`buy_edi`.`s5` AS `s5`,
|
||||
`vn2008`.`buy_edi`.`s6` AS `s6`,
|
||||
`vn2008`.`buy_edi`.`ok` AS `ok`,
|
||||
`vn2008`.`buy_edi`.`trolley_id` AS `trolley_id`,
|
||||
`vn2008`.`buy_edi`.`scanned` AS `scanned`
|
||||
FROM
|
||||
`vn2008`.`buy_edi`;
|
|
@ -0,0 +1,40 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `itemLastEntries`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `itemLastEntries`(vItem INT, vDays DATE)
|
||||
BEGIN
|
||||
SELECT
|
||||
w.id AS warehouseFk,
|
||||
tr.landed,
|
||||
b.entryFk,
|
||||
b.isIgnored,
|
||||
b.price2,
|
||||
b.price3,
|
||||
b.stickers,
|
||||
b.packing,
|
||||
b.grouping,
|
||||
i.stems,
|
||||
b.quantity,
|
||||
b.buyingValue,
|
||||
b.packageFk ,
|
||||
s.id AS supplierFk
|
||||
FROM itemType it
|
||||
RIGHT JOIN (entry e
|
||||
LEFT JOIN supplier s ON s.id = e.supplierFk
|
||||
RIGHT JOIN buy b ON b.entryFk = e.id
|
||||
LEFT JOIN item i ON i.id = b.itemFk
|
||||
LEFT JOIN ink ON ink.id = i.inkFk
|
||||
LEFT JOIN travel tr ON tr.id = e.travelFk
|
||||
LEFT JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
LEFT JOIN origin o ON o.id = i.originFk
|
||||
) ON it.id = i.typeFk
|
||||
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id
|
||||
WHERE b.itemFk = vItem And tr.shipped BETWEEN vDays AND CURDATE()
|
||||
ORDER BY tr.landed DESC , b.id DESC;
|
||||
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `ticketComponentMakeUpdate`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `ticketComponentMakeUpdate`(
|
||||
vTicketFk INT,
|
||||
vClientFk INT,
|
||||
vAgencyModeFk INT,
|
||||
vAddressFk INT,
|
||||
vWarehouseFk INT,
|
||||
vShipped DATETIME,
|
||||
vLanded DATE,
|
||||
vIsDeleted BOOLEAN,
|
||||
vHasToBeUnrouted BOOLEAN,
|
||||
vOption INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Calcula los componentes de un ticket
|
||||
* y los actualiza con los nuevos datos.
|
||||
*
|
||||
* @param vTicketFk Id del ticket
|
||||
* @param vClientFk Id del cliente
|
||||
* @param vAgencyModeFk Id del tipo de agencia
|
||||
* @param vAddressFk Id del consignatario
|
||||
* @param vWarehouseFk Id del almacén
|
||||
* @param vShipped Fecha de salida
|
||||
* @param vLanded Fecha de llegada
|
||||
* @param vIsDeleted Marcado como eliminado
|
||||
* @param vHasToBeUnrouted Marcado para sacar de ruta
|
||||
* @param vOption Id de la acción ticketUpdateAction
|
||||
*/
|
||||
|
||||
CALL vn.ticketComponentPreview (vTicketFk, vLanded, vAddressFk, vAgencyModeFk, vWarehouseFk);
|
||||
CALL vn.ticketComponentUpdate (
|
||||
vTicketFk,
|
||||
vClientFk,
|
||||
vAgencyModeFk,
|
||||
vAddressFk,
|
||||
vWarehouseFk,
|
||||
vShipped,
|
||||
vLanded,
|
||||
vIsDeleted,
|
||||
vHasToBeUnrouted,
|
||||
vOption
|
||||
);
|
||||
|
||||
DROP TEMPORARY TABLE
|
||||
tmp.ticketComponent,
|
||||
tmp.ticketComponentPrice;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `ticketComponentPreview`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentPreview`(
|
||||
vTicketFk INT,
|
||||
vDate DATE,
|
||||
vAddressFk INT,
|
||||
vAgencyModeFk INT,
|
||||
vWarehouseFk SMALLINT)
|
||||
BEGIN
|
||||
/**
|
||||
* Devuelve un listado previo de
|
||||
* componentes para un ticket
|
||||
*
|
||||
* @param vTicketFk Id del ticket
|
||||
* @param vDate Fecha de envÃo
|
||||
* @param vAddressFk Id del consignatario
|
||||
* @param vAgencyModeFk Id del modo de agencia
|
||||
* @param vWarehouseFk Id del almacén
|
||||
*/
|
||||
DECLARE vAgencyFk INT;
|
||||
DECLARE vShipped DATE;
|
||||
DECLARE vBuyOrderItem INT DEFAULT 100;
|
||||
|
||||
SELECT agencyFk INTO vAgencyFk
|
||||
FROM agencyMode
|
||||
WHERE id = vAgencyModeFk;
|
||||
|
||||
CALL agencyHourOffer(vDate, vAddressFk, vAgencyFk);
|
||||
|
||||
SELECT shipped INTO vShipped
|
||||
FROM tmp.agencyHourOffer
|
||||
WHERE warehouseFk = vWarehouseFK;
|
||||
|
||||
CALL buyUltimate(vWarehouseFK, vShipped);
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
|
||||
CREATE TEMPORARY TABLE tmp.ticketLot ENGINE = MEMORY (
|
||||
SELECT
|
||||
vWarehouseFK AS warehouseFk,
|
||||
NULL AS available,
|
||||
s.itemFk,
|
||||
bu.buyFk
|
||||
FROM sale s
|
||||
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
|
||||
WHERE s.ticketFk = vTicketFk
|
||||
AND s.itemFk != vBuyOrderItem
|
||||
GROUP BY bu.warehouseFk, bu.itemFk);
|
||||
|
||||
CALL ticketComponentCalculate(vAddressFk, vAgencyModeFk);
|
||||
|
||||
REPLACE INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost)
|
||||
SELECT t.warehouseFk, s.itemFk, sc.componentFk, sc.value
|
||||
FROM saleComponent sc
|
||||
JOIN sale s ON s.id = sc.saleFk
|
||||
JOIN ticket t ON t.id = s.ticketFk
|
||||
JOIN componentRate cr ON cr.id = sc.componentFk
|
||||
WHERE s.ticketFk = vTicketFk AND NOT cr.isRenewable;
|
||||
|
||||
SET @shipped = vShipped;
|
||||
|
||||
DROP TEMPORARY TABLE
|
||||
tmp.agencyHourOffer,
|
||||
tmp.buyUltimate,
|
||||
tmp.ticketLot;
|
||||
|
||||
IF IFNULL(vShipped, CURDATE() - 1) < CURDATE() THEN
|
||||
CALL util.throw('NO_AGENCY_AVAILABLE');
|
||||
END IF;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
|
@ -1,55 +0,0 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `ticketComponentPriceDifference`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentPriceDifference`(
|
||||
vTicketFk INT,
|
||||
vDate DATE,
|
||||
vAddressFk INT,
|
||||
vAgencyModeFk INT,
|
||||
vWarehouseFk INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Devuelve las diferencias de precio
|
||||
* de los movimientos de un ticket.
|
||||
*
|
||||
* @param vTicketFk Id del ticket
|
||||
* @param vDate Fecha de envÃo
|
||||
* @param vAddressFk Id del consignatario
|
||||
* @param vAgencyModeFk Id del modo de agencia
|
||||
* @param vWarehouseFk Id del almacén
|
||||
*/
|
||||
CALL vn.ticketComponentPreview(vTicketFk, vDate, vAddressFk, vAgencyModeFk, vWarehouseFk);
|
||||
|
||||
SELECT
|
||||
s.itemFk,
|
||||
i.name,
|
||||
i.size,
|
||||
i.category,
|
||||
IFNULL(s.quantity, 0) AS quantity,
|
||||
IFNULL(s.price, 0) AS price,
|
||||
ROUND(SUM(tc.cost), 4) AS newPrice,
|
||||
s.quantity * (s.price - ROUND(SUM(cost), 4)) difference,
|
||||
s.id AS saleFk
|
||||
FROM sale s
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN ticket t ON t.id = s.ticketFk
|
||||
LEFT JOIN tmp.ticketComponent tc ON tc.itemFk = s.itemFk
|
||||
AND tc.warehouseFk = t.warehouseFk
|
||||
LEFT JOIN saleComponent sc ON sc.saleFk = s.id
|
||||
AND sc.componentFk = tc.componentFk
|
||||
LEFT JOIN componentRate cr ON cr.id = tc.componentFk
|
||||
WHERE
|
||||
t.id = vTicketFk
|
||||
AND IF(sc.componentFk IS NULL
|
||||
AND cr.classRate IS NOT NULL, FALSE, TRUE)
|
||||
GROUP BY s.id ORDER BY s.id;
|
||||
|
||||
DROP TEMPORARY TABLE
|
||||
tmp.ticketComponent,
|
||||
tmp.ticketComponentPrice;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `ticketComponentUpdate`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `ticketComponentUpdate`(
|
||||
vTicketFk INT,
|
||||
vClientFk INT,
|
||||
vAgencyModeFk INT,
|
||||
vAddressFk INT,
|
||||
vWarehouseFk INT,
|
||||
vShipped DATETIME,
|
||||
vLanded DATE,
|
||||
vIsDeleted BOOLEAN,
|
||||
vHasToBeUnrouted BOOLEAN,
|
||||
vOption INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Actualiza un ticket y sus componentes
|
||||
* con los nuevos datos.
|
||||
*
|
||||
* @param vTicketFk Id del ticket
|
||||
* @param vClientFk Id del cliente
|
||||
* @param vAgencyModeFk Id del tipo de agencia
|
||||
* @param vAddressFk Id del consignatario
|
||||
* @param vWarehouseFk Id del almacén
|
||||
* @param vShipped Fecha de salida
|
||||
* @param vLanded Fecha de llegada
|
||||
* @param vIsDeleted Marcado como eliminado
|
||||
* @param vHasToBeUnrouted Marcado para sacar de ruta
|
||||
* @param vOption Id de la acción ticketUpdateAction
|
||||
*/
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
UPDATE ticket t
|
||||
SET
|
||||
t.clientFk = vClientFk,
|
||||
t.agencyModeFk = vAgencyModeFk,
|
||||
t.addressFk = vAddressFk,
|
||||
t.warehouseFk = vWarehouseFk,
|
||||
t.landed = vLanded,
|
||||
t.shipped = vShipped,
|
||||
t.isDeleted = vIsDeleted
|
||||
WHERE
|
||||
t.id = vTicketFk;
|
||||
|
||||
IF vHasToBeUnrouted THEN
|
||||
UPDATE ticket t SET t.routeFk = NULL
|
||||
WHERE t.id = vTicketFk;
|
||||
END IF;
|
||||
|
||||
IF vOption <> 8 THEN
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
|
||||
CREATE TEMPORARY TABLE tmp.sale
|
||||
(PRIMARY KEY (saleFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT id AS saleFk, vWarehouseFk warehouseFk
|
||||
FROM sale s WHERE s.ticketFk = vTicketFk;
|
||||
|
||||
CALL ticketComponentUpdateSale (vOption);
|
||||
|
||||
DROP TEMPORARY TABLE tmp.sale;
|
||||
END IF;
|
||||
COMMIT;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -328,16 +328,16 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
|
|||
|
||||
INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `created`)
|
||||
VALUES
|
||||
(1, 1, 1, 5, CURDATE()),
|
||||
(2, 2, 2, 5, CURDATE()),
|
||||
(3, 3, 3, 5, CURDATE()),
|
||||
(4, 4, 1, 5, CURDATE()),
|
||||
(5, 5, 2, 18, CURDATE()),
|
||||
(6, 6, 3, 18, CURDATE()),
|
||||
(7, 7, 1, 18, CURDATE()),
|
||||
(8, 8, 2, 19, CURDATE()),
|
||||
(9, 9, 3, 19, CURDATE()),
|
||||
(10, 10, 3, 19, CURDATE()),
|
||||
(1, 1, 13, 5, CURDATE()),
|
||||
(2, 2, 15, 5, CURDATE()),
|
||||
(3, 3, 16, 5, CURDATE()),
|
||||
(4, 4, 13, 5, CURDATE()),
|
||||
(5, 5, 15, 18, CURDATE()),
|
||||
(6, 6, 16, 18, CURDATE()),
|
||||
(7, 7, 13, 18, CURDATE()),
|
||||
(8, 8, 15, 19, CURDATE()),
|
||||
(9, 9, 16, 19, CURDATE()),
|
||||
(10, 10, 13, 19, CURDATE()),
|
||||
(11, 11, 3, 19, CURDATE()),
|
||||
(12, 12, 3, 19, CURDATE()),
|
||||
(13, 13, 3, 19, CURDATE()),
|
||||
|
@ -346,9 +346,9 @@ INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `crea
|
|||
(16, 16, 1, 19, CURDATE()),
|
||||
(17, 17, 1, 19, CURDATE()),
|
||||
(18, 18, 1, 19, CURDATE()),
|
||||
(19, 19, 1, 19, CURDATE()),
|
||||
(20, 20, 1, 19, CURDATE()),
|
||||
(21, 21, 1, 19, CURDATE());
|
||||
(19, 19, 13, 19, CURDATE()),
|
||||
(20, 20, 15, 19, CURDATE()),
|
||||
(21, 21, 16, 19, CURDATE());
|
||||
|
||||
INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`)
|
||||
VALUES
|
||||
|
@ -631,12 +631,12 @@ INSERT INTO `vn`.`ticketWeekly`(`ticketFk`, `weekDay`)
|
|||
( 4, 4),
|
||||
( 5, 6);
|
||||
|
||||
INSERT INTO `vn`.`travel`(`id`, `landed`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `m3`, `kg`)
|
||||
INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `m3`, `kg`)
|
||||
VALUES
|
||||
( 1, CURDATE(), 1, 2, 1, 100.00, 1000),
|
||||
( 2, CURDATE(), 1, 2, 1, 150, 2000),
|
||||
( 3, CURDATE(), 1, 2, 1, 0.00, 0.00),
|
||||
( 4, CURDATE(), 1, 2, 1, 50.00, 500);
|
||||
( 1, CURDATE(), CURDATE(), 1, 2, 1, 100.00, 1000),
|
||||
( 2, CURDATE(), CURDATE(), 1, 2, 1, 150, 2000),
|
||||
( 3, CURDATE(), CURDATE(), 1, 2, 1, 0.00, 0.00),
|
||||
( 4, CURDATE(), CURDATE(), 1, 2, 1, 50.00, 500);
|
||||
|
||||
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `companyFk`)
|
||||
VALUES
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"name": "Warehouse",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "warehouse",
|
||||
"database": "vn"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"name": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -40,6 +40,7 @@ module.exports = function(Self) {
|
|||
street: data.street,
|
||||
city: data.city,
|
||||
provinceFk: data.provinceFk,
|
||||
countryFk: data.countryFk,
|
||||
isEqualizated: data.isEqualizated
|
||||
};
|
||||
newClient = await Self.create(client);
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
module.exports = function(Client) {
|
||||
Client.installMethod('filter', filterClients);
|
||||
|
||||
function filterClients(params) {
|
||||
let filters = {
|
||||
where: {},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size
|
||||
};
|
||||
|
||||
delete params.page;
|
||||
delete params.size;
|
||||
|
||||
if (params.search) {
|
||||
filters.where.and = [
|
||||
{
|
||||
or: [
|
||||
{id: params.search},
|
||||
{name: {regexp: params.search}}
|
||||
]
|
||||
}
|
||||
];
|
||||
delete params.search;
|
||||
}
|
||||
|
||||
if (params.phone) {
|
||||
let phones = [
|
||||
{phone: params.phone},
|
||||
{mobile: params.phone}
|
||||
];
|
||||
if (filters.where.and) {
|
||||
filters.where.and.push(
|
||||
{
|
||||
or: phones
|
||||
}
|
||||
);
|
||||
} else {
|
||||
filters.where.or = phones;
|
||||
}
|
||||
delete params.phone;
|
||||
}
|
||||
|
||||
let properties = Object.keys(params);
|
||||
if (properties.length) {
|
||||
properties.forEach(
|
||||
property => {
|
||||
let propertyToBeEqual = (property === 'postcode' || property === 'fi' || property === 'id');
|
||||
if (filters.where.and) {
|
||||
let filter = {};
|
||||
filter[property] = propertyToBeEqual ? params[property] : {regexp: params[property]};
|
||||
filters.where.and.push(filter);
|
||||
} else {
|
||||
filters.where[property] = propertyToBeEqual ? params[property] : {regexp: params[property]};
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
};
|
|
@ -47,9 +47,10 @@ module.exports = Self => {
|
|||
FROM vn.itemBotanical ib WHERE itemFk = ?`;
|
||||
promises.push(Self.rawSql(createBotanical, [newItem.id, origin.id]));
|
||||
|
||||
let createTags = `INSERT INTO vn.itemTag (itemFk, tagFk, value, priority)
|
||||
SELECT ?, tagFk, value, priority
|
||||
FROM vn.itemTag WHERE itemFk = ?`;
|
||||
let createTags = `INSERT INTO vn.itemTag(itemFk, tagFk, value, priority)
|
||||
SELECT ?, i.tagFk, i.value,i.priority
|
||||
FROM vn.itemTag i WHERE i.itemFk = ?
|
||||
ON DUPLICATE KEY UPDATE value = i.value, priority = i.priority`;
|
||||
promises.push(Self.rawSql(createTags, [newItem.id, origin.id]));
|
||||
|
||||
let createTax = `REPLACE INTO vn.itemTaxCountry (itemFk, countryFk, taxClassFk)
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installMethod('filter', filterParams);
|
||||
|
||||
function filterParams(params) {
|
||||
let filter = {
|
||||
where: {},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size,
|
||||
order: params.order || 'name ASC', // name, relevancy DESC
|
||||
include: [
|
||||
{relation: 'itemType',
|
||||
scope: {
|
||||
fields: ['name', 'workerFk'],
|
||||
include: {
|
||||
relation: 'worker',
|
||||
fields: ['firstName', 'name']
|
||||
}
|
||||
}
|
||||
},
|
||||
{relation: 'origin'},
|
||||
{relation: 'ink'},
|
||||
{relation: 'producer'},
|
||||
{relation: 'intrastat'},
|
||||
{relation: 'expence'}
|
||||
]
|
||||
};
|
||||
|
||||
delete params.page;
|
||||
delete params.size;
|
||||
delete params.order;
|
||||
|
||||
if (params.search) {
|
||||
filter.where.and = [
|
||||
{
|
||||
or: [
|
||||
{id: params.search},
|
||||
{name: {regexp: params.search}}
|
||||
]
|
||||
}
|
||||
];
|
||||
delete params.search;
|
||||
}
|
||||
|
||||
if (params.itemSize) {
|
||||
params.size = params.itemSize;
|
||||
delete params.itemSize;
|
||||
}
|
||||
|
||||
Object.keys(params).forEach(
|
||||
key => {
|
||||
if (filter.where.and) {
|
||||
let filter = {};
|
||||
filter[key] = (key === 'description' || key === 'name') ? {regexp: params[key]} : params[key];
|
||||
filter.where.and.push(filter);
|
||||
} else {
|
||||
filter.where[key] = (key === 'description' || key === 'name') ? {regexp: params[key]} : params[key];
|
||||
}
|
||||
}
|
||||
);
|
||||
return filter;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('getDiary', {
|
||||
description: 'Returns the ',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'params',
|
||||
type: 'object',
|
||||
description: 'itemFk, warehouseFk'
|
||||
}],
|
||||
returns: {
|
||||
arg: 'diary',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/getDiary`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getDiary = async params => {
|
||||
let [diary] = await Self.rawSql(`CALL vn.itemDiary(?, ?)`, [params.itemFk, params.warehouseFk]);
|
||||
return diary;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('moveToTicket', {
|
||||
description: 'Change the state of a ticket',
|
||||
accessType: '',
|
||||
accepts: [{
|
||||
arg: 'params',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: '[sales IDs], newTicketFk, actualTicketFk',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'string',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/moveToTicket`,
|
||||
verb: 'post'
|
||||
}
|
||||
});
|
||||
|
||||
Self.moveToTicket = async params => {
|
||||
let thisTicketIsEditable = await Self.app.models.Ticket.isEditable(params.actualTicketFk);
|
||||
if (!thisTicketIsEditable)
|
||||
throw new Error(`The sales of this ticket can't be modified`);
|
||||
|
||||
let newTicketIsEditable = await Self.app.models.Ticket.isEditable(params.newTicketFk);
|
||||
if (!newTicketIsEditable)
|
||||
throw new Error(`The sales of this ticket can't be modified`);
|
||||
|
||||
for (let i = 0; i < params.sales.length; i++) {
|
||||
await Self.app.models.Sale.update({id: params.sales[i].id}, {ticketFk: params.newTicketFk});
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('removes', {
|
||||
description: 'Change the state of a ticket',
|
||||
accessType: '',
|
||||
accepts: [{
|
||||
arg: 'params',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: '[sales IDs], actualTicketFk',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'string',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/removes`,
|
||||
verb: 'post'
|
||||
}
|
||||
});
|
||||
|
||||
Self.removes = async params => {
|
||||
let thisTicketIsEditable = await Self.app.models.Ticket.isEditable(params.actualTicketFk);
|
||||
if (!thisTicketIsEditable)
|
||||
throw new Error(`The sales of this ticket can't be modified`);
|
||||
|
||||
for (let i = 0; i < params.sales.length; i++) {
|
||||
await Self.app.models.Sale.destroyById(params.sales[i].id);
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('deleted', {
|
||||
description: 'Sets the isDeleted value of a ticket to 1',
|
||||
accessType: '',
|
||||
accepts: [{
|
||||
arg: 'ticketFk',
|
||||
type: 'Object',
|
||||
required: true,
|
||||
description: 'TicketFk',
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'string',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/deleted`,
|
||||
verb: 'post'
|
||||
}
|
||||
});
|
||||
|
||||
Self.deleted = async params => {
|
||||
return await Self.app.models.Ticket.update({id: params.id}, {isDeleted: '1'});
|
||||
};
|
||||
};
|
|
@ -1,87 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.installMethod('filter', filterParams);
|
||||
|
||||
function filterParams(params) {
|
||||
let filters = {
|
||||
where: {},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size,
|
||||
order: params.order || 'created DESC',
|
||||
include: [
|
||||
{
|
||||
relation: 'address',
|
||||
scope: {
|
||||
fields: ['provinceFk'],
|
||||
include: {
|
||||
relation: 'province',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
relation: 'warehouse',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}, {
|
||||
relation: 'agencyMode',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}, {
|
||||
relation: 'tracking',
|
||||
scope: {
|
||||
fields: ['stateFk'],
|
||||
include: {
|
||||
relation: 'state',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['salesPersonFk'],
|
||||
include: {
|
||||
relation: 'salesPerson',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
delete params.page;
|
||||
delete params.size;
|
||||
delete params.order;
|
||||
|
||||
if (params.search) {
|
||||
filters.where.and = [
|
||||
{
|
||||
or: [
|
||||
{id: params.search},
|
||||
{name: {regexp: params.search}}
|
||||
]
|
||||
}
|
||||
];
|
||||
delete params.search;
|
||||
}
|
||||
|
||||
Object.keys(params).forEach(
|
||||
key => {
|
||||
if (filters.where.and) {
|
||||
let filter = {};
|
||||
filter[key] = (key === 'nickname') ? {regexp: params[key]} : params[key];
|
||||
filters.where.and.push(filter);
|
||||
} else {
|
||||
filters.where[key] = (key === 'nickname') ? {regexp: params[key]} : params[key];
|
||||
}
|
||||
}
|
||||
);
|
||||
return filters;
|
||||
}
|
||||
};
|
|
@ -21,7 +21,7 @@ module.exports = Self => {
|
|||
|
||||
Self.isEditable = async ticketFk => {
|
||||
let state = await Self.app.models.TicketState.findOne({where: {ticketFk: ticketFk}, fields: 'alertLevel'});
|
||||
|
||||
return state != null && state.alertLevel == 0;
|
||||
let exists = await Self.app.models.Ticket.findOne({where: {id: ticketFk}, fields: 'isDeleted'});
|
||||
return (exists && state == null && exists.isDeleted == 0) || (exists.isDeleted == 0 && state.alertLevel == 0);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ describe('ticket componentUpdate()', () => {
|
|||
it('should call the componentUpdate method', done => {
|
||||
let data = {
|
||||
agencyModeFk: 1,
|
||||
addressFk: 121,
|
||||
addressFk: 121,
|
||||
warehouseFk: 1,
|
||||
shipped: Date.now(),
|
||||
landed: Date.now(),
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('threeLastActive', {
|
||||
description: 'Returns the last three tickets of a client that have the alertLevel at 0 and the shiped day is gt today',
|
||||
accessType: '',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'client id, ticketFk'
|
||||
}],
|
||||
returns: {
|
||||
type: [this.modelName],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/threeLastActive`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.threeLastActive = async filter => {
|
||||
console.log(filter);
|
||||
let query = `
|
||||
SELECT t.id,t.shipped,a.name AS agencyName,w.name AS warehouseName
|
||||
FROM vn.ticket t
|
||||
JOIN vn.ticketState ts ON t.id = ts.ticketFk
|
||||
JOIN vn.agencyMode a ON t.agencyModeFk = a.id
|
||||
JOIN vn.warehouse w ON t.warehouseFk = w.id
|
||||
WHERE t.shipped > CURDATE() AND t.clientFk = ? AND ts.alertLevel = 0 AND t.id <> ?
|
||||
ORDER BY t.shipped
|
||||
LIMIT 3`;
|
||||
let result = await Self.rawSql(query, [filter.clientFk, filter.ticketFk]);
|
||||
return result;
|
||||
};
|
||||
};
|
|
@ -10,7 +10,6 @@ module.exports = Self => {
|
|||
require('../methods/client/card')(Self);
|
||||
require('../methods/client/createWithUser')(Self);
|
||||
require('../methods/client/listWorkers')(Self);
|
||||
require('../methods/client/filter')(Self);
|
||||
require('../methods/client/hasCustomerRole')(Self);
|
||||
require('../methods/client/isValidClient')(Self);
|
||||
require('../methods/client/activeSalesPerson')(Self);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
let UserError = require('../helpers').UserError;
|
||||
|
||||
module.exports = Self => {
|
||||
require('../methods/item/filter')(Self);
|
||||
require('../methods/item/clone')(Self);
|
||||
require('../methods/item/updateTaxes')(Self);
|
||||
require('../methods/item/getDiary')(Self);
|
||||
|
||||
Self.validatesPresenceOf('name', {message: 'Cannot be blank'});
|
||||
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});
|
||||
|
|
|
@ -3,4 +3,9 @@ module.exports = Self => {
|
|||
require('../methods/sale/saleComponentFilter')(Self);
|
||||
require('../methods/sale/priceDifference')(Self);
|
||||
require('../methods/sale/crudSale')(Self);
|
||||
require('../methods/sale/moveToTicket')(Self);
|
||||
require('../methods/sale/removes')(Self);
|
||||
// require('../methods/sale/updateDiscount')(Self);
|
||||
// require('../methods/sale/updatePrice')(Self);
|
||||
// require('../methods/sale/updateQuantity')(Self);
|
||||
};
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/ticket/changeTime')(Self);
|
||||
require('../methods/ticket/changeWorker')(Self);
|
||||
require('../methods/ticket/filter')(Self);
|
||||
require('../methods/ticket/getVolume')(Self);
|
||||
require('../methods/ticket/getTotalVolume')(Self);
|
||||
require('../methods/ticket/summary')(Self);
|
||||
require('../methods/ticket/getTotal')(Self);
|
||||
require('../methods/ticket/getTaxes')(Self);
|
||||
require('../methods/ticket/componentUpdate')(Self);
|
||||
// require('../methods/ticket/create')(Self);
|
||||
require('../methods/ticket/isEditable')(Self);
|
||||
require('../methods/ticket/threeLastActive')(Self);
|
||||
require('../methods/ticket/deleted')(Self);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue