Merge pull request '6028_route_getRouteByWorker' (!1857) from 6028_route_getRouteByWorker into dev
gitea/salix/pipeline/head This commit looks good Details

Reviewed-on: #1857
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
Javi Gallego 2023-11-23 14:01:53 +00:00
commit 4a62588464
13 changed files with 138 additions and 170 deletions

View File

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

View File

@ -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);
});
});

View File

@ -1,6 +1,5 @@
module.exports = Self => { module.exports = Self => {
require('../methods/collection/getCollection')(Self); require('../methods/collection/getCollection')(Self);
require('../methods/collection/newCollection')(Self);
require('../methods/collection/getSectors')(Self); require('../methods/collection/getSectors')(Self);
require('../methods/collection/setSaleQuantity')(Self); require('../methods/collection/setSaleQuantity')(Self);
require('../methods/collection/previousLabel')(Self); require('../methods/collection/previousLabel')(Self);

View File

@ -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');

View File

@ -105,7 +105,7 @@ module.exports = Self => {
} }
}); });
filter = mergeFilters(ctx.args.filter, {where}); filter = mergeFilters(filter, {where});
let stmts = []; let stmts = [];
let stmt; let stmt;
@ -129,9 +129,11 @@ module.exports = Self => {
r.description, r.description,
am.name agencyName, am.name agencyName,
u.name AS workerUserName, u.name AS workerUserName,
v.numberPlate AS vehiclePlateNumber v.numberPlate AS vehiclePlateNumber,
Date_format(r.time, '%H:%i') hour
FROM route r FROM route r
LEFT JOIN agencyMode am ON am.id = r.agencyModeFk 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 vehicle v ON v.id = r.vehicleFk
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.id` LEFT JOIN account.user u ON u.id = w.id`

View File

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

View File

@ -1,7 +1,7 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('getDeliveryPoint', { Self.remoteMethod('getDeliveryPoint', {
description: 'get the deliveryPoint address', description: 'get the deliveryPoint address',
accessType: 'WRITE', accessType: 'READ',
accepts: { accepts: {
arg: 'vehicleId', arg: 'vehicleId',
type: 'number', type: 'number',

View File

@ -1,7 +1,7 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('guessPriority', { Self.remoteMethodCtx('guessPriority', {
description: 'Changes automatically the priority of the tickets in a route', description: 'Changes automatically the priority of the tickets in a route',
accessType: 'READ', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'id', arg: 'id',
type: 'number', type: 'number',
@ -15,7 +15,7 @@ module.exports = Self => {
}, },
http: { http: {
path: `/:id/guessPriority`, path: `/:id/guessPriority`,
verb: 'GET' verb: 'PATCH'
} }
}); });

View File

@ -3,7 +3,7 @@ const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('insertTicket', { Self.remoteMethod('insertTicket', {
description: 'Check if the ticket can be insert into the route and insert it', description: 'Check if the ticket can be insert into the route and insert it',
accessType: 'READ', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'routeId', arg: 'routeId',
type: 'number', type: 'number',

View File

@ -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);
});
});

View File

@ -17,6 +17,7 @@ module.exports = Self => {
require('../methods/route/cmr')(Self); require('../methods/route/cmr')(Self);
require('../methods/route/getExternalCmrs')(Self); require('../methods/route/getExternalCmrs')(Self);
require('../methods/route/downloadCmrsZip')(Self); require('../methods/route/downloadCmrsZip')(Self);
require('../methods/route/getByWorker')(Self);
Self.validate('kmStart', validateDistance, { Self.validate('kmStart', validateDistance, {
message: 'Distance must be lesser than 1000' message: 'Distance must be lesser than 1000'
@ -31,5 +32,5 @@ module.exports = Self => {
const routeMaxKm = 1000; const routeMaxKm = 1000;
if (routeTotalKm > routeMaxKm || this.kmStart > this.kmEnd) if (routeTotalKm > routeMaxKm || this.kmStart > this.kmEnd)
err(); err();
}; }
}; };

View File

@ -120,7 +120,7 @@ class Controller extends Section {
guessPriority() { guessPriority() {
let query = `Routes/${this.$params.id}/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.vnApp.showSuccess(this.$t('Order changed'));
this.$.model.refresh(); this.$.model.refresh();
}); });

View File

@ -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()', () => { describe('onDrop()', () => {
it('should call the insert method when dragging a ticket number', () => { it('should call the insert method when dragging a ticket number', () => {
jest.spyOn(controller, 'insert'); jest.spyOn(controller, 'insert');