Merge branch 'dev' into 2940-invoiceInTax-section
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Javi Gallego 2021-06-18 07:07:52 +02:00
commit a6c093cf16
47 changed files with 1186 additions and 676 deletions

View File

@ -806,19 +806,6 @@ INSERT INTO `vn`.`priceFixed`(`id`, `itemFk`, `rate0`, `rate1`, `rate2`, `rate3`
(2, 3, 10, 10, 10, 10, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 0, 1, CURDATE()), (2, 3, 10, 10, 10, 10, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 0, 1, CURDATE()),
(3, 5, 8.5, 10, 7.5, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 1, 2, CURDATE()); (3, 5, 8.5, 10, 7.5, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 1, 2, CURDATE());
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`)
VALUES
(1, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 18),
(2, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 18),
(3, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 3, 1, 18),
(4, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 18),
(5, 1, 2, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 18),
(6, 7, 3, 71, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 1, 1, 18),
(7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 1, 1, 1, 18),
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), 1, 1, 1, 18),
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 18),
(10, 7, 7, 71, CURDATE(), 1, 1, 1, 18);
INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`) INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`)
VALUES VALUES
(71,0.141,1); (71,0.141,1);
@ -834,6 +821,19 @@ INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPack
('cc', 1640038.00, 56.00, 220.00, 128.00, 1, CURDATE(), 15, 90.00), ('cc', 1640038.00, 56.00, 220.00, 128.00, 1, CURDATE(), 15, 90.00),
('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, CURDATE(), 16, 0.00); ('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, CURDATE(), 16, 0.00);
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`, `externalId`, `packagingFk`)
VALUES
(1, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 15, 1, 1, 18, 'UR9000006041', 94),
(2, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 16, 2, 1, 18, 'UR9000006041', 94),
(3, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 3, 1, 18, 'UR9000006041', 94),
(4, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 4, 1, 18, 'UR9000006041', 94),
(5, 1, 2, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94),
(6, 7, 3, 71, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), NULL, 1, 1, 18, NULL, 94),
(7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL, 1, 1, 18, NULL, 94),
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), NULL, 1, 1, 18, NULL, 94),
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94),
(10, 7, 7, 71, CURDATE(), NULL, 1, 1, 18, NULL, 94);
INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`) INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`)
VALUES VALUES
(1, 1, 2, 2, CURDATE(), NULL), (1, 1, 2, 2, CURDATE(), NULL),

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
// Tarea #2972
describe('Travel descriptor path', () => { xdescribe('Travel descriptor path', () => {
let browser; let browser;
let page; let page;

View File

@ -43,14 +43,14 @@ export default class Contextmenu {
get row() { get row() {
if (!this.target) return null; if (!this.target) return null;
return this.target.closest('vn-tr, .vn-tr'); return this.target.closest('[ng-repeat]');
} }
get rowIndex() { get rowIndex() {
if (!this.row) return null; if (!this.row) return null;
const table = this.row.closest('vn-table, .vn-table'); const table = this.row.closest('vn-table, .vn-table');
const tBody = table.querySelector('vn-tbody, .vn-tbody'); const rows = table.querySelectorAll('[ng-repeat]');
const rows = tBody.querySelectorAll('vn-tr, .vn-tr');
return Array.from(rows).findIndex( return Array.from(rows).findIndex(
rowItem => rowItem == this.row rowItem => rowItem == this.row

View File

@ -230,3 +230,7 @@ vn-table.scrollable.lg,
.vn-table.scrollable.lg { .vn-table.scrollable.lg {
max-height: 700px max-height: 700px
} }
.tableWrapper {
overflow-x: auto;
}

View File

@ -51,6 +51,8 @@
</vn-data-viewer> </vn-data-viewer>
<vn-float-button <vn-float-button
ng-if="$ctrl.canCreateNew()" ng-if="$ctrl.canCreateNew()"
vn-acl="insurance"
vn-acl-action="remove"
vn-tooltip="New contract" vn-tooltip="New contract"
fixed-bottom-right fixed-bottom-right
ui-sref="client.card.creditInsurance.create" ui-sref="client.card.creditInsurance.create"

View File

@ -30,6 +30,8 @@
</div> </div>
<a <a
ng-if="!$ctrl.isClosed" ng-if="!$ctrl.isClosed"
vn-acl="insurance"
vn-acl-action="remove"
ui-sref="client.card.creditInsurance.insurance.create({classificationId: {{$ctrl.$params.classificationId}}})" ui-sref="client.card.creditInsurance.insurance.create({classificationId: {{$ctrl.$params.classificationId}}})"
fixed-bottom-right fixed-bottom-right
vn-tooltip="New credit" vn-tooltip="New credit"

View File

@ -240,14 +240,12 @@
"url": "/credit-insurance", "url": "/credit-insurance",
"abstract": true, "abstract": true,
"state": "client.card.creditInsurance", "state": "client.card.creditInsurance",
"component": "ui-view", "component": "ui-view"
"acl": ["insurance"]
}, { }, {
"url": "/index", "url": "/index",
"state": "client.card.creditInsurance.index", "state": "client.card.creditInsurance.index",
"component": "vn-client-credit-insurance-index", "component": "vn-client-credit-insurance-index",
"description": "Credit contracts", "description": "Credit contracts",
"acl": ["insurance"],
"params": { "params": {
"client": "$ctrl.client" "client": "$ctrl.client"
} }
@ -256,6 +254,7 @@
"state": "client.card.creditInsurance.create", "state": "client.card.creditInsurance.create",
"component": "vn-client-credit-insurance-create", "component": "vn-client-credit-insurance-create",
"description": "New insurance", "description": "New insurance",
"acl": ["insurance"],
"params": { "params": {
"client": "$ctrl.client" "client": "$ctrl.client"
} }
@ -279,6 +278,7 @@
"state": "client.card.creditInsurance.insurance.create", "state": "client.card.creditInsurance.insurance.create",
"component": "vn-client-credit-insurance-insurance-create", "component": "vn-client-credit-insurance-insurance-create",
"description": "New credit", "description": "New credit",
"acl": ["insurance"],
"params": { "params": {
"client": "$ctrl.client" "client": "$ctrl.client"
} }

View File

@ -1,3 +1,12 @@
<vn-crud-model
vn-id="ticketsModel"
auto-load="true"
url="Tickets/filter"
link="{'t.clientFk': $ctrl.$params.id}"
limit="5"
data="tickets"
order="shippedDate DESC, shippedHour ASC">
</vn-crud-model>
<vn-card class="summary"> <vn-card class="summary">
<h5> <h5>
<a ng-if="::$ctrl.summary.id" <a ng-if="::$ctrl.summary.id"
@ -269,14 +278,112 @@
ng-class="{alert: $ctrl.summary.defaulters[0].amount}" ng-class="{alert: $ctrl.summary.defaulters[0].amount}"
info="Deviated invoices minus payments"> info="Deviated invoices minus payments">
</vn-label-value> </vn-label-value>
<vn-vertical ng-if="$ctrl.summary.recovery.started"> <vn-label-value label="Recovery since"
<vn-label-value label="Recovery since" ng-if="$ctrl.summary.recovery.started"
value="{{$ctrl.summary.recovery.started | date:'dd/MM/yyyy'}}"> value="{{$ctrl.summary.recovery.started | date:'dd/MM/yyyy'}}">
</vn-label-value> </vn-label-value>
</vn-vertical> </vn-one>
</vn-horizontal>
<vn-horizontal>
<vn-one>
<h4 translate>Latest tickets</h4>
<vn-table model="ticketsModel" class="scrollable sm">
<vn-thead>
<vn-tr>
<vn-th field="id" number>Id</vn-th>
<vn-th field="nickname" expand>Client</vn-th>
<vn-th field="salesPersonFk">Salesperson</vn-th>
<vn-th field="shipped" shrink-date>Date</vn-th>
<vn-th field="stateFk">State</vn-th>
<vn-th shrink>Total</vn-th>
<vn-th></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<a ng-repeat="ticket in ticketsModel.data"
class="clickable vn-tr search-result"
ui-sref="ticket.card.summary({id: {{::ticket.id}}})">
<vn-td number>{{::ticket.id}}</vn-td>
<vn-td expand>
<span
title="{{::ticket.nickname}}"
vn-click-stop="clientDescriptor.show($event, ticket.clientFk)"
class="link">
{{::ticket.nickname}}
</span>
</vn-td>
<vn-td>
<span
title="{{::ticket.userName}}"
vn-click-stop="workerDescriptor.show($event, ticket.salesPersonFk)"
class="link">
{{::ticket.userName | dashIfEmpty}}
</span>
</vn-td>
<vn-td shrink-date>
<span class="chip {{::$ctrl.chipColor(ticket.shipped)}}">
{{::ticket.shipped | date: 'dd/MM/yyyy'}}
</span>
</vn-td>
<vn-td>
<span
ng-show="::ticket.refFk"
title="{{::ticket.refFk}}"
vn-click-stop="invoiceOutDescriptor.show($event, ticket.invoiceOutId)"
class="link">
{{::ticket.refFk}}
</span>
<span
ng-show="::!ticket.refFk"
class="chip {{::$ctrl.stateColor(ticket)}}">
{{::ticket.state}}
</span>
</vn-td>
<vn-td shrink>
<span class="chip {{$ctrl.totalPriceColor(ticket)}}">
{{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}
</span>
</vn-td>
<vn-td actions>
<vn-icon-button
vn-anchor="::{
state: 'ticket.card.sale',
params: {id: ticket.id},
target: '_blank'
}"
vn-tooltip="Go to lines"
icon="icon-lines">
</vn-icon-button>
<vn-icon-button
vn-click-stop="$ctrl.preview(ticket)"
vn-tooltip="Preview"
icon="preview">
</vn-icon-button>
</vn-td>
</a>
</vn-tbody>
</vn-table>
<vn-pagination
model="ticketsModel"
class="vn-pt-xs"
scroll-selector="vn-table[model='ticketsModel']"
scroll-offset="100">
</vn-pagination>
</vn-one> </vn-one>
</vn-horizontal> </vn-horizontal>
</vn-card> </vn-card>
<vn-client-descriptor-popover
vn-id="clientDescriptor">
</vn-client-descriptor-popover>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor"> vn-id="workerDescriptor">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<vn-invoice-out-descriptor-popover
vn-id="invoiceOutDescriptor">
</vn-invoice-out-descriptor-popover>
<vn-popup vn-id="summary">
<vn-ticket-summary
ticket="$ctrl.selectedTicket"
model="model">
</vn-ticket-summary>
</vn-popup>

View File

@ -39,6 +39,43 @@ class Controller extends Summary {
if (rate) if (rate)
return rate * 100; return rate * 100;
} }
stateColor(ticket) {
if (ticket.alertLevelCode === 'OK')
return 'success';
else if (ticket.alertLevelCode === 'FREE')
return 'notice';
else if (ticket.alertLevel === 1)
return 'warning';
else if (ticket.alertLevel === 0)
return 'alert';
}
chipColor(date) {
const today = new Date();
today.setHours(0, 0, 0, 0);
const ticketShipped = new Date(date);
ticketShipped.setHours(0, 0, 0, 0);
const difference = today - ticketShipped;
if (difference == 0)
return 'warning';
if (difference < 0)
return 'success';
}
totalPriceColor(ticket) {
const total = parseInt(ticket.totalWithVat);
if (total > 0 && total < 50)
return 'warning';
}
preview(ticket) {
this.selectedTicket = ticket;
this.$.summary.show();
}
} }
ngModule.vnComponent('vnClientSummary', { ngModule.vnComponent('vnClientSummary', {

View File

@ -4,15 +4,15 @@ describe('Client', () => {
describe('Component vnClientSummary', () => { describe('Component vnClientSummary', () => {
let controller; let controller;
let $httpBackend; let $httpBackend;
let $scope; let $window;
beforeEach(ngModule('client')); beforeEach(ngModule('client'));
beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => { beforeEach(inject(($componentController, _$httpBackend_, _$window_) => {
$window = _$window_;
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$scope = $rootScope.$new();
const $element = angular.element('<vn-client-summary></vn-client-summary>'); const $element = angular.element('<vn-client-summary></vn-client-summary>');
controller = $componentController('vnClientSummary', {$element, $scope}); controller = $componentController('vnClientSummary', {$element});
controller.client = {id: 101}; controller.client = {id: 101};
})); }));
@ -48,5 +48,82 @@ describe('Client', () => {
expect(result).toEqual(300); expect(result).toEqual(300);
}); });
}); });
describe('chipColor()', () => {
it('should return warning when the date is the present', () => {
let today = new Date();
let result = controller.chipColor(today);
expect(result).toEqual('warning');
});
it('should return success when the date is in the future', () => {
let futureDate = new Date();
futureDate = futureDate.setDate(futureDate.getDate() + 10);
let result = controller.chipColor(futureDate);
expect(result).toEqual('success');
});
it('should return undefined when the date is in the past', () => {
let pastDate = new Date();
pastDate = pastDate.setDate(pastDate.getDate() - 10);
let result = controller.chipColor(pastDate);
expect(result).toEqual(undefined);
});
});
describe('stateColor()', () => {
it('should return "success" when the alertLevelCode property is "OK"', () => {
const result = controller.stateColor({alertLevelCode: 'OK'});
expect(result).toEqual('success');
});
it('should return "notice" when the alertLevelCode property is "FREE"', () => {
const result = controller.stateColor({alertLevelCode: 'FREE'});
expect(result).toEqual('notice');
});
it('should return "warning" when the alertLevel property is "1', () => {
const result = controller.stateColor({alertLevel: 1});
expect(result).toEqual('warning');
});
it('should return "alert" when the alertLevel property is "0"', () => {
const result = controller.stateColor({alertLevel: 0});
expect(result).toEqual('alert');
});
});
describe('totalPriceColor()', () => {
it('should return "warning" when the ticket amount is less than 50€', () => {
const result = controller.totalPriceColor({totalWithVat: '8.50'});
expect(result).toEqual('warning');
});
});
describe('preview()', () => {
it('should show the dialog summary', () => {
controller.$.summary = {show: () => {}};
jest.spyOn(controller.$.summary, 'show');
const ticket = {id: 1, clientFk: 101};
const event = new MouseEvent('click', {
view: $window,
bubbles: true,
cancelable: true
});
controller.preview(event, ticket);
expect(controller.$.summary.show).toHaveBeenCalledWith();
});
});
}); });
}); });

