diff --git a/back/methods/collection/newCollection.js b/back/methods/collection/newCollection.js deleted file mode 100644 index 2be9f8b0e..000000000 --- a/back/methods/collection/newCollection.js +++ /dev/null @@ -1,133 +0,0 @@ -module.exports = Self => { - Self.remoteMethodCtx('newCollection', { - description: 'Make a new collection of tickets', - accessType: 'WRITE', - accepts: [{ - arg: 'collectionFk', - type: 'Number', - required: false, - description: 'The collection id' - }, { - arg: 'sectorFk', - type: 'Number', - required: true, - description: 'The sector of worker' - }, { - arg: 'vWagons', - type: 'Number', - required: true, - description: 'The number of wagons' - }], - returns: { - type: 'Object', - root: true - }, - http: { - path: `/newCollection`, - verb: 'POST' - } - }); - - Self.newCollection = async(ctx, collectionFk, sectorFk, vWagons) => { - let query = ''; - const userId = ctx.req.accessToken.userId; - - if (!collectionFk) { - query = `CALL vn.collectionTrain_newBeta(?,?,?)`; - const [result] = await Self.rawSql(query, [sectorFk, vWagons, userId], {userId}); - if (result.length == 0) - throw new Error(`No collections for today`); - - collectionFk = result[0].vCollectionFk; - } - - query = `CALL vn.collectionTicket_get(?)`; - const [tickets] = await Self.rawSql(query, [collectionFk], {userId}); - - query = `CALL vn.collectionSale_get(?)`; - const [sales] = await Self.rawSql(query, [collectionFk], {userId}); - - query = `CALL vn.collectionPlacement_get(?)`; - const [placements] = await Self.rawSql(query, [collectionFk], {userId}); - - query = `CALL vn.collectionSticker_print(?,?)`; - await Self.rawSql(query, [collectionFk, sectorFk], {userId}); - - return makeCollection(tickets, sales, placements, collectionFk); - }; - - /** - * Returns a collection json - * @param {*} tickets - Request tickets - * @param {*} sales - Request sales - * @param {*} placements - Request placements - * @param {*} collectionFk - Request placements - * @return {Object} Collection JSON - */ - async function makeCollection(tickets, sales, placements, collectionFk) { - let collection = []; - - for (let i = 0; i < tickets.length; i++) { - let ticket = {}; - ticket['ticketFk'] = tickets[i]['ticketFk']; - ticket['level'] = tickets[i]['level']; - ticket['agencyName'] = tickets[i]['agencyName']; - ticket['warehouseFk'] = tickets[i]['warehouseFk']; - ticket['salesPersonFk'] = tickets[i]['salesPersonFk']; - - let ticketSales = []; - - for (let x = 0; x < sales.length; x++) { - if (sales[x]['ticketFk'] == ticket['ticketFk']) { - let sale = {}; - sale['collectionFk'] = collectionFk; - sale['ticketFk'] = sales[x]['ticketFk']; - sale['saleFk'] = sales[x]['saleFk']; - sale['itemFk'] = sales[x]['itemFk']; - sale['quantity'] = sales[x]['quantity']; - if (sales[x]['quantityPicked'] != null) - sale['quantityPicked'] = sales[x]['quantityPicked']; - else - sale['quantityPicked'] = 0; - sale['longName'] = sales[x]['longName']; - sale['size'] = sales[x]['size']; - sale['color'] = sales[x]['color']; - sale['discount'] = sales[x]['discount']; - sale['price'] = sales[x]['price']; - sale['stems'] = sales[x]['stems']; - sale['category'] = sales[x]['category']; - sale['origin'] = sales[x]['origin']; - sale['clientFk'] = sales[x]['clientFk']; - sale['productor'] = sales[x]['productor']; - sale['reserved'] = sales[x]['reserved']; - sale['isPreviousPrepared'] = sales[x]['isPreviousPrepared']; - sale['isPrepared'] = sales[x]['isPrepared']; - sale['isControlled'] = sales[x]['isControlled']; - - let salePlacements = []; - - for (let z = 0; z < placements.length; z++) { - if (placements[z]['saleFk'] == sale['saleFk']) { - let placement = {}; - placement['saleFk'] = placements[z]['saleFk']; - placement['itemFk'] = placements[z]['itemFk']; - placement['placement'] = placements[z]['placement']; - placement['shelving'] = placements[z]['shelving']; - placement['created'] = placements[z]['created']; - placement['visible'] = placements[z]['visible']; - placement['order'] = placements[z]['order']; - placement['grouping'] = placements[z]['grouping']; - salePlacements.push(placement); - } - } - sale['placements'] = salePlacements; - ticketSales.push(sale); - } - } - ticket['sales'] = ticketSales; - collection.push(ticket); - } - - return collection; - } -}; diff --git a/back/methods/collection/spec/newCollection.spec.js b/back/methods/collection/spec/newCollection.spec.js deleted file mode 100644 index e729594d1..000000000 --- a/back/methods/collection/spec/newCollection.spec.js +++ /dev/null @@ -1,12 +0,0 @@ -const {models} = require('vn-loopback/server/server'); - -describe('newCollection()', () => { - it('should return a new collection', async() => { - pending('#3400 analizar que hacer con rutas de back collection'); - let ctx = {req: {accessToken: {userId: 1106}}}; - let response = await models.Collection.newCollection(ctx, 1, 1, 1); - - expect(response.length).toBeGreaterThan(0); - expect(response[0].ticketFk).toEqual(2); - }); -}); diff --git a/back/models/collection.js b/back/models/collection.js index bfa906af6..1c10d49fa 100644 --- a/back/models/collection.js +++ b/back/models/collection.js @@ -1,6 +1,5 @@ module.exports = Self => { require('../methods/collection/getCollection')(Self); - require('../methods/collection/newCollection')(Self); require('../methods/collection/getSectors')(Self); require('../methods/collection/setSaleQuantity')(Self); require('../methods/collection/previousLabel')(Self); diff --git a/db/changes/235001/00-getRoutesByWorker.sql b/db/changes/235001/00-getRoutesByWorker.sql new file mode 100644 index 000000000..00d6e658a --- /dev/null +++ b/db/changes/235001/00-getRoutesByWorker.sql @@ -0,0 +1,26 @@ +DELETE FROM `salix`.`ACL` + WHERE + model = 'Route' + AND property = '*' + AND accessType = 'READ'; + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('Route', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'getRoutesByWorker', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'canViewAllRoute', 'READ', 'ALLOW', 'ROLE', 'deliveryBoss'), + ('Route', 'cmr', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'downloadCmrsZip', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'downloadZip', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'filter', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'getByWorker', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'getDeliveryPoint', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'getExternalCmrs', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'getSuggestedTickets', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'getTickets', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'guessPriority', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'insertTicket', 'WRITE', 'ALLOW', 'ROLE', 'employee'), + ('Route', 'getDeliveryPoint', 'READ', 'ALLOW', 'ROLE', 'deliveryBoss'), + ('Route', 'summary', 'READ', 'ALLOW', 'ROLE', 'employee'); diff --git a/modules/route/back/methods/route/filter.js b/modules/route/back/methods/route/filter.js index fc35e979f..afefa77d1 100644 --- a/modules/route/back/methods/route/filter.js +++ b/modules/route/back/methods/route/filter.js @@ -105,7 +105,7 @@ module.exports = Self => { } }); - filter = mergeFilters(ctx.args.filter, {where}); + filter = mergeFilters(filter, {where}); let stmts = []; let stmt; @@ -129,9 +129,11 @@ module.exports = Self => { r.description, am.name agencyName, u.name AS workerUserName, - v.numberPlate AS vehiclePlateNumber + v.numberPlate AS vehiclePlateNumber, + Date_format(r.time, '%H:%i') hour FROM route r LEFT JOIN agencyMode am ON am.id = r.agencyModeFk + LEFT JOIN agency a ON a.id = am.agencyFk LEFT JOIN vehicle v ON v.id = r.vehicleFk LEFT JOIN worker w ON w.id = r.workerFk LEFT JOIN account.user u ON u.id = w.id` diff --git a/modules/route/back/methods/route/getByWorker.js b/modules/route/back/methods/route/getByWorker.js new file mode 100644 index 000000000..7e70cb1f1 --- /dev/null +++ b/modules/route/back/methods/route/getByWorker.js @@ -0,0 +1,65 @@ +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethodCtx('getByWorker', { + description: 'Return the routes by worker', + accessType: 'READ', + returns: { + type: ['object'], + root: true + }, + http: { + path: `/getByWorker`, + verb: 'GET' + } + }); + + Self.getByWorker = async ctx => { + const models = Self.app.models; + const userId = ctx.req.accessToken.userId; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const canViewAll = await models.ACL.checkAccessAcl(ctx, 'Route', 'canViewAllRoute', 'READ'); + let filterGrant = {}; + + if (canViewAll) { + const userConfig = await models.UserConfig.getUserConfig(ctx, myOptions); + filterGrant = { + where: {'a.warehouseFk': userConfig.warehouseFk} + }; + } else { + filterGrant = { + where: {'r.workerFk': userId} + }; + } + + const currentDate = Date.vnNew(); + currentDate.setHours(0, 0, 0, 0); + const nextDay = Date.vnNew(); + nextDay.setDate(currentDate.getDate() + 1); + + const filter = { + where: { + and: [ + { + or: [ + {'r.created': currentDate}, + {'r.created': nextDay} + ] + } + ] + }, + order: [ + 'r.created ASC', + 'r.time ASC', + 'am.name ASC' + ] + }; + + const result = await Self.filter(ctx, mergeFilters(filter, filterGrant)); + return result; + }; +}; diff --git a/modules/route/back/methods/route/getDeliveryPoint.js b/modules/route/back/methods/route/getDeliveryPoint.js index e5a50805a..3359f666e 100644 --- a/modules/route/back/methods/route/getDeliveryPoint.js +++ b/modules/route/back/methods/route/getDeliveryPoint.js @@ -1,7 +1,7 @@ module.exports = Self => { Self.remoteMethod('getDeliveryPoint', { description: 'get the deliveryPoint address', - accessType: 'WRITE', + accessType: 'READ', accepts: { arg: 'vehicleId', type: 'number', diff --git a/modules/route/back/methods/route/guessPriority.js b/modules/route/back/methods/route/guessPriority.js index c6b2a9b74..749075388 100644 --- a/modules/route/back/methods/route/guessPriority.js +++ b/modules/route/back/methods/route/guessPriority.js @@ -1,7 +1,7 @@ module.exports = Self => { Self.remoteMethodCtx('guessPriority', { description: 'Changes automatically the priority of the tickets in a route', - accessType: 'READ', + accessType: 'WRITE', accepts: [{ arg: 'id', type: 'number', @@ -15,7 +15,7 @@ module.exports = Self => { }, http: { path: `/:id/guessPriority`, - verb: 'GET' + verb: 'PATCH' } }); diff --git a/modules/route/back/methods/route/insertTicket.js b/modules/route/back/methods/route/insertTicket.js index f78e1cb83..4ac8bad1a 100644 --- a/modules/route/back/methods/route/insertTicket.js +++ b/modules/route/back/methods/route/insertTicket.js @@ -3,7 +3,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethod('insertTicket', { description: 'Check if the ticket can be insert into the route and insert it', - accessType: 'READ', + accessType: 'WRITE', accepts: [{ arg: 'routeId', type: 'number', diff --git a/modules/route/back/methods/route/specs/getByWorker.spec.js b/modules/route/back/methods/route/specs/getByWorker.spec.js new file mode 100644 index 000000000..f3103509a --- /dev/null +++ b/modules/route/back/methods/route/specs/getByWorker.spec.js @@ -0,0 +1,36 @@ +const app = require('vn-loopback/server/server'); +const LoopBackContext = require('loopback-context'); + +describe('route getByWorker()', () => { + const userId = 56; + const activeCtx = { + accessToken: {userId: userId}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + const ctx = {req: activeCtx}; + + beforeAll(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + it('should return routes assigned to the worker', async() => { + const result = await app.models.Route.getByWorker(ctx); + + expect(result.every(route => route.workerFk === userId)).toBe(true); + }); + + it('should return all routes if user has canViewAllRoute permission', async() => { + // Simular que el usuario tiene permiso para ver todas las rutas + spyOn(app.models.ACL, 'checkAccessAcl').and.returnValue(Promise.resolve(true)); + + const result = await app.models.Route.getByWorker(ctx); + + expect(result.some(route => route.workerFk != userId)).toBe(true); + }); +}); diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index 65fa43ab5..cbdd75679 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -17,6 +17,7 @@ module.exports = Self => { require('../methods/route/cmr')(Self); require('../methods/route/getExternalCmrs')(Self); require('../methods/route/downloadCmrsZip')(Self); + require('../methods/route/getByWorker')(Self); Self.validate('kmStart', validateDistance, { message: 'Distance must be lesser than 1000' @@ -31,5 +32,5 @@ module.exports = Self => { const routeMaxKm = 1000; if (routeTotalKm > routeMaxKm || this.kmStart > this.kmEnd) err(); - }; + } }; diff --git a/modules/route/front/tickets/index.js b/modules/route/front/tickets/index.js index 8789708ac..a1b97005e 100644 --- a/modules/route/front/tickets/index.js +++ b/modules/route/front/tickets/index.js @@ -120,7 +120,7 @@ class Controller extends Section { guessPriority() { let query = `Routes/${this.$params.id}/guessPriority/`; - this.$http.get(query).then(() => { + this.$http.patch(query).then(() => { this.vnApp.showSuccess(this.$t('Order changed')); this.$.model.refresh(); }); diff --git a/modules/route/front/tickets/index.spec.js b/modules/route/front/tickets/index.spec.js index 2c73048bd..fef4b8331 100644 --- a/modules/route/front/tickets/index.spec.js +++ b/modules/route/front/tickets/index.spec.js @@ -209,22 +209,6 @@ describe('Route', () => { }); }); - describe('guessPriority()', () => { - it('should perform a GET query then call both refresh and showSuccess methods', () => { - jest.spyOn(controller.$.model, 'refresh'); - jest.spyOn(controller.vnApp, 'showSuccess'); - controller.$params = {id: 99}; - - const url = `Routes/${controller.$params.id}/guessPriority/`; - $httpBackend.expectGET(url).respond('ok'); - controller.guessPriority(); - $httpBackend.flush(); - - expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Order changed'); - expect(controller.$.model.refresh).toHaveBeenCalledWith(); - }); - }); - describe('onDrop()', () => { it('should call the insert method when dragging a ticket number', () => { jest.spyOn(controller, 'insert');