const UserError = require('vn-loopback/util/user-error'); const axios = require('axios'); module.exports = Self => { Self.remoteMethod('optimize', { description: 'Return optimized coords', accessType: 'READ', accepts: [{ arg: 'addressIds', type: 'array', required: true }], returns: { type: 'string', root: true }, http: { path: `/optimize`, verb: 'GET' } }); Self.optimize = async addressIds => { const models = Self.app.models; try { const osrmConfig = await models.OsrmConfig.findOne(); if (!osrmConfig) throw new UserError(`OSRM service is not configured`); let coords = []; for (const addressId of addressIds) { const address = await models.Address.findById(addressId); coords.push({ addressId, latitude: address.latitude.toFixed(6), longitude: address.longitude.toFixed(6) }); } const concatCoords = coords .map(coord => `${coord.longitude},${coord.latitude}`) .join(';'); const response = await axios.post(` ${osrmConfig.url}/trip/v1/driving/${concatCoords} `); const tolerance = osrmConfig.tolerance; for (waypoint of response.data.waypoints) { const longitude = waypoint.location[0]; const latitude = waypoint.location[1]; const matchedAddress = coords.find(coord => !coord.position && Math.abs(coord.latitude - latitude) <= tolerance && Math.abs(coord.longitude - longitude) <= tolerance ); if (matchedAddress) matchedAddress.position = waypoint.waypoint_index; else console.log(`Las coordenadas no se han podido asociar: ${latitude} | ${longitude}`); } coords.sort((a, b) => { const posA = a.position !== undefined ? a.position : Infinity; const posB = b.position !== undefined ? b.position : Infinity; return posA - posB; }); // Temporal para abrir en maps const coordsString = coords .map(item => `point=${item.latitude},${item.longitude}`) .join('&'); console.log(`https://graphhopper.com/maps/?${coordsString}&profile=small_truck`); // --------- return coords; } catch (err) { switch (err.response?.data?.code) { case 'NoTrips': throw new UserError('No trips found because input coordinates are not connected'); case 'NotImplemented': throw new UserError('This request is not supported'); case 'InvalidOptions': throw new UserError('Invalid options or too many coordinates'); default: throw err; } } }; };