View File

@ -19,3 +19,4 @@ Solunion's maximum risk: Riesgo máximo asumido por Solunion
Invoices minus payments: Facturas menos recibos Invoices minus payments: Facturas menos recibos
Deviated invoices minus payments: Facturas fuera de plazo menos recibos Deviated invoices minus payments: Facturas fuera de plazo menos recibos
Go to the client: Ir al cliente Go to the client: Ir al cliente
Latest tickets: Últimos tickets

View File

@ -1,6 +1,8 @@
@import "variables"; @import "variables";
vn-client-summary { vn-client-summary .summary {
max-width: $width-lg;
.alert span { .alert span {
color: $color-alert !important color: $color-alert !important
} }

View File

@ -25,7 +25,7 @@
<vn-tr ng-repeat="transaction in transactions"> <vn-tr ng-repeat="transaction in transactions">
<vn-td shrink> <vn-td shrink>
<vn-icon <vn-icon
vn-tooltip="{{$ctrl.getFormattedMessage(transaction)}}" vn-tooltip="{{::$ctrl.getFormattedMessage(transaction)}}"
ng-show="::((transaction.errorMessage || transaction.responseMessage) && !transaction.isConfirmed)" ng-show="::((transaction.errorMessage || transaction.responseMessage) && !transaction.isConfirmed)"
icon="clear"> icon="clear">
</vn-icon> </vn-icon>

View File

@ -48,21 +48,15 @@ module.exports = Self => {
switch (field) { switch (field) {
case 'size': case 'size':
case 'density': case 'density':
case 'minPrice':
case 'description': case 'description':
case 'packingOut':
modelName = 'Item'; modelName = 'Item';
identifier = 'itemFk'; identifier = 'itemFk';
break; break;
case 'quantity':
case 'buyingValue':
case 'freightValue':
case 'packing': case 'packing':
case 'grouping': case 'grouping':
case 'groupingMode': case 'groupingMode':
case 'comissionValue':
case 'packageValue': case 'packageValue':
case 'price2':
case 'price3':
case 'weight': case 'weight':
modelName = 'Buy'; modelName = 'Buy';
identifier = 'id'; identifier = 'id';

View File

@ -10,54 +10,59 @@ module.exports = Self => {
accepts: [ accepts: [
{ {
arg: 'filter', arg: 'filter',
type: 'Object', type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
}, },
{ {
arg: 'search', arg: 'search',
type: 'String', type: 'string',
description: `If it's and integer searchs by id, otherwise it searchs by name`, description: `If it's and integer searchs by id, otherwise it searchs by name`,
}, },
{ {
arg: 'id', arg: 'id',
type: 'Integer', type: 'integer',
description: 'Item id', description: 'Item id',
}, },
{ {
arg: 'tags', arg: 'tags',
type: ['Object'], type: ['object'],
description: 'List of tags to filter with', description: 'List of tags to filter with',
http: {source: 'query'} http: {source: 'query'}
}, },
{ {
arg: 'description', arg: 'description',
type: 'String', type: 'string',
description: 'The item description', description: 'The item description',
}, },
{ {
arg: 'salesPersonFk', arg: 'salesPersonFk',
type: 'Integer', type: 'integer',
description: 'The buyer of the item', description: 'The buyer of the item',
}, },
{ {
arg: 'active', arg: 'active',
type: 'Boolean', type: 'boolean',
description: 'Whether the item is or not active', description: 'Whether the item is or not active',
}, },
{ {
arg: 'visible', arg: 'visible',
type: 'Boolean', type: 'boolean',
description: 'Whether the item is or not visible', description: 'Whether the item is or not visible',
}, },
{ {
arg: 'typeFk', arg: 'typeFk',
type: 'Integer', type: 'integer',
description: 'Type id', description: 'Type id',
}, },
{ {
arg: 'categoryFk', arg: 'categoryFk',
type: 'Integer', type: 'integer',
description: 'Category id', description: 'Category id',
},
{
arg: 'packingOut',
type: 'integer',
description: 'the packingOut',
} }
], ],
returns: { returns: {
@ -84,7 +89,10 @@ module.exports = Self => {
? {'i.id': value} ? {'i.id': value}
: {'i.name': {like: `%${value}%`}}; : {'i.name': {like: `%${value}%`}};
case 'id': case 'id':
return {'i.id': value}; case 'packingOut':
case 'typeFk':
param = `i.${param}`;
return {[param]: value};
case 'description': case 'description':
return {'i.description': {like: `%${value}%`}}; return {'i.description': {like: `%${value}%`}};
case 'categoryFk': case 'categoryFk':
@ -93,8 +101,6 @@ module.exports = Self => {
return {'it.workerFk': value}; return {'it.workerFk': value};
case 'code': case 'code':
return {'it.code': value}; return {'it.code': value};
case 'typeFk':
return {'i.typeFk': value};
case 'active': case 'active':
return {'i.isActive': value}; return {'i.isActive': value};
case 'visible': case 'visible':
@ -126,6 +132,7 @@ module.exports = Self => {
i.description, i.description,
i.name, i.name,
i.subName, i.subName,
i.packingOut,
i.tag5, i.tag5,
i.value5, i.value5,
i.tag6, i.tag6,

View File

@ -10,182 +10,185 @@
</vn-watcher> </vn-watcher>
<div class="vn-w-xl"> <div class="vn-w-xl">
<vn-card class="vn-pa-lg"> <vn-card class="vn-pa-lg">
<vn-horizontal class="header"> <div class="tableWrapper">
<vn-tool-bar class="vn-mb-md"> <vn-horizontal class="header">
<vn-button <vn-tool-bar class="vn-mb-md">
disabled="$ctrl.selectedBuys() == 0" <vn-button
ng-click="deleteBuys.show()" disabled="$ctrl.selectedBuys() == 0"
vn-tooltip="Delete buy(s)" ng-click="deleteBuys.show()"
icon="delete"> vn-tooltip="Delete buy(s)"
</vn-button> icon="delete">
</vn-tool-bar> </vn-button>
<vn-one class="taxes" ng-if="$ctrl.sales.length > 0"> </vn-tool-bar>
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.ticket.totalWithoutVat | currency: 'EUR':2}}</p> <vn-one class="taxes" ng-if="$ctrl.sales.length > 0">
<p><vn-label translate>VAT</vn-label> {{$ctrl.ticket.totalWithVat - $ctrl.ticket.totalWithoutVat | currency: 'EUR':2}}</p> <p><vn-label translate>Subtotal</vn-label> {{$ctrl.ticket.totalWithoutVat | currency: 'EUR':2}}</p>
<p><vn-label><strong>Total</strong></vn-label> <strong>{{$ctrl.ticket.totalWithVat | currency: 'EUR':2}}</strong></p> <p><vn-label translate>VAT</vn-label> {{$ctrl.ticket.totalWithVat - $ctrl.ticket.totalWithoutVat | currency: 'EUR':2}}</p>
</vn-one> <p><vn-label><strong>Total</strong></vn-label> <strong>{{$ctrl.ticket.totalWithVat | currency: 'EUR':2}}</strong></p>
</vn-horizontal> </vn-one>
<table class="vn-table"> </vn-horizontal>
<thead> <table class="vn-table">
<tr> <thead>
<th shrink> <tr>
<vn-multi-check model="model" on-change="$ctrl.resetChanges()"> <th shrink>
</vn-multi-check> <vn-multi-check model="model" on-change="$ctrl.resetChanges()">
</th> </vn-multi-check>
<th translate center>Item</th> </th>
<th translate center>Quantity</th> <th translate center>Item</th>
<th translate center>Package</th> <th translate center>Quantity</th>
<th translate>Stickers</th> <th translate center>Package</th>
<th translate>Weight</th> <th translate>Stickers</th>
<th translate>Packing</th> <th translate>Weight</th>
<th translate>Grouping</th> <th translate>Packing</th>
<th translate>Buying value</th> <th translate>Grouping</th>
<th translate expand>Grouping price</th> <th translate>Buying value</th>
<th translate expand>Packing price</th> <th translate expand>Grouping price</th>
<th translate>Import</th> <th translate expand>Packing price</th>
</tr> <th translate>Import</th>
</thead> </tr>
<tbody ng-repeat="buy in $ctrl.buys"> </thead>
<tr> <tbody ng-repeat="buy in $ctrl.buys">
<td shrink> <tr>
<vn-check tabindex="-1" ng-model="buy.checked"> <td shrink>
</vn-check> <vn-check tabindex="-1" ng-model="buy.checked">
</td> </vn-check>
<td shrink> </td>
<span <td shrink>
ng-if="buy.id" <span
ng-click="itemDescriptor.show($event, buy.item.id)" ng-if="buy.id"
class="link"> ng-click="itemDescriptor.show($event, buy.item.id)"
{{::buy.item.id | zeroFill:6}} class="link">
</span> {{::buy.item.id | zeroFill:6}}
<vn-autocomplete ng-if="!buy.id" class="dense" </span>
vn-focus <vn-autocomplete ng-if="!buy.id" class="dense"
url="Items" vn-focus
ng-model="buy.itemFk" url="Items"
show-field="name" ng-model="buy.itemFk"
value-field="id" show-field="name"
search-function="$ctrl.itemSearchFunc($search)" value-field="id"
on-change="$ctrl.saveBuy(buy)" search-function="$ctrl.itemSearchFunc($search)"
order="id DESC" on-change="$ctrl.saveBuy(buy)"
tabindex="1"> order="id DESC"
<tpl-item> tabindex="1">
{{::id}} - {{::name}} <tpl-item>
</tpl-item> {{::id}} - {{::name}}
</vn-autocomplete> </tpl-item>
</td> </vn-autocomplete>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.quantity | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.quantity" title="{{::buy.quantity | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.quantity"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td center> </td>
<vn-autocomplete <td center>
vn-one <vn-autocomplete
title="{{::buy.packageFk | dashIfEmpty}}" vn-one
url="Packagings" title="{{::buy.packageFk | dashIfEmpty}}"
show-field="id" url="Packagings"
value-field="id" show-field="id"
where="{isBox: true}" value-field="id"
ng-model="buy.packageFk" where="{isBox: true}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.packageFk"
</vn-autocomplete> on-change="$ctrl.saveBuy(buy)">
</td> </vn-autocomplete>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.stickers | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.stickers" title="{{::buy.stickers | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.stickers"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.weight | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.weight" title="{{::buy.weight | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.weight"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.packing | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.packing" title="{{::buy.packing | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.packing"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.grouping | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.grouping" title="{{::buy.grouping | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.grouping"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.buyingValue | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.buyingValue" title="{{::buy.buyingValue | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.buyingValue"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.price2 | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.price2" title="{{::buy.price2 | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.price2"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td> </td>
<vn-input-number class="dense" <td>
title="{{::buy.price3 | dashIfEmpty}}" <vn-input-number class="dense"
ng-model="buy.price3" title="{{::buy.price3 | dashIfEmpty}}"
on-change="$ctrl.saveBuy(buy)"> ng-model="buy.price3"
</vn-input-number> on-change="$ctrl.saveBuy(buy)">
</td> </vn-input-number>
<td> </td>
<span <td>
ng-if="buy.quantity != null && buy.buyingValue != null" <span
title="{{buy.quantity * buy.buyingValue | currency: 'EUR':2}}"> ng-if="buy.quantity != null && buy.buyingValue != null"
{{buy.quantity * buy.buyingValue | currency: 'EUR':2}} title="{{buy.quantity * buy.buyingValue | currency: 'EUR':2}}">
</span> {{buy.quantity * buy.buyingValue | currency: 'EUR':2}}
</td> </span>
</tr> </td>
<tr class="dark-row"> </tr>
<td shrink> <tr class="dark-row">
</td> <td shrink>
<td shrink> </td>
<span translate-attr="{title: 'Item type'}"> <td shrink>
{{::buy.item.itemType.code}} <span translate-attr="{title: 'Item type'}">
</span> {{::buy.item.itemType.code}}
</td> </span>
<td number shrink> </td>
<span translate-attr="{title: 'Item size'}"> <td number shrink>
{{::buy.item.size}} <span translate-attr="{title: 'Item size'}">
</span> {{::buy.item.size}}
</td> </span>
<td center> </td>
<span translate-attr="{title: 'Minimum price'}"> <td center>
{{::buy.item.minPrice | currency: 'EUR':2}} <span translate-attr="{title: 'Minimum price'}">
</span> {{::buy.item.minPrice | currency: 'EUR':2}}
</td> </span>
<td vn-fetched-tags colspan="9"> </td>
<vn-one title="{{::buy.item.name}}">{{::buy.item.name}}</vn-one> <td vn-fetched-tags colspan="8">
<vn-fetched-tags <vn-one title="{{::buy.item.name}}">{{::buy.item.name}}</vn-one>
max-length="6" <vn-fetched-tags
item="::buy.item" max-length="6"
tabindex="-1"> item="::buy.item"
</vn-fetched-tags> tabindex="-1">
</td> </vn-fetched-tags>
</tr> </td>
</tbody> </tr>
</table> <tr><td></td></tr>
<div> </tbody>
<vn-icon-button </table>
vn-one <div>
vn-tooltip="Add buy" <vn-icon-button
vn-bind="+" vn-one
icon="add_circle" vn-tooltip="Add buy"
ng-click="model.insert({})"> vn-bind="+"
</vn-icon-button> icon="add_circle"
ng-click="model.insert({})">
</vn-icon-button>
</div>
</div> </div>
</vn-card> </vn-card>
</div> </div>

View File

@ -8,14 +8,29 @@ vn-entry-buy-index vn-card {
background-color: lighten($color-marginal, 10%); background-color: lighten($color-marginal, 10%);
} }
tbody tr:nth-child(1) { thead tr {
border-top: 1px solid $color-marginal; border-left: 1px solid white;
border-right: 1px solid white;
}
tbody tr:nth-child(1),
tbody tr:nth-child(2) {
border-left: 1px solid $color-marginal;
border-right: 1px solid $color-marginal;
}
tbody tr:nth-child(2) {
border-bottom: 1px solid $color-marginal;
} }
tbody{ tbody{
border-bottom: 1px solid $color-marginal; border-bottom: 1px solid $color-marginal;
} }
tbody:last-child {
border-bottom: 0;
}
tbody tr:nth-child(3) { tbody tr:nth-child(3) {
height: inherit height: inherit
} }

View File

@ -57,6 +57,7 @@
<vn-th field="ektFk">Ekt</vn-th> <vn-th field="ektFk">Ekt</vn-th>
<vn-th field="weight">Weight</vn-th> <vn-th field="weight">Weight</vn-th>
<vn-th field="packageFk" expand>PackageName</vn-th> <vn-th field="packageFk" expand>PackageName</vn-th>
<vn-th field="packingOut" expand>PackingOut</vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
@ -147,6 +148,7 @@
<vn-td number>{{::buy.ektFk | dashIfEmpty}}</vn-td> <vn-td number>{{::buy.ektFk | dashIfEmpty}}</vn-td>
<vn-td number>{{::buy.weight}}</vn-td> <vn-td number>{{::buy.weight}}</vn-td>
<vn-td number>{{::buy.packageFk}}</vn-td> <vn-td number>{{::buy.packageFk}}</vn-td>
<vn-td number>{{::buy.packingOut}}</vn-td>
</a> </a>
</vn-tbody> </vn-tbody>
</vn-table> </vn-table>

View File

@ -16,20 +16,14 @@ export default class Controller extends Section {
if (this._columns) return this._columns; if (this._columns) return this._columns;
this._columns = [ this._columns = [
{field: 'quantity', displayName: this.$t('Quantity')},
{field: 'buyingValue', displayName: this.$t('Buying value')},
{field: 'freightValue', displayName: this.$t('Freight value')},
{field: 'packing', displayName: this.$t('Packing')}, {field: 'packing', displayName: this.$t('Packing')},
{field: 'grouping', displayName: this.$t('Grouping')}, {field: 'grouping', displayName: this.$t('Grouping')},
{field: 'comissionValue', displayName: this.$t('Commission value')},
{field: 'packageValue', displayName: this.$t('Package value')}, {field: 'packageValue', displayName: this.$t('Package value')},
{field: 'price2', displayName: this.$t('Grouping price')},
{field: 'price3', displayName: this.$t('Packing price')},
{field: 'weight', displayName: this.$t('Weight')}, {field: 'weight', displayName: this.$t('Weight')},
{field: 'description', displayName: this.$t('Description')}, {field: 'description', displayName: this.$t('Description')},
{field: 'minPrice', displayName: this.$t('Min price')},
{field: 'size', displayName: this.$t('Size')}, {field: 'size', displayName: this.$t('Size')},
{field: 'density', displayName: this.$t('Density')} {field: 'density', displayName: this.$t('Density')},
{field: 'packingOut', displayName: this.$t('PackingOut')}
]; ];
return this._columns; return this._columns;
@ -59,10 +53,14 @@ export default class Controller extends Section {
} }
onEditAccept() { onEditAccept() {
const rowsToEdit = [];
for (let row of this.checked)
rowsToEdit.push({id: row.id, itemFk: row.itemFk});
let data = { let data = {
field: this.editedColumn.field, field: this.editedColumn.field,
newValue: this.editedColumn.newValue, newValue: this.editedColumn.newValue,
lines: this.checked lines: rowsToEdit
}; };
return this.$http.post('Buys/editLatestBuys', data) return this.$http.post('Buys/editLatestBuys', data)

View File

@ -14,3 +14,4 @@ Field to edit: Campo a editar
PackageName: Cubo PackageName: Cubo
Edit: Editar Edit: Editar
buy(s): compra(s) buy(s): compra(s)
PackingOut: Packing envíos

View File

@ -137,6 +137,9 @@
"minPrice": { "minPrice": {
"type": "number" "type": "number"
}, },
"packingOut": {
"type": "number"
},
"hasMinPrice": { "hasMinPrice": {
"type": "boolean" "type": "boolean"
}, },

View File

@ -10,6 +10,11 @@
Clients on website Clients on website
</vn-one> </vn-one>
<vn-none> <vn-none>
<vn-icon class="arrow"
icon="keyboard_arrow_up"
vn-tooltip="Minimize/Maximize"
ng-click="$ctrl.main.toggle()">
</vn-icon>
<vn-icon <vn-icon
icon="refresh" icon="refresh"
vn-tooltip="Refresh" vn-tooltip="Refresh"
@ -17,7 +22,7 @@
</vn-icon> </vn-icon>
</vn-none> </vn-none>
</vn-horizontal> </vn-horizontal>
<vn-card> <vn-card vn-id="card">
<vn-table model="model" class="scrollable sm"> <vn-table model="model" class="scrollable sm">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
@ -52,12 +57,6 @@
</vn-tr> </vn-tr>
</vn-tbody> </vn-tbody>
</vn-table> </vn-table>
<div
ng-if="!model.data.length"
class="empty-rows vn-pa-sm"
translate>
No results
</div>
<vn-pagination <vn-pagination
model="model" model="model"
class="vn-pt-xs" class="vn-pt-xs"

View File

@ -26,5 +26,8 @@ export default class Controller extends Section {
ngModule.vnComponent('vnMonitorSalesClients', { ngModule.vnComponent('vnMonitorSalesClients', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller controller: Controller,
require: {
main: '^vnMonitorIndex'
}
}); });

View File

@ -1,11 +1,5 @@
<vn-horizontal> <vn-horizontal>
<vn-three class="vn-mr-sm"> <vn-monitor-sales-clients class="vn-mb-sm"></vn-monitor-sales-clients>
<vn-monitor-sales-tickets></vn-monitor-sales-tickets> <vn-monitor-sales-orders></vn-monitor-sales-orders>
</vn-three>
<vn-one>
<vn-vertical>
<vn-monitor-sales-clients class="vn-mb-sm"></vn-monitor-sales-clients>
<vn-monitor-sales-orders></vn-monitor-sales-orders>
</vn-vertical>
</vn-one>
</vn-horizontal> </vn-horizontal>
<vn-monitor-sales-tickets></vn-monitor-sales-tickets>

View File

@ -2,7 +2,22 @@ import ngModule from '../module';
import Section from 'salix/components/section'; import Section from 'salix/components/section';
import './style.scss'; import './style.scss';
export default class Controller extends Section {
toggle() {
const monitor = this.element.querySelector('vn-horizontal');
const isHidden = monitor.classList.contains('hidden');
if (!isHidden)
monitor.classList.add('hidden');
else
monitor.classList.remove('hidden');
}
}
ngModule.vnComponent('vnMonitorIndex', { ngModule.vnComponent('vnMonitorIndex', {
template: require('./index.html'), template: require('./index.html'),
controller: Section controller: Controller,
require: {
main: '^vnMonitorIndex'
}
}); });

View File

@ -5,3 +5,4 @@ Search tickets: Buscar tickets
Delete selected elements: Eliminar los elementos seleccionados Delete selected elements: Eliminar los elementos seleccionados
All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar? All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar?
Component lack: Faltan componentes Component lack: Faltan componentes
Minimize/Maximize: Minimizar/Maximizar

View File

@ -1,4 +1,4 @@
<vn-crud-model <vn-crud-model auto-load="true"
vn-id="model" vn-id="model"
url="SalesMonitors/ordersFilter" url="SalesMonitors/ordersFilter"
limit="6" limit="6"
@ -15,6 +15,11 @@
ng-if="$ctrl.totalChecked > 0" ng-if="$ctrl.totalChecked > 0"
ng-click="delete.show()"> ng-click="delete.show()">
</vn-icon> </vn-icon>
<vn-icon class="arrow"
icon="keyboard_arrow_up"
vn-tooltip="Minimize/Maximize"
ng-click="$ctrl.main.toggle()">
</vn-icon>
<vn-icon <vn-icon
icon="refresh" icon="refresh"
vn-tooltip="Refresh" vn-tooltip="Refresh"
@ -31,13 +36,13 @@
model="model"> model="model">
</vn-multi-check> </vn-multi-check>
</vn-th> </vn-th>
<vn-th field="date_make" shrink-datetime default-order="DESC">Date</vn-th> <vn-th field="date_send" shrink-datetime>Date</vn-th>
<vn-th field="clientFk">Client</vn-th> <vn-th field="clientFk">Client</vn-th>
<vn-th>Import</vn-th> <vn-th field="salesPersonFk" shrink>SalesPerson</vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<a ng-repeat="order in model.data" <a ng-repeat="order in model.data"
class="clickable vn-tbody search-result" class="clickable vn-tbody"
ui-sref="order.card.summary({id: {{::order.id}}})" target="_blank"> ui-sref="order.card.summary({id: {{::order.id}}})" target="_blank">
<vn-tr> <vn-tr>
<vn-td> <vn-td>
@ -47,7 +52,7 @@
</vn-check> </vn-check>
</vn-td> </vn-td>
<vn-td> <vn-td>
<span class="chip success"> <span class="chip {{::$ctrl.chipColor(order.date_send)}}">
{{::order.date_send | date: 'dd/MM/yyyy'}} {{::order.date_send | date: 'dd/MM/yyyy'}}
</span> </span>
</vn-td> </vn-td>
@ -59,11 +64,18 @@
{{::order.clientName}} {{::order.clientName}}
</span> </span>
</vn-td> </vn-td>
<vn-td number>{{::order.import | currency: 'EUR':2}}</vn-td> <vn-td>
<span
title="{{::order.salesPerson}}"
vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)"
class="link">
{{::order.salesPerson | dashIfEmpty}}
</span>
</vn-td>
</vn-tr> </vn-tr>
<vn-tr> <vn-tr>
<vn-td></vn-td> <vn-td></vn-td>
<vn-td shrink-datetime> <vn-td>
<span> <span>
{{::order.date_make | date: 'dd/MM/yyyy HH:mm'}} {{::order.date_make | date: 'dd/MM/yyyy HH:mm'}}
</span> </span>
@ -74,22 +86,11 @@
</span> </span>
</vn-td> </vn-td>
<vn-td> <vn-td>
<span {{::order.import | currency: 'EUR':2}}
title="{{::order.salesPerson}}"
vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)"
class="link">
{{::order.salesPerson | dashIfEmpty}}
</span>
</vn-td> </vn-td>
</vn-tr> </vn-tr>
</a> </a>
</vn-table> </vn-table>
<div
ng-if="!model.data.length"
class="empty-rows vn-pa-sm"
translate>
No results
</div>
<vn-pagination <vn-pagination
model="model" model="model"
class="vn-pt-xs" class="vn-pt-xs"
@ -103,6 +104,35 @@
<vn-client-descriptor-popover <vn-client-descriptor-popover
vn-id="clientDescriptor"> vn-id="clientDescriptor">
</vn-client-descriptor-popover> </vn-client-descriptor-popover>
<vn-contextmenu vn-id="contextmenu" targets="['vn-monitor-sales-orders vn-table']" model="model"
expr-builder="$ctrl.exprBuilder(param, value)">
<slot-menu>
<vn-item translate
ng-if="contextmenu.isFilterAllowed()"
ng-click="contextmenu.filterBySelection()">
Filter by selection
</vn-item>
<vn-item translate
ng-if="contextmenu.isFilterAllowed()"
ng-click="contextmenu.excludeSelection()">
Exclude selection
</vn-item>
<vn-item translate
ng-if="contextmenu.isFilterAllowed()"
ng-click="contextmenu.removeFilter()">
Remove filter
</vn-item>
<vn-item translate
ng-click="contextmenu.removeAllFilters()">
Remove all filters
</vn-item>
<vn-item translate
ng-if="contextmenu.isActionAllowed()"
ng-click="contextmenu.copyValue()">
Copy value
</vn-item>
</slot-menu>
</vn-contextmenu>
<vn-confirm <vn-confirm
vn-id="delete" vn-id="delete"
on-accept="$ctrl.onDelete()" on-accept="$ctrl.onDelete()"

View File

@ -24,9 +24,51 @@ export default class Controller extends Section {
this.$http.post(query, params).then( this.$http.post(query, params).then(
() => this.$.model.refresh()); () => this.$.model.refresh());
} }
chipColor(date) {
const today = new Date();
today.setHours(0, 0, 0, 0);
const orderLanded = new Date(date);
orderLanded.setHours(0, 0, 0, 0);
const difference = today - orderLanded;
if (difference == 0)
return 'warning';
if (difference < 0)
return 'success';
if (difference > 0)
return 'alert';
}
exprBuilder(param, value) {
switch (param) {
case 'date_send':
return {[`o.date_send`]: {
between: this.dateRange(value)}
};
case 'clientFk':
return {[`c.id`]: value};
case 'salesPersonFk':
return {[`c.${param}`]: value};
}
}
dateRange(value) {
const minHour = new Date(value);
minHour.setHours(0, 0, 0, 0);
const maxHour = new Date(value);
maxHour.setHours(23, 59, 59, 59);
return [minHour, maxHour];
}
} }
ngModule.vnComponent('vnMonitorSalesOrders', { ngModule.vnComponent('vnMonitorSalesOrders', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller controller: Controller,
require: {
main: '^vnMonitorIndex'
}
}); });

View File

@ -2,7 +2,8 @@
vn-monitor-sales-orders { vn-monitor-sales-orders {
vn-table.scrollable { vn-table.scrollable {
max-height: 350px max-height: 350px;
overflow-x: hidden
} }
vn-table a.vn-tbody { vn-table a.vn-tbody {

View File

@ -21,36 +21,17 @@
ng-model="filter.orderFk"> ng-model="filter.orderFk">
</vn-textfield> </vn-textfield>
</vn-horizontal> </vn-horizontal>
<section class="vn-px-md"> <vn-horizontal class="vn-px-lg">
<vn-horizontal class="manifold-panel vn-pa-md"> <vn-input-number
<vn-date-picker vn-one
vn-one min="0"
label="From" step="1"
ng-model="filter.from" label="Days onward"
on-change="$ctrl.from = value"> ng-model="filter.scopeDays"
</vn-date-picker> on-change="$ctrl.scopeDays = value"
<vn-date-picker display-controls="true">
vn-one </vn-input-number>
label="To" </vn-horizontal>
ng-model="filter.to"
on-change="$ctrl.to = value">
</vn-date-picker>
<vn-none class="or vn-px-md" translate>Or</vn-none>
<vn-input-number
vn-one
min="0"
step="1"
label="Days onward"
ng-model="filter.scopeDays"
on-change="$ctrl.scopeDays = value"
display-controls="true">
</vn-input-number>
<vn-icon color-marginal
icon="info"
vn-tooltip="Cannot choose a range of dates and days onward at the same time">
</vn-icon>
</vn-horizontal>
</section>
<vn-horizontal class="vn-px-lg"> <vn-horizontal class="vn-px-lg">
<vn-textfield <vn-textfield
vn-one vn-one

View File

@ -3,52 +3,81 @@
vn-monitor-index { vn-monitor-index {
.header { .header {
padding: 12px 0; padding: 12px 0 5px 0;
color: gray; color: gray;
font-size: 1.2rem; font-size: 1.2rem;
border-bottom: 2px solid $color-font-secondary;
margin-bottom: 10px;
& > vn-none > vn-icon { & > vn-none > vn-icon {
@extend %clickable-light; @extend %clickable-light;
color: $color-button; color: $color-button;
font-size: 1.4rem; font-size: 1.4rem;
} }
}
.empty-rows { vn-none > .arrow {
color: $color-font-secondary; transition: transform 200ms;
text-align: center; }
} }
vn-vertical { vn-monitor-sales-clients {
position: fixed; vn-card {
width: 400px margin-right: 15px;
}
.header {
padding-right: 15px;
& > vn-none > .arrow {
display: none
}
}
}
vn-table.scrollable {
height: 300px
} }
vn-horizontal { vn-horizontal {
flex-wrap: wrap flex-wrap: wrap
} }
}
@media (max-width:1500px) { .hidden {
vn-monitor-index { vn-card {
& > vn-horizontal { display: none
flex-direction: column-reverse;
} }
& > vn-horizontal > vn-one { .header > vn-none > .arrow {
flex: none; transform: rotate(180deg);
width: 100%; }
}
}
& > vn-vertical { @media (max-width:1150px) {
position: initial; vn-monitor-index {
flex-direction: row; & > vn-horizontal {
width: 100%; flex-direction: column;
vn-monitor-sales-clients { vn-monitor-sales-clients,
margin-right: 15px vn-monitor-sales-orders {
} width: 100%
}
vn-table.scrollable { vn-monitor-sales-clients {
height: 300px margin-bottom: 15px
}
}
vn-monitor-sales-clients {
vn-card {
margin-right: 0
}
.header {
padding-right: 0;
& > vn-none > .arrow {
display: inline-block
} }
} }
} }

View File

@ -115,6 +115,14 @@ describe('Component vnMonitorSalesTickets', () => {
}); });
}); });
describe('totalPriceColor()', () => {
it('should return "warning" when the ticket amount is less than 50€', () => {
const result = controller.totalPriceColor({totalWithVat: '8.50'});
expect(result).toEqual('warning');
});
});
describe('preview()', () => { describe('preview()', () => {
it('should show the dialog summary', () => { it('should show the dialog summary', () => {
controller.$.summary = {show: () => {}}; controller.$.summary = {show: () => {}};

View File

@ -49,6 +49,7 @@
rule> rule>
</vn-input-number> </vn-input-number>
</vn-horizontal> </vn-horizontal>
</vn-card>
<vn-button-bar> <vn-button-bar>
<vn-submit <vn-submit
label="Save" label="Save"

View File

@ -34,14 +34,14 @@ module.exports = Self => {
e.checked, e.checked,
i2.name freightItemName, i2.name freightItemName,
e.itemFk, e.itemFk,
u.nickname userNickname, u.name userName,
e.created, e.created,
e.externalId, e.externalId,
i3.name packagingName, i3.name packagingName,
i3.id packagingItemFk, i3.id packagingItemFk,
e.packagingFk, e.packagingFk,
es.workerFk expeditionScanWorkerFk, es.workerFk expeditionScanWorkerFk,
su.nickname scannerUserNickname, su.name scannerUserName,
es.scanned es.scanned
FROM FROM
vn.expedition e vn.expedition e

View File

@ -17,6 +17,8 @@ describe('ticket makeInvoice()', () => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx active: activeCtx
}); });
done();
}); });
afterAll(async done => { afterAll(async done => {

View File

@ -8,60 +8,62 @@
</vn-crud-model> </vn-crud-model>
<vn-data-viewer model="model" class="vn-w-xl"> <vn-data-viewer model="model" class="vn-w-xl">
<vn-card class="vn-mt-md"> <vn-card class="vn-mt-md">
<table class="vn-table"> <div class="tableWrapper">
<thead> <table class="vn-table">
<tr> <thead>
<th number translate>Item</th> <tr>
<th translate expand>Description</th> <th number translate>Item</th>
<th number translate>Quantity</th> <th translate expand>Description</th>
<th translate>Serie</th> <th number translate>Quantity</th>
<th translate>Components</th> <th translate>Serie</th>
<th number translate>Import</th> <th translate>Components</th>
<th number translate>Total</th> <th number translate>Import</th>
</tr> <th number translate>Total</th>
</thead> </tr>
<tbody ng-repeat="sale in components track by sale.id"> </thead>
<tr class="initial"> <tbody ng-repeat="sale in components track by sale.id">
<td rowspan="{{::sale.components.length + 1}}" number> <tr class="initial">
<span <td rowspan="{{::sale.components.length + 1}}" number>
ng-click="itemDescriptor.show($event, sale.itemFk, sale.id)" <span
class="link"> ng-click="itemDescriptor.show($event, sale.itemFk, sale.id)"
{{sale.itemFk | zeroFill:6}} class="link">
</span> {{sale.itemFk | zeroFill:6}}
</td> </span>
<td rowspan="{{::sale.components.length + 1}}" vn-fetched-tags> </td>
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one> <td rowspan="{{::sale.components.length + 1}}" vn-fetched-tags>
<vn-one ng-if="::sale.item.subName"> <vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3> <vn-one ng-if="::sale.item.subName">
</vn-one> <h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
<vn-fetched-tags </vn-one>
max-length="6" <vn-fetched-tags
item="::sale.item" max-length="6"
tabindex="-1"> item="::sale.item"
</vn-fetched-tags> tabindex="-1">
</td> </vn-fetched-tags>
<td rowspan="{{::sale.components.length + 1}}" number> </td>
{{::sale.quantity}} <td rowspan="{{::sale.components.length + 1}}" number>
</td> {{::sale.quantity}}
</tr> </td>
<tr </tr>
ng-repeat="saleComponent in sale.components track by saleComponent.componentFk" <tr
class="components"> ng-repeat="saleComponent in sale.components track by saleComponent.componentFk"
<td> class="components">
{{::saleComponent.component.componentType.type}} <td>
</td> {{::saleComponent.component.componentType.type}}
<td> </td>
{{::saleComponent.component.name}} <td>
</td> {{::saleComponent.component.name}}
<td number> </td>
{{::saleComponent.value | currency: 'EUR':3}} <td number>
</td> {{::saleComponent.value | currency: 'EUR':3}}
<td number> </td>
{{::sale.quantity * saleComponent.value | currency: 'EUR':3}} <td number>
</td> {{::sale.quantity * saleComponent.value | currency: 'EUR':3}}
</tr> </td>
</tbody> </tr>
</table> </tbody>
</table>
</div>
</vn-card> </vn-card>
</vn-data-viewer> </vn-data-viewer>
<vn-side-menu side="right"> <vn-side-menu side="right">

View File

@ -15,14 +15,14 @@
<vn-th></vn-th> <vn-th></vn-th>
<vn-th field="itemFk" number>Expedition</vn-th> <vn-th field="itemFk" number>Expedition</vn-th>
<vn-th field="itemFk" number>Item</vn-th> <vn-th field="itemFk" number>Item</vn-th>
<vn-th field="name">Name</vn-th> <vn-th field="packageItemName">Name</vn-th>
<vn-th field="isBox">Package type</vn-th> <vn-th field="freightItemName">Package type</vn-th>
<vn-th field="counter" number>Counter</vn-th> <vn-th field="counter" number>Counter</vn-th>
<vn-th field="externalId" number>externalId</vn-th> <vn-th field="externalId" number>externalId</vn-th>
<vn-th field="worker">Packager</vn-th> <vn-th field="workerFk">Packager</vn-th>
<vn-th field="created" expand>Created</vn-th> <vn-th field="created" expand>Created</vn-th>
<vn-th field="scanned" expand>Scanned</vn-th>
<vn-th field="expeditionScanWorkerFk">Palletizer</vn-th> <vn-th field="expeditionScanWorkerFk">Palletizer</vn-th>
<vn-th field="scanned" expand>Scanned</vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
@ -44,21 +44,21 @@
<vn-td>{{::expedition.packageItemName}}</vn-td> <vn-td>{{::expedition.packageItemName}}</vn-td>
<vn-td>{{::expedition.freightItemName}}</vn-td> <vn-td>{{::expedition.freightItemName}}</vn-td>
<vn-td number>{{::expedition.counter}}</vn-td> <vn-td number>{{::expedition.counter}}</vn-td>
<vn-td number>{{::expedition.externalId}}</vn-td> <vn-td expand>{{::expedition.externalId}}</vn-td>
<vn-td expand> <vn-td>
<span <span
class="link" class="link"
ng-click="workerDescriptor.show($event, expedition.workerFk)"> ng-click="workerDescriptor.show($event, expedition.workerFk)">
{{::expedition.userNickname | dashIfEmpty}} {{::expedition.userName | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand>{{::expedition.created | date:'dd/MM/yyyy HH:mm'}}</vn-td> <vn-td shrink-datetime>{{::expedition.created | date:'dd/MM/yyyy HH:mm'}}</vn-td>
<vn-td expand>{{::expedition.scanned | date:'dd/MM/yyyy HH:mm'}}</vn-td> <vn-td>
<vn-td expand>
<span class="link" ng-click="workerDescriptor.show($event, expedition.expeditionScanWorkerFk)"> <span class="link" ng-click="workerDescriptor.show($event, expedition.expeditionScanWorkerFk)">
{{::expedition.scannerUserNickname | dashIfEmpty}} {{::expedition.scannerUserName | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td shrink-datetime>{{::expedition.scanned | date:'dd/MM/yyyy HH:mm'}}</vn-td>
</vn-tr> </vn-tr>
</vn-tbody> </vn-tbody>
</vn-table> </vn-table>

View File

@ -5,149 +5,149 @@
model="model" model="model"
class="vn-mb-xl vn-w-xl"> class="vn-mb-xl vn-w-xl">
<vn-card> <vn-card>
<vn-table model="model"> <vn-table model="model">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th shrink> <vn-th shrink>
<vn-multi-check <vn-multi-check
model="model"> model="model">
</vn-multi-check> </vn-multi-check>
</vn-th> </vn-th>
<vn-th class="icon-field"></vn-th> <vn-th class="icon-field"></vn-th>
<vn-th field="id">Id</vn-th> <vn-th field="id">Id</vn-th>
<vn-th field="salesPersonFk" class="expendable">Salesperson</vn-th> <vn-th field="salesPersonFk" class="expendable">Salesperson</vn-th>
<vn-th field="shipped" shrink-date>Date</vn-th> <vn-th field="shipped" shrink-date>Date</vn-th>
<vn-th>Hour</vn-th> <vn-th>Hour</vn-th>
<vn-th field="zoneHour" shrink>Closure</vn-th> <vn-th field="zoneHour" shrink>Closure</vn-th>
<vn-th field="nickname">Alias</vn-th> <vn-th field="nickname">Alias</vn-th>
<vn-th field="provinceFk" class="expendable">Province</vn-th> <vn-th field="provinceFk" class="expendable">Province</vn-th>
<vn-th field="stateFk" >State</vn-th> <vn-th field="stateFk" >State</vn-th>
<vn-th field="zoneFk">Zone</vn-th> <vn-th field="zoneFk">Zone</vn-th>
<vn-th field="warehouseFk">Warehouse</vn-th> <vn-th field="warehouseFk">Warehouse</vn-th>
<vn-th number>Total</vn-th> <vn-th number>Total</vn-th>
<vn-th></vn-th> <vn-th></vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
<a ng-repeat="ticket in model.data" <a ng-repeat="ticket in model.data"
class="clickable vn-tr search-result" class="clickable vn-tr search-result"
ui-sref="ticket.card.summary({id: {{::ticket.id}}})"> ui-sref="ticket.card.summary({id: {{::ticket.id}}})">
<vn-td> <vn-td>
<vn-check <vn-check
ng-model="ticket.checked" ng-model="ticket.checked"
vn-click-stop> vn-click-stop>
</vn-check> </vn-check>
</vn-td> </vn-td>
<vn-td class="icon-field"> <vn-td class="icon-field">
<vn-icon <vn-icon
ng-show="::ticket.isTaxDataChecked === 0" ng-show="::ticket.isTaxDataChecked === 0"
translate-attr="{title: 'No verified data'}" translate-attr="{title: 'No verified data'}"
class="bright" class="bright"
icon="icon-no036"> icon="icon-no036">
</vn-icon> </vn-icon>
<vn-icon <vn-icon
ng-show="::ticket.hasTicketRequest" ng-show="::ticket.hasTicketRequest"
translate-attr="{title: 'Purchase request'}" translate-attr="{title: 'Purchase request'}"
class="bright" class="bright"
icon="icon-100"> icon="icon-100">
</vn-icon> </vn-icon>
<vn-icon <vn-icon
ng-show="::ticket.isAvailable === 0" ng-show="::ticket.isAvailable === 0"
translate-attr="{title: 'Not available'}" translate-attr="{title: 'Not available'}"
class="bright" class="bright"
icon="icon-unavailable"> icon="icon-unavailable">
</vn-icon> </vn-icon>
<vn-icon <vn-icon
ng-show="::ticket.isFreezed" ng-show="::ticket.isFreezed"
translate-attr="{title: 'Client frozen'}" translate-attr="{title: 'Client frozen'}"
class="bright" class="bright"
icon="icon-frozen"> icon="icon-frozen">
</vn-icon> </vn-icon>
<vn-icon <vn-icon
ng-show="::ticket.risk" ng-show="::ticket.risk"
title="{{::$ctrl.$t('Risk')}}: {{ticket.risk}}" title="{{::$ctrl.$t('Risk')}}: {{ticket.risk}}"
class="bright" class="bright"
icon="icon-risk"> icon="icon-risk">
</vn-icon> </vn-icon>
<vn-icon <vn-icon
ng-show="::ticket.hasComponentLack" ng-show="::ticket.hasComponentLack"
translate-attr="{title: 'Component lack'}" translate-attr="{title: 'Component lack'}"
class="bright" class="bright"
icon="icon-components"> icon="icon-components">
</vn-icon> </vn-icon>
</vn-td> </vn-td>
<vn-td shrink>{{::ticket.id}}</vn-td> <vn-td shrink>{{::ticket.id}}</vn-td>
<vn-td class="expendable"> <vn-td class="expendable">
<span <span
title="{{::ticket.userName}}" title="{{::ticket.userName}}"
vn-click-stop="workerDescriptor.show($event, ticket.salesPersonFk)" vn-click-stop="workerDescriptor.show($event, ticket.salesPersonFk)"
class="link"> class="link">
{{::ticket.userName | dashIfEmpty}} {{::ticket.userName | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td shrink-date> <vn-td shrink-date>
<span class="chip {{$ctrl.compareDate(ticket.shipped)}}"> <span class="chip {{$ctrl.compareDate(ticket.shipped)}}">
{{::ticket.shipped | date: 'dd/MM/yyyy'}} {{::ticket.shipped | date: 'dd/MM/yyyy'}}
</span> </span>
</vn-td> </vn-td>
<vn-td shrink>{{::ticket.shipped | date: 'HH:mm'}}</vn-td> <vn-td shrink>{{::ticket.shipped | date: 'HH:mm'}}</vn-td>
<vn-td shrink>{{::ticket.zoneLanding | date: 'HH:mm'}}</vn-td> <vn-td shrink>{{::ticket.zoneLanding | date: 'HH:mm'}}</vn-td>
<vn-td> <vn-td>
<span <span
title="{{::ticket.nickname}}" title="{{::ticket.nickname}}"
vn-click-stop="clientDescriptor.show($event, ticket.clientFk)" vn-click-stop="clientDescriptor.show($event, ticket.clientFk)"
class="link"> class="link">
{{::ticket.nickname}} {{::ticket.nickname}}
</span> </span>
</vn-td> </vn-td>
<vn-td class="expendable">{{::ticket.province}}</vn-td> <vn-td class="expendable">{{::ticket.province}}</vn-td>
<vn-td class="expendable"> <vn-td class="expendable">
<span <span
ng-show="ticket.refFk" ng-show="ticket.refFk"
title="{{::ticket.refFk}}" title="{{::ticket.refFk}}"
vn-click-stop="invoiceOutDescriptor.show($event, ticket.invoiceOutId)" vn-click-stop="invoiceOutDescriptor.show($event, ticket.invoiceOutId)"
class="link"> class="link">
{{::ticket.refFk}} {{::ticket.refFk}}
</span> </span>
<span <span
ng-show="!ticket.refFk" ng-show="!ticket.refFk"
class="chip {{$ctrl.stateColor(ticket)}}"> class="chip {{$ctrl.stateColor(ticket)}}">
{{ticket.state}} {{ticket.state}}
</span> </span>
</vn-td> </vn-td>
<vn-td> <vn-td>
<span <span
title="{{::ticket.zoneName}}" title="{{::ticket.zoneName}}"
vn-click-stop="zoneDescriptor.show($event, ticket.zoneFk)" vn-click-stop="zoneDescriptor.show($event, ticket.zoneFk)"
class="link"> class="link">
{{::ticket.zoneName | dashIfEmpty}} {{::ticket.zoneName | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td>{{::ticket.warehouse}}</vn-td> <vn-td>{{::ticket.warehouse}}</vn-td>
<vn-td number> <vn-td number>
<span class="chip {{$ctrl.totalPriceColor(ticket)}}"> <span class="chip {{$ctrl.totalPriceColor(ticket)}}">
{{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} {{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}
</span> </span>
</vn-td> </vn-td>
<vn-td actions> <vn-td actions>
<vn-icon-button <vn-icon-button
vn-anchor="::{ vn-anchor="::{
state: 'ticket.card.sale', state: 'ticket.card.sale',
params: {id: ticket.id}, params: {id: ticket.id},
target: '_blank' target: '_blank'
}" }"
vn-tooltip="Go to lines" vn-tooltip="Go to lines"
icon="icon-lines"> icon="icon-lines">
</vn-icon-button> </vn-icon-button>
<vn-icon-button <vn-icon-button
vn-click-stop="$ctrl.preview(ticket)" vn-click-stop="$ctrl.preview(ticket)"
vn-tooltip="Preview" vn-tooltip="Preview"
icon="preview"> icon="preview">
</vn-icon-button> </vn-icon-button>
</vn-td> </vn-td>
</a> </a>
</vn-tbody> </vn-tbody>
</vn-table> </vn-table>
</vn-card> </vn-card>
</vn-data-viewer> </vn-data-viewer>
<div fixed-bottom-right> <div fixed-bottom-right>

View File

@ -18,6 +18,13 @@
translate> translate>
Clone travel and his entries Clone travel and his entries
</vn-item> </vn-item>
<vn-item
id="delete"
ng-click="delete.show()"
ng-show="$ctrl.isBuyer && !$ctrl.entries.length"
translate>
Delete travel
</vn-item>
<a class="vn-item" <a class="vn-item"
ui-sref="entry.create({travelFk: $ctrl.travel.id})" ui-sref="entry.create({travelFk: $ctrl.travel.id})"
name="addEntry" name="addEntry"
@ -35,6 +42,14 @@
message="All it's properties will be copied"> message="All it's properties will be copied">
</vn-confirm> </vn-confirm>
<!-- Delete travel popup -->
<vn-confirm
vn-id="delete"
on-accept="$ctrl.onDeleteAccept()"
question="Do you want to delete this travel?"
message="The travel will be deleted">
</vn-confirm>
<!-- Clone travel popup --> <!-- Clone travel popup -->
<vn-confirm <vn-confirm
vn-id="cloneWithEntries" vn-id="cloneWithEntries"

View File

@ -44,14 +44,23 @@ class Controller extends Section {
} }
] ]
}; };
return this.$http.get(`Travels/${this.travelId}`, {filter}) this.$http.get(`Travels/${this.travelId}`, {filter})
.then(res => this.travel = res.data); .then(res => this.travel = res.data);
this.$http.get(`Travels/${this.travelId}/getEntries`)
.then(res => this.entries = res.data);
} }
get isBuyer() { get isBuyer() {
return this.aclService.hasAny(['buyer']); return this.aclService.hasAny(['buyer']);
} }
onDeleteAccept() {
this.$http.delete(`Travels/${this.travelId}`)
.then(() => this.$state.go('travel.index'))
.then(() => this.vnApp.showSuccess(this.$t('Travel deleted')));
}
onCloneAccept() { onCloneAccept() {
const params = JSON.stringify({ const params = JSON.stringify({
ref: this.travel.ref, ref: this.travel.ref,

View File

@ -40,6 +40,21 @@ describe('Travel Component vnTravelDescriptorMenu', () => {
}); });
}); });
describe('onDeleteAccept()', () => {
it('should perform a delete query', () => {
jest.spyOn(controller.$state, 'go').mockReturnValue('ok');
controller.travelId = 1;
$httpBackend.when('GET', `Travels/${controller.travelId}`).respond(200);
$httpBackend.when('GET', `Travels/${controller.travelId}/getEntries`).respond(200);
$httpBackend.expect('DELETE', `Travels/${controller.travelId}`).respond(200);
controller.onDeleteAccept();
$httpBackend.flush();
expect(controller.$state.go).toHaveBeenCalledWith('travel.index');
});
});
describe('onCloneWithEntriesAccept()', () => { describe('onCloneWithEntriesAccept()', () => {
it('should make an HTTP query and then call to the $state.go method with the returned id', () => { it('should make an HTTP query and then call to the $state.go method with the returned id', () => {
jest.spyOn(controller.$state, 'go').mockReturnValue('ok'); jest.spyOn(controller.$state, 'go').mockReturnValue('ok');

View File

@ -2,3 +2,7 @@ Clone travel: Clonar envío
Add entry: Añadir entrada Add entry: Añadir entrada
Clone travel and his entries: Clonar travel y sus entradas Clone travel and his entries: Clonar travel y sus entradas
Do you want to clone this travel and all containing entries?: ¿Quieres clonar este travel y todas las entradas que contiene? Do you want to clone this travel and all containing entries?: ¿Quieres clonar este travel y todas las entradas que contiene?
Delete travel: Eliminar envío
The travel will be deleted: El envío será eliminado
Do you want to delete this travel?: ¿Quieres eliminar este envío?
Travel deleted: Envío eliminado

255
package-lock.json generated
View File

@ -2851,12 +2851,6 @@
"stack-chain": "^1.3.7" "stack-chain": "^1.3.7"
} }
}, },
"async-limiter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
"dev": true
},
"async-settle": { "async-settle": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz",
@ -3597,16 +3591,16 @@
} }
}, },
"browserslist": { "browserslist": {
"version": "4.16.3", "version": "4.16.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
"integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"caniuse-lite": "^1.0.30001181", "caniuse-lite": "^1.0.30001219",
"colorette": "^1.2.1", "colorette": "^1.2.2",
"electron-to-chromium": "^1.3.649", "electron-to-chromium": "^1.3.723",
"escalade": "^3.1.1", "escalade": "^3.1.1",
"node-releases": "^1.1.70" "node-releases": "^1.1.71"
} }
}, },
"bser": { "bser": {
@ -3824,9 +3818,9 @@
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30001200", "version": "1.0.30001237",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001200.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001237.tgz",
"integrity": "sha512-ic/jXfa6tgiPBAISWk16jRI2q8YfjxHnSG7ddSL1ptrIP8Uy11SayFrjXRAk3NumHpDb21fdTkbTxb/hOrFrnQ==", "integrity": "sha512-pDHgRndit6p1NR2GhzMbQ6CkRrp4VKuSsqbcLeOQppYPKOYkKT/6ZvZDvKJUqcmtyWIAHuZq3SVS2vc1egCZzw==",
"dev": true "dev": true
}, },
"canonical-json": { "canonical-json": {
@ -4589,21 +4583,67 @@
} }
}, },
"css-select": { "css-select": {
"version": "2.1.0", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
"integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
"dev": true, "dev": true,
"requires": { "requires": {
"boolbase": "^1.0.0", "boolbase": "^1.0.0",
"css-what": "^3.2.1", "css-what": "^5.0.0",
"domutils": "^1.7.0", "domhandler": "^4.2.0",
"nth-check": "^1.0.2" "domutils": "^2.6.0",
"nth-check": "^2.0.0"
},
"dependencies": {
"dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"dev": true,
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
}
},
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
"dev": true
},
"domhandler": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
"dev": true,
"requires": {
"domelementtype": "^2.2.0"
}
},
"domutils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
"dev": true,
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
}
},
"entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"dev": true
}
} }
}, },
"css-what": { "css-what": {
"version": "3.4.2", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
"integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
"dev": true "dev": true
}, },
"cssesc": { "cssesc": {
@ -5031,9 +5071,9 @@
"dev": true "dev": true
}, },
"dns-packet": { "dns-packet": {
"version": "1.3.1", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
"integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
"dev": true, "dev": true,
"requires": { "requires": {
"ip": "^1.1.0", "ip": "^1.1.0",
@ -5282,9 +5322,9 @@
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.687", "version": "1.3.752",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.687.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz",
"integrity": "sha512-IpzksdQNl3wdgkzf7dnA7/v10w0Utf1dF2L+B4+gKrloBrxCut+au+kky3PYvle3RMdSxZP+UiCZtLbcYRxSNQ==", "integrity": "sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==",
"dev": true "dev": true
}, },
"elliptic": { "elliptic": {
@ -8336,9 +8376,9 @@
} }
}, },
"hosted-git-info": { "hosted-git-info": {
"version": "2.8.8", "version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true "dev": true
}, },
"hpack.js": { "hpack.js": {
@ -8709,12 +8749,12 @@
"integrity": "sha512-wcGvY31MpFNHIkUcXHHnvrE4IKYlpvitJw5P/1u892gMBAM46muQ+RH7UN1d+Ntnfx5apnOnVY6vcLmrWHOLwg==" "integrity": "sha512-wcGvY31MpFNHIkUcXHHnvrE4IKYlpvitJw5P/1u892gMBAM46muQ+RH7UN1d+Ntnfx5apnOnVY6vcLmrWHOLwg=="
}, },
"httpntlm": { "httpntlm": {
"version": "1.6.1", "version": "1.7.7",
"resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.7.7.tgz",
"integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "integrity": "sha512-Pv2Rvrz8H0qv1Dne5mAdZ9JegG1uc6Vu5lwLflIY6s8RKHdZQbW39L4dYswSgqMDT0pkJILUTKjeyU0VPNRZjA==",
"requires": { "requires": {
"httpreq": ">=0.4.22", "httpreq": ">=0.4.22",
"underscore": "~1.7.0" "underscore": "~1.12.1"
} }
}, },
"httpreq": { "httpreq": {
@ -13392,9 +13432,9 @@
} }
}, },
"node-releases": { "node-releases": {
"version": "1.1.71", "version": "1.1.73",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz",
"integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==",
"dev": true "dev": true
}, },
"node-sass": { "node-sass": {
@ -13639,9 +13679,9 @@
"dev": true "dev": true
}, },
"normalize-url": { "normalize-url": {
"version": "4.5.0", "version": "4.5.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
"dev": true "dev": true
}, },
"now-and-later": { "now-and-later": {
@ -13673,12 +13713,12 @@
} }
}, },
"nth-check": { "nth-check": {
"version": "1.0.2", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"boolbase": "~1.0.0" "boolbase": "^1.0.0"
} }
}, },
"number-is-nan": { "number-is-nan": {
@ -14555,9 +14595,9 @@
"integrity": "sha1-Su7rfa3mb8qKk2XdqfawBXQctiE=" "integrity": "sha1-Su7rfa3mb8qKk2XdqfawBXQctiE="
}, },
"postcss": { "postcss": {
"version": "7.0.35", "version": "7.0.36",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
"integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
"dev": true, "dev": true,
"requires": { "requires": {
"chalk": "^2.4.2", "chalk": "^2.4.2",
@ -15442,16 +15482,16 @@
"dev": true "dev": true
}, },
"renderkid": { "renderkid": {
"version": "2.0.5", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz",
"integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==", "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"css-select": "^2.0.2", "css-select": "^4.1.3",
"dom-converter": "^0.2", "dom-converter": "^0.2.0",
"htmlparser2": "^3.10.1", "htmlparser2": "^6.1.0",
"lodash": "^4.17.20", "lodash": "^4.17.21",
"strip-ansi": "^3.0.0" "strip-ansi": "^3.0.1"
}, },
"dependencies": { "dependencies": {
"ansi-regex": { "ansi-regex": {
@ -15460,6 +15500,61 @@
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true "dev": true
}, },
"dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"dev": true,
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
}
},
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
"dev": true
},
"domhandler": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
"dev": true,
"requires": {
"domelementtype": "^2.2.0"
}
},
"domutils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
"integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
"dev": true,
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
}
},
"entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"dev": true
},
"htmlparser2": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
"dev": true,
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"domutils": "^2.5.2",
"entities": "^2.0.0"
}
},
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@ -16669,6 +16764,22 @@
"requires": { "requires": {
"httpntlm": "1.6.1", "httpntlm": "1.6.1",
"nodemailer-shared": "1.1.0" "nodemailer-shared": "1.1.0"
},
"dependencies": {
"httpntlm": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz",
"integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=",
"requires": {
"httpreq": ">=0.4.22",
"underscore": "~1.7.0"
}
},
"underscore": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",
"integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk="
}
} }
}, },
"snakeize": { "snakeize": {
@ -18603,9 +18714,9 @@
} }
}, },
"underscore": { "underscore": {
"version": "1.7.0", "version": "1.12.1",
"resolved": "http://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
"integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw=="
}, },
"underscore.string": { "underscore.string": {
"version": "3.3.5", "version": "3.3.5",
@ -20112,12 +20223,20 @@
} }
}, },
"ws": { "ws": {
"version": "6.2.1", "version": "6.2.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
"dev": true, "dev": true,
"requires": { "requires": {
"async-limiter": "~1.0.0" "async-limiter": "~1.0.0"
},
"dependencies": {
"async-limiter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
"dev": true
}
} }
}, },
"yargs": { "yargs": {
@ -20402,9 +20521,9 @@
} }
}, },
"ws": { "ws": {
"version": "7.4.4", "version": "7.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz",
"integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==" "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw=="
}, },
"x-xss-protection": { "x-xss-protection": {
"version": "1.3.0", "version": "1.3.0",

View File

@ -24,7 +24,7 @@ module.exports = {
* *
* @return {Object} - Pool connection * @return {Object} - Pool connection
*/ */
getConnection(name) { getConnection(name = 'default') {
let pool = this.pool; let pool = this.pool;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
pool.getConnection(name, function(error, connection) { pool.getConnection(name, function(error, connection) {

View File

@ -15,22 +15,11 @@ module.exports = {
continent: this.continent continent: this.continent
}; };
const connection = await db.pool.getConnection(); const travels = await this.fetchTravels(args);
const travelIds = travels.map(travel => travel.id);
await this.fetchTravels(args, connection); const entries = await this.fetchEntries(travelIds);
const travels = await this.rawSql(`
SELECT * FROM tmp.travel`, connection);
const entries = await this.fetchEntries(connection);
await this.rawSql(`
DROP TEMPORARY TABLE
tmp.travel`, connection);
await connection.release();
const map = new Map(); const map = new Map();
for (let travel of travels) for (let travel of travels)
map.set(travel.id, travel); map.set(travel.id, travel);
@ -71,7 +60,7 @@ module.exports = {
} }
}, },
methods: { methods: {
fetchTravels(args, connection) { fetchTravels(args) {
const where = db.buildWhere(args, (key, value) => { const where = db.buildWhere(args, (key, value) => {
switch (key) { switch (key) {
case 'shippedFrom': case 'shippedFrom':
@ -91,14 +80,11 @@ module.exports = {
query = db.merge(query, where); query = db.merge(query, where);
query = db.merge(query, 'GROUP BY t.id'); query = db.merge(query, 'GROUP BY t.id');
return this.rawSql(query, connection); return this.rawSql(query);
}, },
fetchEntries(connection) { fetchEntries(travelIds) {
let query = this.getSqlFromDef('entries'); return this.rawSqlFromDef('entries', [travelIds]);
query = db.merge(query, 'GROUP BY e.id');
return this.rawSql(query, connection);
} }
}, },
components: { components: {

View File

@ -1,15 +1,17 @@
SELECT SELECT
e.id, e.id,
e.travelFk, e.travelFk,
e.ref, e.ref,
s.name AS supplierName, s.name AS supplierName,
SUM(b.stickers) AS stickers, SUM(b.stickers) AS stickers,
CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg, CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg,
CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg
FROM tmp.travel t FROM travel t
JOIN entry e ON e.travelFk = t.id JOIN entry e ON e.travelFk = t.id
JOIN buy b ON b.entryFk = e.id JOIN buy b ON b.entryFk = e.id
JOIN packaging pkg ON pkg.id = b.packageFk JOIN packaging pkg ON pkg.id = b.packageFk
JOIN item i ON i.id = b.itemFk JOIN item i ON i.id = b.itemFk
JOIN itemType it ON it.id = i.typeFk JOIN itemType it ON it.id = i.typeFk
JOIN supplier s ON s.id = e.supplierFk JOIN supplier s ON s.id = e.supplierFk
WHERE t.id IN(?)
GROUP BY e.id

View File

@ -1,24 +1,21 @@
CREATE TEMPORARY TABLE tmp.travel SELECT
(INDEX (id)) t.id,
ENGINE = MEMORY t.ref,
SELECT t.shipped,
t.id, t.landed,
t.ref, t.kg,
t.shipped, SUM(b.stickers) AS stickers,
t.landed, CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg,
t.kg, CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg
SUM(b.stickers) AS stickers, FROM travel t
CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg, LEFT JOIN supplier s ON s.id = t.cargoSupplierFk
CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg LEFT JOIN entry e ON e.travelFk = t.id
FROM travel t LEFT JOIN buy b ON b.entryFk = e.id
LEFT JOIN supplier s ON s.id = t.cargoSupplierFk LEFT JOIN packaging pkg ON pkg.id = b.packageFk
LEFT JOIN entry e ON e.travelFk = t.id LEFT JOIN item i ON i.id = b.itemFk
LEFT JOIN buy b ON b.entryFk = e.id LEFT JOIN itemType it ON it.id = i.typeFk
LEFT JOIN packaging pkg ON pkg.id = b.packageFk JOIN warehouse w ON w.id = t.warehouseInFk
LEFT JOIN item i ON i.id = b.itemFk JOIN warehouse wo ON wo.id = t.warehouseOutFk
LEFT JOIN itemType it ON it.id = i.typeFk JOIN country c ON c.id = wo.countryFk
JOIN warehouse w ON w.id = t.warehouseInFk LEFT JOIN continent cnt ON cnt.id = c.continentFk
JOIN warehouse wo ON wo.id = t.warehouseOutFk JOIN agencyMode am ON am.id = t.agencyFk
JOIN country c ON c.id = wo.countryFk
LEFT JOIN continent cnt ON cnt.id = c.continentFk
JOIN agencyMode am ON am.id = t.agencyFk