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,6 +10,7 @@
</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">
<div class="tableWrapper">
<vn-horizontal class="header"> <vn-horizontal class="header">
<vn-tool-bar class="vn-mb-md"> <vn-tool-bar class="vn-mb-md">
<vn-button <vn-button
@ -167,7 +168,7 @@
{{::buy.item.minPrice | currency: 'EUR':2}} {{::buy.item.minPrice | currency: 'EUR':2}}
</span> </span>
</td> </td>
<td vn-fetched-tags colspan="9"> <td vn-fetched-tags colspan="8">
<vn-one title="{{::buy.item.name}}">{{::buy.item.name}}</vn-one> <vn-one title="{{::buy.item.name}}">{{::buy.item.name}}</vn-one>
<vn-fetched-tags <vn-fetched-tags
max-length="6" max-length="6"
@ -176,6 +177,7 @@
</vn-fetched-tags> </vn-fetched-tags>
</td> </td>
</tr> </tr>
<tr><td></td></tr>
</tbody> </tbody>
</table> </table>
<div> <div>
@ -187,6 +189,7 @@
ng-click="model.insert({})"> ng-click="model.insert({})">
</vn-icon-button> </vn-icon-button>
</div> </div>
</div>
</vn-card> </vn-card>
</div> </div>
<div fixed-bottom-right> <div fixed-bottom-right>

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-tickets></vn-monitor-sales-tickets>
</vn-three>
<vn-one>
<vn-vertical>
<vn-monitor-sales-clients class="vn-mb-sm"></vn-monitor-sales-clients> <vn-monitor-sales-clients class="vn-mb-sm"></vn-monitor-sales-clients>
<vn-monitor-sales-orders></vn-monitor-sales-orders> <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,21 +21,7 @@
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-date-picker
vn-one
label="From"
ng-model="filter.from"
on-change="$ctrl.from = value">
</vn-date-picker>
<vn-date-picker
vn-one
label="To"
ng-model="filter.to"
on-change="$ctrl.to = value">
</vn-date-picker>
<vn-none class="or vn-px-md" translate>Or</vn-none>
<vn-input-number <vn-input-number
vn-one vn-one
min="0" min="0"
@ -45,12 +31,7 @@
on-change="$ctrl.scopeDays = value" on-change="$ctrl.scopeDays = value"
display-controls="true"> display-controls="true">
</vn-input-number> </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> </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,53 +3,82 @@
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 {
color: $color-font-secondary;
text-align: center;
}
vn-vertical { vn-none > .arrow {
position: fixed; transition: transform 200ms;
width: 400px
}
vn-horizontal {
flex-wrap: wrap
} }
} }
@media (max-width:1500px) {
vn-monitor-index {
& > vn-horizontal {
flex-direction: column-reverse;
}
& > vn-horizontal > vn-one {
flex: none;
width: 100%;
& > vn-vertical {
position: initial;
flex-direction: row;
width: 100%;
vn-monitor-sales-clients { vn-monitor-sales-clients {
margin-right: 15px vn-card {
margin-right: 15px;
}
.header {
padding-right: 15px;
& > vn-none > .arrow {
display: none
}
}
} }
vn-table.scrollable { vn-table.scrollable {
height: 300px height: 300px
} }
vn-horizontal {
flex-wrap: wrap
}
.hidden {
vn-card {
display: none
}
.header > vn-none > .arrow {
transform: rotate(180deg);
}
}
}
@media (max-width:1150px) {
vn-monitor-index {
& > vn-horizontal {
flex-direction: column;
vn-monitor-sales-clients,
vn-monitor-sales-orders {
width: 100%
}
vn-monitor-sales-clients {
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,6 +8,7 @@
</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">
<div class="tableWrapper">
<table class="vn-table"> <table class="vn-table">
<thead> <thead>
<tr> <tr>
@ -62,6 +63,7 @@
</tr> </tr>
</tbody> </tbody>
</table> </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

@ -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

@ -6,10 +6,12 @@ SELECT
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,6 +1,3 @@
CREATE TEMPORARY TABLE tmp.travel
(INDEX (id))
ENGINE = MEMORY
SELECT SELECT
t.id, t.id,
t.ref, t.ref,