From 51320dd973832da998cead9228404f385c2ed69c Mon Sep 17 00:00:00 2001 From: Pau Date: Thu, 17 Apr 2025 17:24:18 +0200 Subject: [PATCH] fused coordinates and places table --- .../resource_types/coordinatesController.js | 151 ---------------- src/models/resource_types/coordinatesModel.js | 63 ------- .../resource_types/coordinatesRepository.js | 84 --------- .../resource_types/placesRepository.js | 17 +- src/routes/index.js | 169 ++---------------- 5 files changed, 22 insertions(+), 462 deletions(-) delete mode 100644 src/controllers/resource_types/coordinatesController.js delete mode 100644 src/models/resource_types/coordinatesModel.js delete mode 100644 src/repositories/resource_types/coordinatesRepository.js diff --git a/src/controllers/resource_types/coordinatesController.js b/src/controllers/resource_types/coordinatesController.js deleted file mode 100644 index 81ff486..0000000 --- a/src/controllers/resource_types/coordinatesController.js +++ /dev/null @@ -1,151 +0,0 @@ -import { - getCoordinatesListModel, - countCoordinatesListModel, - insertCoordinatesModel, - modifyCoordinatesModel, - softDeleteCoordinatesModel -} from "../../models/resource_types/coordinatesModel.js"; -import { error404 } from "../../utils/errors.js" -import { sendResponseNotFound } from "../../utils/responses.js"; -import { noResults } from "../../validators/result-validators.js"; -import mysql from "../../adapters/mysql.js"; -import { errorHandler } from "../../utils/errors.js"; - -const getCoordinatesListController = (req, res, next, config) => { - const conn = mysql.start(config) - - Promise.all([ - getCoordinatesListModel({...req.query, conn}), - countCoordinatesListModel({...req.query, conn}) - ]) - .then(([getResults, countResults]) => { - next({ - _data: {coordinates: getResults}, - _page: { - totalElements: countResults, - limit: req.query.limit || 100, - page: req.query.page || (countResults && 1) || 0 - } - }) - }) - .catch((err) => { - const error = errorHandler(err, config.environment) - res.status(error.code).json(error) - }) - .finally(() => { - mysql.end(conn) - }) -} - -const getCoordinatesByUuidController = (req, res, next, config) => { - const uuid_coordinates = req.params.uuid - const conn = mysql.start(config) - - getCoordinatesListModel({ uuid_coordinates, conn }) - .then((response) => { - if (noResults(response)) { - const err = error404() - const error = errorHandler(err, config.environment) - return sendResponseNotFound(res, error) - } - - const result = { - _data: { - coordinates: response - } - } - next(result) - }) - .catch((err) => { - const error = errorHandler(err, config.environment) - res.status(error.code).json(error) - }) - .finally(() => { - mysql.end(conn) - }) -} - -const postCoordinatesController = (req, res, next, config) => { - const conn = mysql.start(config) - - insertCoordinatesModel({ ...req.body, conn }) - .then((response) => { - const result = { - _data: { - coordinates: response - } - } - next(result) - }) - .catch((err) => { - const error = errorHandler(err, config.environment) - res.status(error.code).json(error) - }) - .finally(() => { - mysql.end(conn) - }) -} - -const putCoordinatesController = (req, res, next, config) => { - const uuid_coordinates = req.params.uuid - const conn = mysql.start(config) - - modifyCoordinatesModel({ ...req.body, uuid: uuid_coordinates, conn }) - .then((response) => { - if (noResults(response)) { - const err = error404() - const error = errorHandler(err, config.environment) - return sendResponseNotFound(res, error) - } - const result = { - _data: { - coordinates: response - } - } - next(result) - }) - .catch((err) => { - const error = errorHandler(err, config.environment) - res.status(error.code).json(error) - }) - .finally(() => { - mysql.end(conn) - }) -} - -const deleteCoordinatesController = (req, res, next, config) => { - const uuid_coordinates = req.params.uuid - const conn = mysql.start(config) - - softDeleteCoordinatesModel({ uuid: uuid_coordinates, conn }) - .then((response) => { - if (noResults(response)) { - const err = error404() - const error = errorHandler(err, config.environment) - return sendResponseNotFound(res, error) - } - - const result = { - _data: { - coordinates: response - } - } - next(result) - - }) - .catch((err) => { - const error = errorHandler(err, config.environment) - res.status(error.code).json(error) - }) - .finally(() => { - mysql.end(conn) - }) -} - -export { - getCoordinatesListController, - getCoordinatesByUuidController, - postCoordinatesController, - putCoordinatesController, - deleteCoordinatesController -} diff --git a/src/models/resource_types/coordinatesModel.js b/src/models/resource_types/coordinatesModel.js deleted file mode 100644 index 76d3df6..0000000 --- a/src/models/resource_types/coordinatesModel.js +++ /dev/null @@ -1,63 +0,0 @@ -import { - getCoordinatesListQuery, - countCoordinatesListQuery, - insertCoordinatesQuery, - updateCoordinatesQuery, - softDeleteCoordinatesQuery -} from "../../repositories/resource_types/coordinatesRepository.js"; -import { randomUUID as uuidv4 } from 'node:crypto' -import dayjs from 'dayjs' -import mysql from '../../adapters/mysql.js' -import { error404 } from '../../utils/errors.js' - -const getCoordinatesListModel = ({conn, ...rest}) => { - const now = dayjs.utc().format('YYYY-MM-DD HH:mm:ss') - const paramsToSearch = {...rest, now} - return mysql - .execute(getCoordinatesListQuery(paramsToSearch), conn, paramsToSearch) - .then(queryResult => queryResult.map(({id, created, deleted, createdBy, deletedBy, ...resultFiltered}) => resultFiltered)) -} - -const countCoordinatesListModel = ({conn, ...rest}) => { - const now = dayjs.utc().format('YYYY-MM-DD HH:mm:ss') - const paramsToSearch = {...rest, now} - return mysql - .execute(countCoordinatesListQuery(paramsToSearch), conn, paramsToSearch) - .then(results => results[0].count) -} - -const insertCoordinatesModel = ({conn, ...params}) => { - const now = dayjs.utc().format('YYYY-MM-DD HH:mm:ss') - const uuid = uuidv4() - return mysql - .execute(insertCoordinatesQuery({...params, uuid, now}), conn, {...params, uuid, now}) - .then(queryResult => queryResult[1].map(({id, created, deleted, createdBy, deletedBy, ...resultFiltered}) => resultFiltered)) -} - -const modifyCoordinatesModel = ({conn, ...params}) => { - return mysql - .execute(updateCoordinatesQuery(params), conn, params) - .then(queryResult => { - const deletedItem = queryResult[1].find(item => item.deleted !== null); - - if (deletedItem) { - throw error404() - } - return queryResult[1].map(({id, created, deleted, createdBy, deletedBy, ...resultFiltered}) => resultFiltered) - }) -} - -const softDeleteCoordinatesModel = ({uuid, deleted, deletedBy, conn}) => { - const deletedData = deleted ? dayjs.utc(deleted).format('YYYY-MM-DD HH:mm:ss') : dayjs.utc().format('YYYY-MM-DD HH:mm:ss') - const params = {uuid, deletedBy, deleted: deletedData} - return mysql - .execute(softDeleteCoordinatesQuery(params), conn, params) -} - -export { - getCoordinatesListModel, - countCoordinatesListModel, - insertCoordinatesModel, - modifyCoordinatesModel, - softDeleteCoordinatesModel -} diff --git a/src/repositories/resource_types/coordinatesRepository.js b/src/repositories/resource_types/coordinatesRepository.js deleted file mode 100644 index b6d2b1f..0000000 --- a/src/repositories/resource_types/coordinatesRepository.js +++ /dev/null @@ -1,84 +0,0 @@ -import { pagination } from "../../utils/pagination.js"; - -const _coordinatesSelectQuery = (_pagination = '') => ({ count }) => ({ uuid, latitude, longitude }) => { - const uuidCondition = uuid ? 'AND c.uuid = :uuid ' : ''; - const latitudeCondition = latitude ? 'AND c.latitude = :latitude ' : ''; - const longitudeCondition = longitude ? 'AND c.longitude = :longitude ' : ''; - - return ` - SELECT ${count || - `c.uuid, - c.created, - c.createdby, - c.latitude, - c.longitude`} - FROM dbmaster.coordinates AS c - WHERE c.created <= :now - AND (c.deleted > :now OR c.deleted IS NULL) - AND true - ${uuidCondition} - ${latitudeCondition} - ${longitudeCondition} - ${_pagination} - `; -} - -const getCoordinatesListQuery = ({ limit, page, ...rest }) => - _coordinatesSelectQuery(pagination({ limit, page }))({ count: false })(rest); - -const countCoordinatesListQuery = rest => - _coordinatesSelectQuery()({ count: 'COUNT(DISTINCT(c.uuid)) AS count' })(rest); - -const insertCoordinatesQuery = () => { - return ` - INSERT INTO dbmaster.coordinates ( - uuid, - latitude, - longitude, - created, - createdBy - ) - VALUES ( - :uuid, - :latitude, - :longitude, - :now, - :createdBy - ); - SELECT * FROM dbmaster.coordinates WHERE uuid = :uuid; - ` -} - -const updateCoordinatesQuery = (latitude, longitude) => { - const latitudeCondition = latitude ? 'latitude = :latitude,' : ''; - const longitudeCondition = longitude ? 'longitude = :longitude,' : ''; - return ` - UPDATE dbmaster.coordinates - SET - ${latitudeCondition} - ${longitudeCondition} - uuid = :uuid - WHERE uuid = :uuid - AND deleted IS NULL; - SELECT * FROM dbmaster.coordinates WHERE uuid = :uuid; - ` -} - -const softDeleteCoordinatesQuery = () => { - return ` - UPDATE - dbmaster.coordinates - SET - deleted = :deleted, deletedby = :deletedBy - WHERE uuid = :uuid - AND deleted IS NULL; - ` -} - -export { - getCoordinatesListQuery, - countCoordinatesListQuery, - insertCoordinatesQuery, - updateCoordinatesQuery, - softDeleteCoordinatesQuery -} \ No newline at end of file diff --git a/src/repositories/resource_types/placesRepository.js b/src/repositories/resource_types/placesRepository.js index 3502031..4ce8e4e 100644 --- a/src/repositories/resource_types/placesRepository.js +++ b/src/repositories/resource_types/placesRepository.js @@ -12,11 +12,10 @@ const _placeSelectQuery = (_pagination = '') => ({ count }) => ({ uuid, name, de p.name, p.description, p.address, - c.latitude, - c.longitude, + p.latitude, + p.longitude, p.created`} FROM dbmaster.places AS p - JOIN dbmaster.coordinates AS c ON p.fk_coordinate = c.id WHERE p.deleted IS NULL AND p.created <= :now AND (p.deleted > :now OR p.deleted IS NULL) @@ -46,7 +45,8 @@ const insertPlaceQuery = ({ description, address, createdBy }) => { name, description, address, - fk_coordinates, + longitude, + latitude created, createdBy ) @@ -55,7 +55,8 @@ const insertPlaceQuery = ({ description, address, createdBy }) => { :name, ${descriptionCondition}, ${addressCondition}, - (SELECT id FROM dbmaster.coordinates WHERE latitude = :latitude AND longitude = :longitude), + :longitude + :latitude, :now, ${createdByCondition} ) @@ -66,7 +67,8 @@ const updatePlaceQuery = ({ name, description, address, latitude, longitude }) = const nameCondition = name ? 'name = :name,' : ''; const descriptionCondition = description ? 'description = :description,' : ''; const addressCondition = address ? 'address = :address' : ''; - const fk_coordinateCondition = latitude && longitude ? 'fk_coordinate = (SELECT id FROM dbmaster.coordinates WHERE latitude = :latitude AND longitude = :longitude),' : ''; + const longitudeCondition = longitude ? 'longitude = :longitude' : ''; + const latitudeCondition = latitude ? 'latitude = :latitude' : ''; return ` UPDATE dbmaster.places AS p @@ -74,7 +76,8 @@ const updatePlaceQuery = ({ name, description, address, latitude, longitude }) = ${nameCondition} ${descriptionCondition} ${addressCondition} - ${fk_coordinateCondition} + ${longitudeCondition} + ${latitudeCondition} WHERE p.uuid = :uuid AND p.deleted IS NULL diff --git a/src/routes/index.js b/src/routes/index.js index e87e6c2..3acf828 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -879,7 +879,9 @@ export default(config) => { * @param {string} uuid.path.required - The unique identifier for the place * @param {string} name.path.required - The name of the place * @param {string} address.path.required - The address of the place - * @param {string} fk_coordinate.path.required - The unique identifier for the coordinate + * @param {string} latitude.path.required - The latitude of the place + * @param {string} longitude.path.required - The longitude of the place + * @param {string} description.path.optional - The description of the place * @returns {SuccessResponse} 200 - The place object * @returns {ErrorResponse} 404 - Place not found * @returns {ErrorResponse} 422 - Unprocessable entity @@ -915,7 +917,9 @@ export default(config) => { * @param {string} uuid.path.required - The unique identifier for the place * @param {string} name.path.required - The name of the place * @param {string} address.path.required - The address of the place - * @param {string} fk_coordinate.path.required - The unique identifier for the coordinate + * @param {string} latitude.path.required - The latitude of the place + * @param {string} longitude.path.required - The longitude of the place + * @param {string} description.path.optional - The description of the place * @returns {SuccessResponse} 200 - The place object * @returns {ErrorResponse} 404 - Place not found * @returns {ErrorResponse} 422 - Unprocessable entity @@ -950,7 +954,9 @@ export default(config) => { * @group Places - Operations about places * @param {string} name.path.required - The name of the place * @param {string} address.path.required - The address of the place - * @param {string} fk_coordinate.path.required - The unique identifier for the coordinate + * @param {string} description.path.required - The description of the place + * @param {string} latitude.path.required - The latitude of the place + * @param {string} longitude.path.required - The longitude of the place * @returns {SuccessResponse} 200 - Place created successfully * @returns {ErrorResponse} 400 - Bad request * @returns {ErrorResponse} 404 - Place not found @@ -985,7 +991,9 @@ export default(config) => { * @param {string} uuid.path.required - The unique identifier for the place * @param {string} name.path.required - The name of the place * @param {string} address.path.required - The address of the place - * @param {string} fk_coordinate.path.required - The unique identifier for the coordinate + * @param {string} latitude.path.required - The latitude of the place + * @param {string} longitude.path.required - The longitude of the place + * @param {string} description.path.optional - The description of the place * @returns {SuccessResponse} 200 - Place updated successfully * @returns {ErrorResponse} 400 - Bad request * @returns {ErrorResponse} 404 - Place not found @@ -1038,159 +1046,6 @@ export default(config) => { (result, req, res, _) => sendResponseNoContent(result, req, res) ); - // Coordinates Routes - /** - * @name GET/coordinates - * @function - * @inner - * @memberof placeRouter - * @route GET /coordinates - * @group Coordinates - Operations about coordinates - * @param {string} uuid.path.required - The unique identifier for the coordinate - * @param {string} latitude.path.required - The latitude of the coordinate - * @param {string} longitude.path.required - The longitude of the coordinate - * @returns {SuccessResponse} 200 - The coordinate object - * @returns {ErrorResponse} 404 - Coordinate not found - * @returns {ErrorResponse} 422 - Unprocessable entity - * @returns {ErrorResponse} 500 - Internal server error - * @returns {ErrorResponse} 403 - Forbidden - */ - routes.get( - '/coordinates', - (req, res, next) => authenticateToken(req, res, next, config), - (req, res, next) => authorizePermission('/coordinates')(req, res, next, config), - [ - uuid('uuid').optional({ nullable: false, values: 'falsy' }), - varChar('latitude').optional({ nullable: false, values: 'falsy' }), - varChar('longitude').optional({ nullable: false, values: 'falsy' }), - ], - (req, res, next) => payloadExpressValidator(req, res, next, config), - (req, res, next) => getCoordinatesListController(req, res, next, config), - (result, req, res, next) => addLinks(result, req, res, next, hasAddLinks, linkRoutes), - (result, req, res, _) => sendOkResponse(result, req, res) - ); - - /** - * @name GET/coordinates/:uuid - * @function - * @inner - * @memberof placeRouter - * @route GET /coordinates/{uuid} - * @group Coordinates - Operations about coordinates - * @param {string} uuid.path.required - The unique identifier for the coordinate - * @param {string} latitude.path.required - The latitude of the coordinate - * @param {string} longitude.path.required - The longitude of the coordinate - * @returns {SuccessResponse} 200 - The coordinate object - * @returns {ErrorResponse} 404 - Coordinate not found - * @returns {ErrorResponse} 422 - Unprocessable entity - * @returns {ErrorResponse} 500 - Internal server error - * @returns {ErrorResponse} 403 - Forbidden - */ - routes.get( - '/coordinates/:uuid', - (req, res, next) => authenticateToken(req, res, next, config), - (req, res, next) => authorizePermission('/coordinates/:uuid')(req, res, next, config), - [ - uuid('uuid'), - varChar('latitude').optional({ nullable: false, values: 'falsy' }), - varChar('longitude').optional({ nullable: false, values: 'falsy' }), - ], - (req, res, next) => payloadExpressValidator(req, res, next, config), - (req, res, next) => getCoordinatesByUuidController(req, res, next, config), - (result, req, res, next) => addLinks(result, req, res, next, hasAddLinks, linkRoutes), - (result, req, res, _) => sendOkResponse(result, req, res) - ); - - /** - * @name POST/coordinates - * @function - * @inner - * @memberof placeRouter - * @route POST /coordinates - * @group Coordinates - Operations about coordinates - * @param {string} latitude.path.required - The latitude of the coordinate - * @param {string} longitude.path.required - The longitude of the coordinate - * @returns {SuccessResponse} 200 - Coordinate created successfully - * @returns {ErrorResponse} 400 - Bad request - * @returns {ErrorResponse} 404 - Coordinate not found - * @returns {ErrorResponse} 422 - Unprocessable entity - * @returns {ErrorResponse} 500 - Internal server error - * @returns {ErrorResponse} 403 - Forbidden - */ - routes.post( - '/coordinates', - (req, res, next) => authenticateToken(req, res, next, config), - (req, res, next) => authorizePermission('/coordinates')(req, res, next, config), - [ - varChar('latitude'), - varChar('longitude') - ], - (req, res, next) => payloadExpressValidator(req, res, next, config), - (req, res, next) => postCoordinatesController(req, res, next, config), - (result, req, res, next) => addLinks(result, req, res, next, hasAddLinks, linkRoutes), - (result, req, res, _) => sendCreatedResponse(result, req, res) - ); - - /** - * @name PUT/coordinates/:uuid - * @function - * @inner - * @memberof placeRouter - * @route PUT /coordinates/{uuid} - * @group Coordinates - Operations about coordinates - * @param {string} uuid.path.required - The unique identifier for the coordinate - * @param {string} latitude.path.required - The latitude of the coordinate - * @param {string} longitude.path.required - The longitude of the coordinate - * @returns {SuccessResponse} 200 - Coordinate updated successfully - * @returns {ErrorResponse} 400 - Bad request - * @returns {ErrorResponse} 404 - Coordinate not found - * @returns {ErrorResponse} 422 - Unprocessable entity - * @returns {ErrorResponse} 500 - Internal server error - * @returns {ErrorResponse} 403 - Forbidden - */ - routes.put( - '/coordinates/:uuid', - (req, res, next) => authenticateToken(req, res, next, config), - (req, res, next) => authorizePermission('/coordinates/:uuid')(req, res, next, config), - [ - uuid('uuid'), - varChar('latitude').optional({ nullable: false, values: 'falsy' }), - varChar('longitude').optional({ nullable: false, values: 'falsy' }), - ], - (req, res, next) => payloadExpressValidator(req, res, next, config), - (req, res, next) => putCoordinatesController(req, res, next, config), - (result, req, res, next) => addLinks(result, req, res, next, hasAddLinks, linkRoutes), - (result, req, res, _) => sendCreatedResponse(result, req, res) - ); - - /** - * @name DELETE/coordinates/:uuid - * @function - * @inner - * @memberof placeRouter - * @route DELETE /coordinates/{uuid} - * @group Coordinates - Operations about coordinates - * @param {string} uuid.path.required - The unique identifier for the coordinate - * @returns {SuccessResponse} 200 - Coordinate deleted successfully. No content - * @returns {ErrorResponse} 404 - Coordinate not found - * @returns {ErrorResponse} 422 - Unprocessable entity - * @returns {ErrorResponse} 500 - Internal server error - * @returns {ErrorResponse} 403 - Forbidden - * @returns {ErrorResponse} 401 - Unauthorized - */ - routes.delete( - '/coordinates/:uuid', - (req, res, next) => authenticateToken(req, res, next, config), - (req, res, next) => authorizePermission('/coordinates/:uuid')(req, res, next, config), - [ - uuid('uuid') - ], - (req, res, next) => payloadExpressValidator(req, res, next, config), - (req, res, next) => deleteCoordinatesController(req, res, next, config), - (result, req, res, next) => addLinks(result, req, res, next, hasAddLinks, linkRoutes), - (result, req, res, _) => sendResponseNoContent(result, req, res) - ); - //Reports routes /** * @name GET/users_has_places