Merge branch 'dev' of https://git.verdnatura.es/salix into dev
This commit is contained in:
commit
6136a1c8de
|
@ -30,7 +30,7 @@
|
|||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.address.agencyModeFk"
|
||||
url="/client/api/AgencyModes"
|
||||
url="/client/api/AgencyModes/active"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import ngModule from '../module';
|
||||
import './style.css';
|
||||
|
||||
export default class Controller {
|
||||
constructor($http, $state) {
|
||||
|
|
|
@ -105,9 +105,9 @@
|
|||
<vn-horizontal vn-one>
|
||||
<vn-one margin-medium>
|
||||
<h5 translate>Default address</h5>
|
||||
<p>{{$ctrl.address.nickname}}</p>
|
||||
<p><span>{{$ctrl.address.street}}</span></p>
|
||||
<p><span>{{$ctrl.address.city}}</span></p>
|
||||
<p>{{$ctrl.summary.addresses[0].nickname}}</p>
|
||||
<p><span>{{$ctrl.summary.addresses[0].street}}</span></p>
|
||||
<p><span>{{$ctrl.summary.addresses[0].city}}</span></p>
|
||||
</vn-one>
|
||||
<vn-one margin-medium>
|
||||
<h5 translate>Web access</h5>
|
||||
|
@ -122,23 +122,19 @@
|
|||
</vn-one>
|
||||
<vn-one margin-medium>
|
||||
<h5 translate>Recovery</h5>
|
||||
<vn-vertical ng-if="$ctrl.recovery">
|
||||
<p><vn-label translate>Since</vn-label> {{$ctrl.recovery.started | date:'dd/MM/yyyy'}}</p>
|
||||
<p><vn-label translate>To</vn-label> {{$ctrl.recovery.finished | date:'dd/MM/yyyy'}}</p>
|
||||
<p><vn-label translate>Amount</vn-label> {{$ctrl.recovery.amount | currency:'€':2}}</p>
|
||||
<p><vn-label translate>Period</vn-label> {{$ctrl.recovery.period}}</p>
|
||||
<vn-vertical ng-if="$ctrl.summary.recovery">
|
||||
<p><vn-label translate>Since</vn-label> {{$ctrl.summary.recovery.started | date:'dd/MM/yyyy'}}</p>
|
||||
<p><vn-label translate>To</vn-label> {{$ctrl.summary.recovery.finished | date:'dd/MM/yyyy'}}</p>
|
||||
<p><vn-label translate>Amount</vn-label> {{$ctrl.summary.recovery.amount | currency:'€ ':2}}</p>
|
||||
<p><vn-label translate>Period</vn-label> {{$ctrl.summary.recovery.period}}</p>
|
||||
</vn-vertical>
|
||||
</vn-one>
|
||||
|
||||
</vn-horizontal>
|
||||
<vn-horizontal vn-one>
|
||||
<vn-one margin-medium>
|
||||
<h5 translate>Total greuge</h5>
|
||||
<p><vn-label translate>Total</vn-label> {{$ctrl.greuge.sumAmount | currency:'€':2}}</p>
|
||||
</vn-one>
|
||||
|
||||
<vn-one margin-medium>
|
||||
<h5 translate>Credit</h5>
|
||||
<h5 translate>Financial data</h5>
|
||||
<p><vn-label translate>Mana</vn-label> {{$ctrl.summary.mana.mana | currency:'€ ':2}}</p>
|
||||
<p><vn-label translate>Risk</vn-label> {{$ctrl.summary.debt.debt | currency:'€ ':2}}</p>
|
||||
<p><vn-label translate>Average invoiced</vn-label> {{$ctrl.summary.averageInvoiced.invoiced | currency:'€ ':2}}</p>
|
||||
<p><vn-label translate>Total greuge</vn-label> {{$ctrl.summary.totalGreuge | currency:'€ ':2}}</p>
|
||||
<p>
|
||||
<vn-label translate>Credit</vn-label>
|
||||
{{$ctrl.summary.credit | currency:'€ ':2}}
|
||||
|
|
|
@ -1,73 +1,22 @@
|
|||
import ngModule from '../module';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
|
||||
constructor($http) {
|
||||
this.$http = $http;
|
||||
}
|
||||
|
||||
$onChanges() {
|
||||
if (!this.client || !this.client.id)
|
||||
if (!this.client)
|
||||
return;
|
||||
|
||||
this.getSummary();
|
||||
this.getGreuse();
|
||||
this.getRecoveries();
|
||||
}
|
||||
|
||||
getSummary() {
|
||||
let filter = {
|
||||
include: [
|
||||
{relation: 'account', scope: {fields: ['name', 'active']}},
|
||||
{relation: 'salesPerson', scope: {fields: ['name']}},
|
||||
{relation: 'country', scope: {fields: ['country']}},
|
||||
{relation: 'province', scope: {fields: ['name']}},
|
||||
{relation: 'contactChannel', scope: {fields: ['name']}},
|
||||
{relation: 'payMethod', scope: {fields: ['name']}},
|
||||
{
|
||||
relation: 'addresses',
|
||||
scope: {
|
||||
where: {isDefaultAddress: true},
|
||||
fields: ['nickname', 'street', 'city', 'postalCode']
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
|
||||
let query = `/client/api/Clients/${this.client.id}?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data) {
|
||||
this.$http.get(`/client/api/Clients/${this.client.id}/summary`).then(res => {
|
||||
if (res && res.data)
|
||||
this.summary = res.data;
|
||||
this.address = res.data.addresses[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getGreuse() {
|
||||
let query = `/client/api/Greuges/${this.client.id}/sumAmount`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data)
|
||||
this.greuge = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
getRecoveries() {
|
||||
let filter = {
|
||||
where: {
|
||||
and: [{clientFk: this.client.id}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}]
|
||||
},
|
||||
limit: 1
|
||||
};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
|
||||
let query = `/client/api/Recoveries?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data)
|
||||
this.recovery = res.data[0];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http'];
|
||||
|
||||
ngModule.component('vnClientSummary', {
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
Default address: Consignatario pred.
|
||||
Total greuge: Greuge total
|
||||
Financial data: Datos financieros
|
||||
Mana: Maná
|
||||
Risk: Riesgo
|
||||
Secured credit: Crédito asegurado
|
||||
Average invoiced: Consumo medio
|
|
@ -0,0 +1,3 @@
|
|||
vn-dialog vn-one {
|
||||
min-width: 200px
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
</input>
|
||||
<div class="icons">
|
||||
<vn-icon
|
||||
ng-show="!$ctrl.disabled"
|
||||
icon="clear"
|
||||
class="clear"
|
||||
ng-click="$ctrl.onClearClick($event)"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import Input from '../../lib/input';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
|
@ -11,7 +11,7 @@ import './style.scss';
|
|||
* @property {Object} intialData A initial data to avoid the server request used to get the selection
|
||||
* @property {Boolean} multiple Wether to allow multiple selection
|
||||
*/
|
||||
export default class Autocomplete extends Component {
|
||||
export default class Autocomplete extends Input {
|
||||
constructor($element, $scope, $http, $transclude) {
|
||||
super($element, $scope);
|
||||
this.$http = $http;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
vn-check {
|
||||
float: left;
|
||||
& > .mdl-checkbox {
|
||||
width: initial;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
.vn-grid {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
td, th{
|
||||
text-align: left;
|
||||
padding: 10px;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
info_outline
|
||||
</i>
|
||||
<i class="material-icons pointer"
|
||||
ng-show="$ctrl.hasValue && ($ctrl.hasFocus || $ctrl.hasMouseIn)"
|
||||
ng-show="!$ctrl.disabled && $ctrl.hasValue && ($ctrl.hasFocus || $ctrl.hasMouseIn)"
|
||||
ng-click="$ctrl.clear()">
|
||||
clear
|
||||
</i>
|
||||
|
|
|
@ -37,7 +37,7 @@ class ItemTags {
|
|||
|
||||
addItemTag() {
|
||||
if (this.instancedItemTags) {
|
||||
this.instancedItemTags.push({value: null, itemFk: this.params.id, tagFk: null, priority: null, showAddIcon: true});
|
||||
this.instancedItemTags.push({value: null, itemFk: this.params.id, tagFk: null, priority: this.getMaxPriority(this.instancedItemTags) + 1, showAddIcon: true});
|
||||
this._setIconAdd();
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,15 @@ class ItemTags {
|
|||
}
|
||||
}
|
||||
|
||||
getMaxPriority(instancedItemTags) {
|
||||
let max = 0;
|
||||
instancedItemTags.forEach(tag => {
|
||||
if (tag.priority > max)
|
||||
max = tag.priority;
|
||||
});
|
||||
return max;
|
||||
}
|
||||
|
||||
_equalItemTags(oldTag, newTag) {
|
||||
return oldTag.tagFk === newTag.tagFk && oldTag.value === newTag.value && oldTag.priority === newTag.priority;
|
||||
}
|
||||
|
|
|
@ -96,8 +96,14 @@
|
|||
},
|
||||
{
|
||||
"url" : "/package",
|
||||
"abstract": true,
|
||||
"state": "ticket.card.package",
|
||||
"component": "vn-ticket-package",
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url" : "/index",
|
||||
"state": "ticket.card.package.index",
|
||||
"component": "vn-ticket-package-index",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
},
|
||||
|
@ -109,6 +115,12 @@
|
|||
{
|
||||
"url": "/tracking",
|
||||
"state": "ticket.card.tracking",
|
||||
"abstract": true,
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url" : "/index",
|
||||
"state": "ticket.card.tracking.index",
|
||||
"component": "vn-ticket-tracking",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
|
@ -118,6 +130,14 @@
|
|||
"icon": "remove_red_eye"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/edit",
|
||||
"state": "ticket.card.tracking.edit",
|
||||
"component": "vn-ticket-tracking-edit",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "ticket.card.tracking.create",
|
||||
|
@ -137,6 +157,18 @@
|
|||
"description": "Sale",
|
||||
"icon": "icon-lines"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url" : "/sale-checked",
|
||||
"state": "ticket.card.saleChecked",
|
||||
"component": "vn-ticket-sale-checked",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Sale Checked",
|
||||
"icon": "assignment"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -18,13 +18,13 @@
|
|||
vn-one class="list list-element text-center"
|
||||
pad-small-bottom
|
||||
ng-repeat="expedition in index.model.instances track by expedition.id">
|
||||
<vn-none pad-medium-h style="color:#FFA410;">
|
||||
<vn-one pad-medium-h style="color:#FFA410;">
|
||||
<i
|
||||
pointer
|
||||
class="material-icons"
|
||||
vn-tooltip="delete expedition"
|
||||
ng-click="$ctrl.deleteExpedition(expedition)">delete</i>
|
||||
</vn-none>
|
||||
</vn-one>
|
||||
<vn-one pad-medium-h>{{expedition.itemFk}}</vn-one>
|
||||
<vn-one pad-medium-h>{{expedition.item.name}}</vn-one>
|
||||
<vn-one pad-medium-h>{{expedition.package.name}}</vn-one>
|
||||
|
|
|
@ -19,3 +19,11 @@ Sale: Lineas del pedido
|
|||
Some fields are invalid: Algunos campos no son válidos
|
||||
The observation type must be unique: El tipo de observación debe ser único
|
||||
Tickets: Tickets
|
||||
Date : Fecha
|
||||
Employee : Empleado
|
||||
State: Estado
|
||||
Tracking: Revisión
|
||||
Created : Añadido
|
||||
New : Nuevo
|
||||
New state: Nuevo estado
|
||||
Sale Checked: Control clientes
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import ngModule from '../module';
|
||||
import ngModule from '../../module';
|
||||
|
||||
class Controller {
|
||||
|
||||
|
@ -8,7 +8,6 @@ class Controller {
|
|||
this.$translate = $translate;
|
||||
this.vnApp = vnApp;
|
||||
this.removedPackages = [];
|
||||
this.updatedPackages = [];
|
||||
}
|
||||
|
||||
submit() {
|
||||
|
@ -23,10 +22,16 @@ class Controller {
|
|||
if (typeof item.id === 'undefined')
|
||||
packagesObj.create.push(item);
|
||||
|
||||
if (typeof item.id !== 'undefined' && angular.equals(item, this.oldPackages[item.id]))
|
||||
if (typeof item.id !== 'undefined' && !this.packageEquals(item, this.oldPackages[item.id]))
|
||||
packagesObj.update.push(item);
|
||||
});
|
||||
|
||||
if (this.$.form.$invalid)
|
||||
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid'));
|
||||
|
||||
if (!this.hasChanges(packagesObj))
|
||||
return this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
||||
|
||||
this.$http.post(query, packagesObj).then(res => {
|
||||
this.$.index.accept();
|
||||
});
|
||||
|
@ -55,16 +60,31 @@ class Controller {
|
|||
}
|
||||
|
||||
setOldPackages() {
|
||||
if (this.oldPackages && !this.$.watcher.dataChanged())
|
||||
return;
|
||||
|
||||
this.oldPackages = [];
|
||||
this.removedPackages = [];
|
||||
this.packages.forEach(item => {
|
||||
this.oldPackages[item.id] = item;
|
||||
this.oldPackages[item.id] = Object.assign({}, item);
|
||||
});
|
||||
}
|
||||
|
||||
packageEquals(newPackage, oldPackage) {
|
||||
return newPackage.packagingFk === oldPackage.packagingFk && newPackage.quantity == oldPackage.quantity;
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', '$scope'];
|
||||
hasChanges(packagesObj) {
|
||||
if (packagesObj.create.length || packagesObj.update.length || packagesObj.delete.length)
|
||||
return true;
|
||||
|
||||
ngModule.component('vnTicketPackage', {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', '$scope', '$translate', 'vnApp'];
|
||||
|
||||
ngModule.component('vnTicketPackageIndex', {
|
||||
template: require('./package.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
|
@ -1,7 +1,7 @@
|
|||
import './package.js';
|
||||
|
||||
describe('Ticket', () => {
|
||||
describe('Component vnTicketPackage', () => {
|
||||
describe('Component vnTicketPackageIndex', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
@ -19,7 +19,7 @@ describe('Ticket', () => {
|
|||
accept: function() {}
|
||||
}
|
||||
};
|
||||
controller = $componentController('vnTicketPackage', {$scope: $scope});
|
||||
controller = $componentController('vnTicketPackageIndex', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('removePackage()', () => {
|
||||
|
@ -37,11 +37,11 @@ describe('Ticket', () => {
|
|||
let query = '/ticket/api/TicketPackagings/crudTicketPackaging';
|
||||
controller.removedPackages = [];
|
||||
controller.oldPackages = [
|
||||
{id: 1, quantity: 5, ticketFk: 1}
|
||||
{id: 1, packagingFk: 1, quantity: 5, ticketFk: 1}
|
||||
];
|
||||
controller.packages = [
|
||||
{quantity: 5, ticketFk: 1},
|
||||
{id: 1, quantity: 25, ticketFk: 1}
|
||||
{quantity: 5, packagingFk: 2, ticketFk: 1},
|
||||
{id: 1, packagingFk: 1, quantity: 25, ticketFk: 1}
|
||||
];
|
||||
let packagesObj = {
|
||||
delete: controller.removedPackages,
|
|
@ -0,0 +1,36 @@
|
|||
<mg-ajax path="/ticket/api/sales/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Sale checked</vn-title>
|
||||
<table class="vn-grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center" translate>Is checked</th>
|
||||
<th number translate>Item</th>
|
||||
<th translate style="text-align:center">Description</th>
|
||||
<th number translate>Quantity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="sale in index.model.instances track by sale.id">
|
||||
|
||||
<td style="text-align:center!important"><vn-check style="text-align:center!important" vn-one field="sale.isChecked.isChecked" disabled="true"></vn-check></td>
|
||||
<td number>{{::sale.itemFk}}</td>
|
||||
<td>
|
||||
<vn-vertical style="text-align:center">
|
||||
<vn-one>{{::sale.concept}}</vn-one>
|
||||
<vn-one>
|
||||
<vn-one ng-repeat="fetchedTag in sale.itemTag track by $index">
|
||||
<vn-label>{{::fetchedTag.tag.name}} </vn-label>{{::fetchedTag.value}}
|
||||
</vn-one>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
</td>
|
||||
<td number>{{::sale.quantity}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
|
@ -0,0 +1,17 @@
|
|||
import ngModule from '../module';
|
||||
import FilterTicketList from '../filter-ticket-list';
|
||||
|
||||
class Controller extends FilterTicketList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
super($scope, $timeout, $state);
|
||||
|
||||
this.onOrder('quantity', 'ASC');
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$timeout', '$state'];
|
||||
|
||||
ngModule.component('vnTicketSaleChecked', {
|
||||
template: require('./sale-checked.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
<mg-ajax path="/ticket/api/sales/filter" options="vnIndex"></mg-ajax>
|
||||
<mg-ajax path="/ticket/api/sales/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
import ngModule from '../module';
|
||||
import FilterTicketList from '../filter-ticket-list';
|
||||
|
||||
class Controller extends FilterTicketList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
super($scope, $timeout, $state);
|
||||
|
||||
this.onOrder('quantity', 'ASC');
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$timeout', '$state'];
|
||||
|
||||
ngModule.component('vnTicketSale', {
|
||||
template: require('./sale.html'),
|
||||
controller: FilterTicketList
|
||||
controller: Controller
|
||||
});
|
||||
|
|
|
@ -8,7 +8,9 @@ import './data/ticket-data';
|
|||
import './note/ticket-observation';
|
||||
import './expedition/ticket-expedition';
|
||||
import './volume/ticket-volume';
|
||||
import './package/package';
|
||||
import './package/index/package';
|
||||
import './sale/sale';
|
||||
import './tracking/tracking';
|
||||
import './tracking/index';
|
||||
import './tracking/edit/edit';
|
||||
import './fetched-tags/fetched-tags';
|
||||
import './sale-checked/sale-checked';
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<mg-ajax path="/ticket/api/TicketTrackings/" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.ticket"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()">
|
||||
<vn-card pad-large>
|
||||
<vn-title>New state</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.ticket.stateFk"
|
||||
url="/ticket/api/States"
|
||||
label="State"
|
||||
vn-focus>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,25 @@
|
|||
import ngModule from '../../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor($scope, $state) {
|
||||
this.$ = $scope;
|
||||
this.$state = $state;
|
||||
this.ticket = {
|
||||
ticketFk: $state.params.id,
|
||||
text: null
|
||||
};
|
||||
}
|
||||
onSubmit() {
|
||||
this.$.watcher.submit().then(
|
||||
() => {
|
||||
this.$state.go('ticket.card.tracking.index');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$state'];
|
||||
|
||||
ngModule.component('vnTicketTrackingEdit', {
|
||||
template: require('./edit.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
<mg-ajax path="/ticket/api/TicketTrackings/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Tracking</vn-title>
|
||||
|
@ -7,7 +7,6 @@
|
|||
<vn-column-header vn-one pad-medium-h field="state.name" text="State"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="employee" text="Employee"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="created" text="Created" default-order="ASC"></vn-column-header>
|
||||
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-horizontal
|
||||
|
@ -15,9 +14,8 @@
|
|||
pad-small-bottom
|
||||
ng-repeat="ticket in index.model.instances track by ticket.id">
|
||||
<vn-one pad-medium-h>{{::ticket.state.name}}</vn-one>
|
||||
<vn-two pad-medium-h>{{::ticket.worker.firstName}} {{::ticket.worker.name}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::ticket.worker.firstName}} {{ticket.worker.name}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::ticket.created | date:'dd/MM/yyyy HH:mm'}}</vn-two>
|
||||
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
|
||||
|
@ -26,6 +24,6 @@
|
|||
</vn-vertical>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
<a ui-sref="ticket.card.tracking.create" fixed-bottom-right>
|
||||
<a ui-sref="ticket.card.tracking.edit" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -2,6 +2,6 @@ import ngModule from '../module';
|
|||
import FilterTicketList from '../filter-ticket-list';
|
||||
|
||||
ngModule.component('vnTicketTracking', {
|
||||
template: require('./tracking.html'),
|
||||
template: require('./index.html'),
|
||||
controller: FilterTicketList
|
||||
});
|
|
@ -1,5 +0,0 @@
|
|||
Date : Fecha
|
||||
Employee : Empleado
|
||||
State: Estado
|
||||
Tracking: Revisión
|
||||
Created : Añadido
|
|
@ -18,14 +18,14 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.sumAmount = (clientFk, callback) => {
|
||||
Self.sumAmount = async clientFk => {
|
||||
let query = `SELECT SUM(amount) AS sumAmount FROM vn.greuge WHERE clientFk = ?`;
|
||||
Self.rawSql(query, [clientFk])
|
||||
.then(response => {
|
||||
callback(null, response.length ? response[0].sumAmount : 0);
|
||||
})
|
||||
.catch(err => {
|
||||
callback(err);
|
||||
});
|
||||
try {
|
||||
let [response] = await Self.rawSql(query, [clientFk]);
|
||||
|
||||
return response ? response.sumAmount : 0;
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/creditInsurance/filter.js')(Self);
|
||||
|
||||
Self.validateCredit = function(credit) {
|
||||
return credit >= 0;
|
||||
};
|
||||
|
||||
Self.validateBinded('credit', Self.validateCredit, {
|
||||
message: 'The credit must be an integer greater than or equal to zero',
|
||||
allowNull: false, // FIXME: Ignored by loopback when it's false
|
||||
allowBlank: false
|
||||
});
|
||||
|
||||
Self.validateCredit = function(credit) {
|
||||
return (credit >= 0 && credit % 1 == 0);
|
||||
Self.validateGrade = function(grade) {
|
||||
return typeof grade === 'undefined' || grade >= 0;
|
||||
};
|
||||
|
||||
Self.validateBinded('grade', Self.validateGrade, {
|
||||
message: 'The grade must be an integer greater than or equal to zero',
|
||||
allowNull: true
|
||||
});
|
||||
|
||||
Self.validateGrade = function(grade) {
|
||||
return (typeof grade === 'undefined' || (grade >= 0 && grade % 1 == 0));
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
USE `vn`;
|
||||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `agencyMode` AS
|
||||
SELECT
|
||||
`a`.`Id_Agencia` AS `id`,
|
||||
`a`.`Agencia` AS `name`,
|
||||
`a`.`description` AS `description`,
|
||||
`a`.`Vista` AS `deliveryMethodFk`,
|
||||
`a`.`m3` AS `m3`,
|
||||
`a`.`cod71` AS `cod71`,
|
||||
`a`.`web` AS `web`,
|
||||
`a`.`agency_id` AS `agencyFk`,
|
||||
`a`.`agency_service_id` AS `agencyServiceFk`,
|
||||
`a`.`inflacion` AS `inflation`,
|
||||
`a`.`is_volumetric` AS `isVolumetric`,
|
||||
`a`.`send_mail` AS `reportMail`,
|
||||
`a`.`tpv` AS `isActive`
|
||||
FROM
|
||||
`vn2008`.`Agencias` `a`;
|
|
@ -6,5 +6,6 @@
|
|||
"Unable to default a disabled consignee": "Unable to default a disabled consignee",
|
||||
"El método de pago seleccionado requiere que se especifique el IBAN": "El método de pago seleccionado requiere que se especifique el IBAN",
|
||||
"Ya existe un usuario con ese nombre": "Ya existe un usuario con ese nombre",
|
||||
"Quantity cannot be zero": "Quantity cannot be zero"
|
||||
"Quantity cannot be zero": "Quantity cannot be zero",
|
||||
"can't be blank": "can't be blank"
|
||||
}
|
|
@ -9,5 +9,6 @@
|
|||
"DNI Incorrecto": "DNI Incorrecto",
|
||||
"Ya existe un usuario con ese nombre": "Ya existe un usuario con ese nombre",
|
||||
"is invalid": "is invalid",
|
||||
"Quantity cannot be zero": "La cantidad no puede ser cero"
|
||||
"Quantity cannot be zero": "La cantidad no puede ser cero",
|
||||
"Package cannot be blank": "Package cannot be blank"
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('getAverageInvoiced', {
|
||||
description: 'Returns the annual average invoiced of a client',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'client id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'number',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/getAverageInvoiced`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getAverageInvoiced = async clientFk => {
|
||||
let query = `SELECT invoiced FROM vn.annualAverageInvoiced WHERE clientFk = ?`;
|
||||
let [invoiced] = await Self.rawSql(query, [clientFk]);
|
||||
|
||||
return invoiced;
|
||||
};
|
||||
};
|
|
@ -21,7 +21,8 @@ module.exports = Self => {
|
|||
|
||||
Self.getDebt = async clientFk => {
|
||||
let query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`;
|
||||
let response = await Self.rawSql(query, [clientFk]);
|
||||
return response[0];
|
||||
let [debt] = await Self.rawSql(query, [clientFk]);
|
||||
|
||||
return debt;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('getMana', {
|
||||
description: 'Returns the boolean mana of a client',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'client id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'number',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/getMana`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getMana = async clientFk => {
|
||||
let query = `SELECT vn.clientGetMana(?) AS mana`;
|
||||
let [mana] = await Self.rawSql(query, [clientFk]);
|
||||
|
||||
return mana;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('summary', {
|
||||
description: 'Returns a client summary',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'client id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
returns: {
|
||||
type: [this.modelName],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/summary`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.summary = async clientFk => {
|
||||
let models = Self.app.models;
|
||||
let summaryObj = await getSummary(models.Client, clientFk);
|
||||
|
||||
summaryObj.mana = await models.Client.getMana(clientFk);
|
||||
summaryObj.debt = await models.Client.getDebt(clientFk);
|
||||
summaryObj.averageInvoiced = await models.Client.getAverageInvoiced(clientFk);
|
||||
summaryObj.totalGreuge = await models.Greuge.sumAmount(clientFk);
|
||||
summaryObj.recovery = await getRecoveries(models.Recovery, clientFk);
|
||||
|
||||
return summaryObj;
|
||||
};
|
||||
|
||||
async function getSummary(client, clientId) {
|
||||
let filter = {
|
||||
include: [
|
||||
{relation: 'account', scope: {fields: ['name', 'active']}},
|
||||
{relation: 'salesPerson', scope: {fields: ['name']}},
|
||||
{relation: 'country', scope: {fields: ['country']}},
|
||||
{relation: 'province', scope: {fields: ['name']}},
|
||||
{relation: 'contactChannel', scope: {fields: ['name']}},
|
||||
{relation: 'payMethod', scope: {fields: ['name']}},
|
||||
{
|
||||
relation: 'addresses',
|
||||
scope: {
|
||||
where: {isDefaultAddress: true},
|
||||
fields: ['nickname', 'street', 'city', 'postalCode']
|
||||
}
|
||||
}
|
||||
],
|
||||
where: {id: clientId}
|
||||
};
|
||||
|
||||
return await client.findOne(filter);
|
||||
}
|
||||
|
||||
async function getRecoveries(recovery, clientId) {
|
||||
let filter = {
|
||||
where: {
|
||||
and: [{clientFk: clientId}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}]
|
||||
},
|
||||
limit: 1
|
||||
};
|
||||
|
||||
return await recovery.findOne(filter);
|
||||
}
|
||||
};
|
|
@ -28,6 +28,9 @@
|
|||
},
|
||||
"reportMail": {
|
||||
"type": "string"
|
||||
},
|
||||
"isActive":{
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
@ -49,5 +52,8 @@
|
|||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
],
|
||||
"scopes" : {
|
||||
"active" : {"where": {"isActive": {"neq": false}}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ module.exports = function(Self) {
|
|||
require('../methods/client/activeSalesPerson')(Self);
|
||||
require('../methods/client/addressesPropagateRe')(Self);
|
||||
require('../methods/client/getDebt')(Self);
|
||||
require('../methods/client/getMana')(Self);
|
||||
require('../methods/client/getAverageInvoiced')(Self);
|
||||
require('../methods/client/summary')(Self);
|
||||
|
||||
// Validations
|
||||
|
||||
|
|
|
@ -20,6 +20,12 @@ module.exports = Self => {
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: "isChecked",
|
||||
scope: {
|
||||
fields: ["isChecked"]
|
||||
}
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
|
|
@ -51,6 +51,11 @@
|
|||
"model": "Ticket",
|
||||
"foreignKey": "ticketFk",
|
||||
"required": true
|
||||
},
|
||||
"isChecked": {
|
||||
"type": "hasOne",
|
||||
"model": "SaleChecked",
|
||||
"foreignKey": "saleFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/ticketTracking/filter')(Self);
|
||||
|
||||
Self.observe('before save', function(ctx, next) {
|
||||
let token = ctx.options.accessToken;
|
||||
let userId = token && token.userId;
|
||||
|
||||
Self.app.models.Worker.findOne({where: {userFk: userId}}, (err, user) => {
|
||||
if (err) return next(err);
|
||||
ctx.instance.workerFk = user.id;
|
||||
next();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "ticketTracking"
|
||||
"table": "ticketTracking",
|
||||
"database": "vn"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
|
Loading…
Reference in New Issue