diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 237fdad0c..df9088140 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -835,14 +835,16 @@ export default { confirmButton: '.vn-confirm.shown button[response="accept"]', }, routeIndex: { - anyResult: 'vn-table a', - firstRouteCheckbox: 'a:nth-child(1) vn-td:nth-child(1) > vn-check', + anyResult: 'vn-route-index tbody > tr', + firstRouteCheckbox: 'vn-route-index tbody > tr:nth-child(1) > td:nth-child(1) > vn-check', addNewRouteButton: 'vn-route-index a[ui-sref="route.create"]', cloneButton: 'vn-route-index button > vn-icon[icon="icon-clone"]', submitClonationButton: 'tpl-buttons > button[response="accept"]', openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]', searchAgencyAutocomlete: 'vn-route-search-panel vn-autocomplete[ng-model="filter.agencyModeFk"]', advancedSearchButton: 'vn-route-search-panel button[type=submit]', + previewButton: 'vn-route-index tbody > tr:nth-child(7) > td:nth-child(11) > vn-icon-button[icon="preview"]', + }, createRouteView: { worker: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.workerFk"]', @@ -862,6 +864,8 @@ export default { firstTicketDescriptor: '.vn-popover.shown vn-ticket-descriptor', firstAlias: 'vn-route-summary vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(3) > span', firstClientDescriptor: '.vn-popover.shown vn-client-descriptor', + goToRouteSummaryButton: 'vn-route-summary > vn-card > h5 > a', + }, routeBasicData: { worker: 'vn-route-basic-data vn-autocomplete[ng-model="$ctrl.route.workerFk"]', diff --git a/e2e/paths/08-route/01_summary.spec.js b/e2e/paths/08-route/01_summary.spec.js index b6052dff6..44f66ba2d 100644 --- a/e2e/paths/08-route/01_summary.spec.js +++ b/e2e/paths/08-route/01_summary.spec.js @@ -9,7 +9,8 @@ describe('Route summary path', () => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('employee', 'route'); - await page.waitToClick('vn-route-index vn-tbody > a:nth-child(7)'); + await page.waitToClick(selectors.routeIndex.previewButton); + await page.waitToClick(selectors.routeSummary.goToRouteSummaryButton); }); afterAll(async() => { @@ -34,6 +35,8 @@ describe('Route summary path', () => { }); it('should click on the first ticket ID making the descriptor popover visible', async() => { + await page.waitForState('route.card.summary'); + await page.waitForTimeout(250); await page.waitToClick(selectors.routeSummary.firstTicketID); await page.waitForSelector(selectors.routeSummary.firstTicketDescriptor); const visible = await page.isVisible(selectors.routeSummary.firstTicketDescriptor); diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json index f9be2b6b1..704c97434 100644 --- a/modules/item/back/models/item.json +++ b/modules/item/back/models/item.json @@ -143,9 +143,6 @@ }, "packingShelve": { "type": "number" - }, - "weightByPiece": { - "type": "number" } }, "relations": { diff --git a/modules/route/back/methods/route/getTickets.js b/modules/route/back/methods/route/getTickets.js index 9a2f5289a..18e5abaf2 100644 --- a/modules/route/back/methods/route/getTickets.js +++ b/modules/route/back/methods/route/getTickets.js @@ -49,7 +49,8 @@ module.exports = Self => { a.city, am.name AS agencyModeName, u.nickname AS userNickname, - vn.ticketTotalVolume(t.id) AS volume + vn.ticketTotalVolume(t.id) AS volume, + tob.description FROM route r JOIN ticket t ON t.routeFk = r.id LEFT JOIN ticketState ts ON ts.ticketFk = t.id diff --git a/modules/route/back/models/route.json b/modules/route/back/models/route.json index 3b33cc028..12b9785db 100644 --- a/modules/route/back/models/route.json +++ b/modules/route/back/models/route.json @@ -48,6 +48,9 @@ "description": { "type": "string" }, + "isOk": { + "type": "boolean" + }, "commissionWorkCenterFk": { "type": "number" } diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index 737bbab13..831599ae8 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -68,6 +68,11 @@ label="Hour finished" ng-model="$ctrl.route.finished"> + + - +
- - - - - - - - Id - Worker - Agency - Vehicle - Date - - Description - - - - - - - - - - {{::route.id | dashIfEmpty}} - - - {{::route.workerUserName}} - - - {{::route.agencyName | dashIfEmpty}} - {{::route.vehiclePlateNumber | dashIfEmpty}} - {{::route.created | dashIfEmpty | date:'dd/MM/yyyy'}} - {{::route.m3 | dashIfEmpty}} - {{::route.description | dashIfEmpty}} - - - - - - - - - + + +
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Id + + Worker + + Agency + + Vehicle + + Date + + + + Description + + Hour started + + Hour finished +
+ + + {{::route.id | dashIfEmpty}} + + +
{{name}} - {{nickname}}
+
+
+
+ + + + + + + + + {{::route.m3 | dashIfEmpty}} + + + + + + + + + + + + + +
+
+
- +
- - - - { + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } + + markAsServed() { + const routes = []; + for (let route of this.checked) + routes.push(route.id); + + const params = {isOk: true}; + for (let routeId of routes) + this.$http.patch(`Routes/${routeId}`, params); + } } Controller.$inject = ['$element', '$scope', 'vnReport']; diff --git a/modules/route/front/index/index.spec.js b/modules/route/front/index/index.spec.js index 80e660b76..37386bc38 100644 --- a/modules/route/front/index/index.spec.js +++ b/modules/route/front/index/index.spec.js @@ -12,7 +12,7 @@ describe('Component vnRouteIndex', () => { const $element = angular.element(''); controller = $componentController('vnRouteIndex', {$element}); controller.$.model = crudModel; - controller.$.model.data = [{id: 1}, {id: 2}, {id: 3}]; + controller.$.model.data = [{id: 1, checked: true}, {id: 2}, {id: 3}]; })); describe('checked() getter', () => { @@ -148,4 +148,13 @@ describe('Component vnRouteIndex', () => { expect(controller.$.model.refresh).toHaveBeenCalledWith(); }); }); + + describe('markAsServed()', () => { + it('should perform a HTTP patch query', () => { + const data = {isOk: true}; + $httpBackend.expect('PATCH', `Routes/1`, data).respond(); + controller.markAsServed(); + $httpBackend.flush(); + }); + }); }); diff --git a/modules/route/front/index/locale/es.yml b/modules/route/front/index/locale/es.yml index 591ea80d8..e4c5c8c55 100644 --- a/modules/route/front/index/locale/es.yml +++ b/modules/route/front/index/locale/es.yml @@ -2,4 +2,10 @@ Vehicle: Vehículo Download selected routes as PDF: Descargar rutas seleccionadas como PDF Clone selected routes: Clonar rutas seleccionadas The date can't be empty: La fecha no puede estar vacía -Starting date: Fecha de inicio \ No newline at end of file +Starting date: Fecha de inicio +Hour started: Hora inicio +Hour finished: Hora fin +Go to route: Ir a la ruta +You must select a valid time: Debe seleccionar una hora válida +You must select a valid date: Debe seleccionar una fecha válida +Mark as served: Marcar como servidas \ No newline at end of file diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index e02969219..1f91276e7 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -11,7 +11,8 @@
- + +
+ + + + - - - + @@ -35,6 +45,7 @@ model="model"> + Order Street City @@ -45,6 +56,7 @@ Ticket + @@ -54,13 +66,20 @@ ng-model="ticket.checked"> + + + + + class="dense"> {{::ticket.street}} @@ -98,9 +117,18 @@ tabindex="-1"> - + + + + + +
diff --git a/modules/route/front/tickets/index.js b/modules/route/front/tickets/index.js index b14b28ed6..e78d9b8b7 100644 --- a/modules/route/front/tickets/index.js +++ b/modules/route/front/tickets/index.js @@ -20,15 +20,48 @@ class Controller extends Section { return highestPriority + 1; } + setHighestPriority(ticket) { + const highestPriority = this.getHighestPriority(); + if (highestPriority - 1 != ticket.priority) { + const params = {priority: highestPriority}; + const query = `Tickets/${ticket.id}/`; + this.$http.patch(query, params).then(res => { + ticket.priority = res.data.priority; + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } + } + setPriority(id, priority) { let params = {priority: priority}; let query = `Tickets/${id}/`; this.$http.patch(query, params).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); - this.$.model.refresh(); }); } + deletePriority() { + const lines = this.getSelectedItems(this.tickets); + + for (const line of lines) { + this.$http.patch(`Tickets/${line.id}/`, {priority: null}).then(() => { + this.vnApp.showSuccess(this.$t('Data saved!')); + this.$.model.refresh(); + }); + } + } + + setOrderedPriority(lines) { + let priority = 1; + for (const line of lines) { + this.$http.patch(`Tickets/${line.id}/`, {priority: priority}).then(() => { + this.vnApp.showSuccess(this.$t('Data saved!')); + this.$.model.refresh(); + }); + priority++; + } + } + getSelectedItems(items) { const selectedItems = []; @@ -57,8 +90,10 @@ class Controller extends Section { let lines = this.getSelectedItems(this.tickets); let url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr='; - lines.forEach(line => { - addresses = addresses + '+to:' + line.postalCode + ' ' + line.city + ' ' + line.street; + lines.forEach((line, index) => { + const previusLine = lines[index - 1] ? lines[index - 1].street : null; + if (previusLine != line.street) + addresses = addresses + '+to:' + line.postalCode + ' ' + line.city + ' ' + line.street; }); window.open(url + addresses, '_blank'); diff --git a/modules/route/front/tickets/index.spec.js b/modules/route/front/tickets/index.spec.js index 82647d903..f4a58154e 100644 --- a/modules/route/front/tickets/index.spec.js +++ b/modules/route/front/tickets/index.spec.js @@ -58,9 +58,23 @@ describe('Route', () => { }); }); + describe('setHighestPriority()', () => { + it('should set a ticket highest priority', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + controller.$.model.data = [{priority: 3}]; + const ticket = {id: 1, priority: 2}; + const res = {data: {priority: 4}}; + + $httpBackend.expectPATCH(`Tickets/${ticket.id}/`).respond(res); + controller.setHighestPriority(ticket); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + }); + }); + describe('setPriority()', () => { it('should set a ticket priority', () => { - jest.spyOn(controller.$.model, 'refresh'); jest.spyOn(controller.vnApp, 'showSuccess'); const ticketId = 1; const priority = 999; @@ -69,6 +83,35 @@ describe('Route', () => { controller.setPriority(ticketId, priority); $httpBackend.flush(); + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + }); + }); + + describe('deletePriority()', () => { + it('should delete priority of all tickets', () => { + jest.spyOn(controller.$.model, 'refresh'); + jest.spyOn(controller.vnApp, 'showSuccess'); + controller.tickets = [{id: 1, checked: true}]; + + $httpBackend.expectPATCH(`Tickets/${controller.tickets[0].id}/`).respond(); + controller.deletePriority(); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + expect(controller.$.model.refresh).toHaveBeenCalledWith(); + }); + }); + + describe('setOrderedPriority()', () => { + it('should set priority of all tickets starting by 1', () => { + jest.spyOn(controller.$.model, 'refresh'); + jest.spyOn(controller.vnApp, 'showSuccess'); + const tickets = [{id: 1, checked: true}]; + + $httpBackend.expectPATCH(`Tickets/${tickets[0].id}/`).respond(); + controller.setOrderedPriority(tickets); + $httpBackend.flush(); + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); expect(controller.$.model.refresh).toHaveBeenCalledWith(); }); diff --git a/modules/route/front/tickets/locale/es.yml b/modules/route/front/tickets/locale/es.yml index 6d63b4b6e..e7f483d2f 100644 --- a/modules/route/front/tickets/locale/es.yml +++ b/modules/route/front/tickets/locale/es.yml @@ -13,3 +13,6 @@ The route's vehicle doesn't have a delivery point: El vehículo de la ruta no ti The route doesn't have a vehicle: La ruta no tiene un vehículo Population: Población Unlink selected zone?: Desvincular zona seleccionada? +Delete priority: Borrar orden +Renumber all tickets in the order you see on the screen: Renumerar todos los tickets con el orden que ves por pantalla +Assign highest priority: Asignar máxima prioridad \ No newline at end of file