diff --git a/back/methods/locationiq-config/optimize.js b/back/methods/locationiq-config/optimize.js new file mode 100644 index 000000000..cd1f6e7ff --- /dev/null +++ b/back/methods/locationiq-config/optimize.js @@ -0,0 +1,77 @@ +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 locationiqConfig = await models.LocationiqConfig.findOne(); + if (!locationiqConfig) throw new UserError(`LocationIQ 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(`${locationiqConfig.url}${concatCoords}?key=${locationiqConfig.key}`); + const tolerance = locationiqConfig.tolerance; + + for (waypoint of response.data.waypoints) { + const longitude = waypoint.location[0]; + const latitude = waypoint.location[1]; + + const matchedAddress = coords.find(coord => + Math.abs(coord.latitude - latitude) <= tolerance && + Math.abs(coord.longitude - longitude) <= tolerance + ); + if (matchedAddress) matchedAddress.position = waypoint.waypoint_index; + } + 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 => `${item.latitude},${item.longitude}`) + .join('/'); + console.log(`https://www.google.es/maps/dir/${coordsString}`); + // --------- + 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'); + default: + throw err; + } + } + }; +}; diff --git a/back/model-config.json b/back/model-config.json index c1682f29a..f48e5f2eb 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -88,6 +88,9 @@ "Language": { "dataSource": "vn" }, + "LocationiqConfig": { + "dataSource": "vn" + }, "Machine": { "dataSource": "vn" }, diff --git a/back/models/locationiq-config.js b/back/models/locationiq-config.js new file mode 100644 index 000000000..e0fe736bb --- /dev/null +++ b/back/models/locationiq-config.js @@ -0,0 +1,4 @@ +module.exports = Self => { + require('../methods/locationiq-config/optimize')(Self); +}; + diff --git a/back/models/locationiq-config.json b/back/models/locationiq-config.json new file mode 100644 index 000000000..624341615 --- /dev/null +++ b/back/models/locationiq-config.json @@ -0,0 +1,28 @@ +{ + "name": "LocationiqConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "locationiqConfig" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "required": true + }, + "url": { + "type": "string", + "required": true + }, + "key": { + "type": "string", + "required": true + }, + "tolerance": { + "type": "number", + "required": false + } + } +} diff --git a/db/versions/11379-yellowCordyline/00-firstScript.sql b/db/versions/11379-yellowCordyline/00-firstScript.sql new file mode 100644 index 000000000..001ef6049 --- /dev/null +++ b/db/versions/11379-yellowCordyline/00-firstScript.sql @@ -0,0 +1,8 @@ +CREATE TABLE `vn`.`locationiqConfig` ( + `id` int(10) unsigned NOT NULL, + `url` varchar(100) NOT NULL, + `key` varchar(100) NOT NULL, + `tolerance` decimal(6,6) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + CONSTRAINT `locationiqConfig_check` CHECK (`id` = 1) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 1eb953d89..fb495dfb1 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -388,8 +388,9 @@ "You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada", "ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}", "The web user's email already exists": "El correo del usuario web ya existe", - "Sales already moved": "Ya han sido transferidas", - "The raid information is not correct": "La información de la redada no es correcta", - "There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero" -} - + "Sales already moved": "Ya han sido transferidas", + "The raid information is not correct": "La información de la redada no es correcta", + "There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero", + "No trips found because input coordinates are not connected": "No se encontraron rutas porque las coordenadas de entrada no están conectadas", + "This request is not supported": "Esta solicitud no es compatible" +} \ No newline at end of file