Merge pull request 'Download route PDF on route index' (#357) from 2358-route_download_pdf into dev
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #357 Reviewed-by: Carlos Jimenez <carlosjr@verdnatura.es>
This commit is contained in:
commit
17cd808015
|
@ -371,7 +371,7 @@ export default {
|
||||||
ticketsIndex: {
|
ticketsIndex: {
|
||||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||||
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"]',
|
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"]',
|
||||||
newTicketButton: 'vn-ticket-index a',
|
newTicketButton: 'vn-ticket-index a[ui-sref="ticket.create"]',
|
||||||
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||||
secondTicketCheckbox: 'vn-ticket-index vn-tbody > a:nth-child(2) > vn-td:nth-child(1) > vn-check',
|
secondTicketCheckbox: 'vn-ticket-index vn-tbody > a:nth-child(2) > vn-td:nth-child(1) > vn-check',
|
||||||
thirdTicketCheckbox: 'vn-ticket-index vn-tbody > a:nth-child(3) > vn-td:nth-child(1) > vn-check',
|
thirdTicketCheckbox: 'vn-ticket-index vn-tbody > a:nth-child(3) > vn-td:nth-child(1) > vn-check',
|
||||||
|
@ -689,7 +689,7 @@ export default {
|
||||||
confirmButton: '.vn-confirm.shown button[response="accept"]',
|
confirmButton: '.vn-confirm.shown button[response="accept"]',
|
||||||
},
|
},
|
||||||
routeIndex: {
|
routeIndex: {
|
||||||
addNewRouteButton: 'vn-route-index > a[ui-sref="route.create"]'
|
addNewRouteButton: 'vn-route-index a[ui-sref="route.create"]'
|
||||||
},
|
},
|
||||||
createRouteView: {
|
createRouteView: {
|
||||||
worker: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
|
worker: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
<vn-table model="model">
|
<vn-table model="model">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
|
<vn-th shrink>
|
||||||
|
<vn-multi-check
|
||||||
|
model="model">
|
||||||
|
</vn-multi-check>
|
||||||
|
</vn-th>
|
||||||
<vn-th field="id" number>Id</vn-th>
|
<vn-th field="id" number>Id</vn-th>
|
||||||
<vn-th th-id="worker">Worker</vn-th>
|
<vn-th th-id="worker">Worker</vn-th>
|
||||||
<vn-th th-id="agency">Agency</vn-th>
|
<vn-th th-id="agency">Agency</vn-th>
|
||||||
|
@ -22,6 +27,12 @@
|
||||||
<a ng-repeat="route in model.data"
|
<a ng-repeat="route in model.data"
|
||||||
class="clickable vn-tr search-result"
|
class="clickable vn-tr search-result"
|
||||||
ui-sref="route.card.summary({id: {{::route.id}}})">
|
ui-sref="route.card.summary({id: {{::route.id}}})">
|
||||||
|
<vn-td shrink>
|
||||||
|
<vn-check
|
||||||
|
ng-model="route.checked"
|
||||||
|
vn-click-stop>
|
||||||
|
</vn-check>
|
||||||
|
</vn-td>
|
||||||
<vn-td number>{{::route.id | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::route.id | dashIfEmpty}}</vn-td>
|
||||||
<vn-td expand>
|
<vn-td expand>
|
||||||
<span
|
<span
|
||||||
|
@ -55,9 +66,26 @@
|
||||||
<vn-worker-descriptor-popover
|
<vn-worker-descriptor-popover
|
||||||
vn-id="workerDescriptor">
|
vn-id="workerDescriptor">
|
||||||
</vn-worker-descriptor-popover>
|
</vn-worker-descriptor-popover>
|
||||||
<a ui-sref="route.create"
|
|
||||||
vn-tooltip="New route"
|
|
||||||
vn-bind="+"
|
</vn-data-viewer>
|
||||||
fixed-bottom-right>
|
<div fixed-bottom-right>
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
<vn-vertical style="align-items: center;">
|
||||||
</a>
|
<vn-button class="round sm vn-mb-sm"
|
||||||
|
icon="cloud_download"
|
||||||
|
ng-show="$ctrl.totalChecked > 0"
|
||||||
|
ng-click="$ctrl.showRouteReport()"
|
||||||
|
vn-tooltip="Download selected routes as PDF"
|
||||||
|
tooltip-position="left">
|
||||||
|
</vn-button>
|
||||||
|
|
||||||
|
<a ui-sref="route.create">
|
||||||
|
<vn-button class="round md vn-mb-sm"
|
||||||
|
icon="add"
|
||||||
|
vn-bind="+"
|
||||||
|
vn-tooltip="New route"
|
||||||
|
tooltip-position="left">
|
||||||
|
</vn-button>
|
||||||
|
</a>
|
||||||
|
</vn-vertical>
|
||||||
|
</div>
|
|
@ -2,12 +2,46 @@ import ngModule from '../module';
|
||||||
import Section from 'salix/components/section';
|
import Section from 'salix/components/section';
|
||||||
|
|
||||||
export default class Controller extends Section {
|
export default class Controller extends Section {
|
||||||
|
constructor($element, $, vnReport) {
|
||||||
|
super($element, $);
|
||||||
|
this.vnReport = vnReport;
|
||||||
|
}
|
||||||
|
|
||||||
preview(route) {
|
preview(route) {
|
||||||
this.routeSelected = route;
|
this.routeSelected = route;
|
||||||
this.$.summary.show();
|
this.$.summary.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get checked() {
|
||||||
|
const rows = this.$.model.data || [];
|
||||||
|
const checkedRows = [];
|
||||||
|
for (let row of rows) {
|
||||||
|
if (row.checked)
|
||||||
|
checkedRows.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkedRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
get totalChecked() {
|
||||||
|
return this.checked.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
showRouteReport() {
|
||||||
|
const routes = [];
|
||||||
|
for (let route of this.checked)
|
||||||
|
routes.push(route.id);
|
||||||
|
const routesId = routes.join(',');
|
||||||
|
|
||||||
|
this.vnReport.show('driver-route', {
|
||||||
|
authorization: this.vnToken.token,
|
||||||
|
routeId: routesId
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$element', '$scope', 'vnReport'];
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteIndex', {
|
ngModule.vnComponent('vnRouteIndex', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller
|
controller: Controller
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import './index.js';
|
||||||
|
import crudModel from 'core/mocks/crud-model';
|
||||||
|
|
||||||
|
describe('Component vnRouteIndex', () => {
|
||||||
|
let controller;
|
||||||
|
|
||||||
|
beforeEach(ngModule('route'));
|
||||||
|
|
||||||
|
beforeEach(inject($componentController => {
|
||||||
|
const $element = angular.element('<vn-route-index></vn-route-index>');
|
||||||
|
controller = $componentController('vnRouteIndex', {$element});
|
||||||
|
controller.$.model = crudModel;
|
||||||
|
controller.$.model.data = [{id: 1}, {id: 2}, {id: 3}];
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('checked() getter', () => {
|
||||||
|
it('should return the checked lines', () => {
|
||||||
|
const data = controller.$.model.data;
|
||||||
|
data[0].checked = true;
|
||||||
|
data[2].checked = true;
|
||||||
|
|
||||||
|
const checkedRows = controller.checked;
|
||||||
|
|
||||||
|
const firstCheckedRow = checkedRows[0];
|
||||||
|
const secondCheckedRow = checkedRows[1];
|
||||||
|
|
||||||
|
expect(firstCheckedRow.id).toEqual(1);
|
||||||
|
expect(secondCheckedRow.id).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('totalCheked() getter', () => {
|
||||||
|
it('should return the total checked lines', () => {
|
||||||
|
const data = controller.$.model.data;
|
||||||
|
data[0].checked = true;
|
||||||
|
|
||||||
|
const checkedRows = controller.totalChecked;
|
||||||
|
|
||||||
|
expect(checkedRows).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showRouteReport()', () => {
|
||||||
|
it('should call to the vnReport show method', () => {
|
||||||
|
controller.vnReport.show = jest.fn();
|
||||||
|
|
||||||
|
const data = controller.$.model.data;
|
||||||
|
data[0].checked = true;
|
||||||
|
data[2].checked = true;
|
||||||
|
const expectedParams = {
|
||||||
|
authorization: null,
|
||||||
|
routeId: '1,3'
|
||||||
|
};
|
||||||
|
|
||||||
|
controller.showRouteReport();
|
||||||
|
|
||||||
|
expect(controller.vnReport.show).toHaveBeenCalledWith('driver-route', expectedParams);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1 +1,2 @@
|
||||||
Vehicle: Vehículo
|
Vehicle: Vehículo
|
||||||
|
Download selected routes as PDF: Descargar rutas seleccionadas como PDF
|
|
@ -24,8 +24,9 @@ p.privacy {
|
||||||
text-align: center
|
text-align: center
|
||||||
}
|
}
|
||||||
|
|
||||||
.page .pageCount {
|
.pageCount {
|
||||||
text-align: right
|
text-align: right;
|
||||||
|
float: right
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer .page > div {
|
.footer .page > div {
|
||||||
|
|
|
@ -33,6 +33,7 @@ class Report extends Component {
|
||||||
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
||||||
});
|
});
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
await page.emulateMedia('screen');
|
||||||
await page.setContent(template);
|
await page.setContent(template);
|
||||||
|
|
||||||
const element = await page.$('#pageFooter');
|
const element = await page.$('#pageFooter');
|
||||||
|
|
|
@ -47,3 +47,8 @@ section.text-area {
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
background-color: #e5e5e5;
|
background-color: #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.route-block {
|
||||||
|
margin-bottom: 100px;
|
||||||
|
page-break-after: always;
|
||||||
|
}
|
|
@ -8,9 +8,9 @@
|
||||||
<!-- Header block -->
|
<!-- Header block -->
|
||||||
<report-header v-bind="$props"></report-header>
|
<report-header v-bind="$props"></report-header>
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row">
|
<div class="grid-row route-block" v-for="route in routes">
|
||||||
<div class="grid-block">
|
<div class="grid-block">
|
||||||
<h1 class="title uppercase">{{route.id}}</h1>
|
<h1 class="title uppercase">{{$t('route')}} {{route.id}}</h1>
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="header">{{$t('information')}}</div>
|
<div class="header">{{$t('information')}}</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
|
@ -80,7 +80,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="no-page-break" v-for="ticket in tickets">
|
<!-- Route ticket list -->
|
||||||
|
<div class="no-page-break" v-for="ticket in route.tickets">
|
||||||
<div>
|
<div>
|
||||||
<table class="column-oriented repeatable">
|
<table class="column-oriented repeatable">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -151,7 +152,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Footer block -->
|
<!-- Footer block -->
|
||||||
<report-footer id="pageFooter"
|
<report-footer id="pageFooter"
|
||||||
v-bind:left-text="$t('routeId', [route.id])"
|
v-bind:left-text="$t('routeId', [routeId])"
|
||||||
v-bind="$props">
|
v-bind="$props">
|
||||||
</report-footer>
|
</report-footer>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -6,15 +6,26 @@ const reportFooter = new Component('report-footer');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'driver-route',
|
name: 'driver-route',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.route = await this.fetchRoute(this.routeId);
|
const routesId = this.routeId.split(',');
|
||||||
this.tickets = await this.fetchTickets(this.routeId);
|
const routes = await this.fetchRoutes(routesId);
|
||||||
|
const tickets = await this.fetchTickets(routesId);
|
||||||
|
|
||||||
if (!this.route)
|
for (let route of routes) {
|
||||||
|
const routeTickets = tickets.filter(ticket => {
|
||||||
|
return ticket.routeFk == route.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
route.tickets = routeTickets;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.routes = routes;
|
||||||
|
|
||||||
|
if (!this.routes)
|
||||||
throw new Error('Something went wrong');
|
throw new Error('Something went wrong');
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchRoute(id) {
|
fetchRoutes(routesId) {
|
||||||
return db.findOne(
|
return db.rawSql(
|
||||||
`SELECT
|
`SELECT
|
||||||
r.id,
|
r.id,
|
||||||
r.m3,
|
r.m3,
|
||||||
|
@ -30,9 +41,9 @@ module.exports = {
|
||||||
LEFT JOIN worker w ON w.id = r.workerFk
|
LEFT JOIN worker w ON w.id = r.workerFk
|
||||||
LEFT JOIN account.user u ON u.id = w.userFk
|
LEFT JOIN account.user u ON u.id = w.userFk
|
||||||
LEFT JOIN agencyMode am ON am.id = r.agencyModeFk
|
LEFT JOIN agencyMode am ON am.id = r.agencyModeFk
|
||||||
WHERE r.id = :routeId`, {routeId: id});
|
WHERE r.id IN(:routesId)`, {routesId});
|
||||||
},
|
},
|
||||||
fetchTickets(routeId) {
|
fetchTickets(routesId) {
|
||||||
return db.rawSql(
|
return db.rawSql(
|
||||||
`SELECT
|
`SELECT
|
||||||
t.nickname addressName,
|
t.nickname addressName,
|
||||||
|
@ -41,6 +52,7 @@ module.exports = {
|
||||||
t.id,
|
t.id,
|
||||||
t.clientFk,
|
t.clientFk,
|
||||||
t.companyFk,
|
t.companyFk,
|
||||||
|
t.routeFk,
|
||||||
if(a.phone, a.phone, c.phone) AS phone,
|
if(a.phone, a.phone, c.phone) AS phone,
|
||||||
if(a.mobile, a.mobile, c.mobile) AS mobile,
|
if(a.mobile, a.mobile, c.mobile) AS mobile,
|
||||||
wh.name warehouseName,
|
wh.name warehouseName,
|
||||||
|
@ -65,8 +77,8 @@ module.exports = {
|
||||||
LEFT JOIN warehouse wh ON wh.id = t.warehouseFk
|
LEFT JOIN warehouse wh ON wh.id = t.warehouseFk
|
||||||
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||||
LEFT JOIN stowaway s ON s.id = t.id
|
LEFT JOIN stowaway s ON s.id = t.id
|
||||||
WHERE r.id = ?
|
WHERE r.id IN(:routesId)
|
||||||
ORDER BY t.priority, t.id`, [routeId]);
|
ORDER BY t.priority, t.id`, {routesId});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
Loading…
Reference in New Issue