fused coordinates and places table

This commit is contained in:
Pau 2025-04-17 17:24:18 +02:00
parent d9f6e3a928
commit 51320dd973
5 changed files with 22 additions and 462 deletions

View File

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

View File

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

View File

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

View File

@ -12,11 +12,10 @@ const _placeSelectQuery = (_pagination = '') => ({ count }) => ({ uuid, name, de
p.name, p.name,
p.description, p.description,
p.address, p.address,
c.latitude, p.latitude,
c.longitude, p.longitude,
p.created`} p.created`}
FROM dbmaster.places AS p FROM dbmaster.places AS p
JOIN dbmaster.coordinates AS c ON p.fk_coordinate = c.id
WHERE p.deleted IS NULL WHERE p.deleted IS NULL
AND p.created <= :now AND p.created <= :now
AND (p.deleted > :now OR p.deleted IS NULL) AND (p.deleted > :now OR p.deleted IS NULL)
@ -46,7 +45,8 @@ const insertPlaceQuery = ({ description, address, createdBy }) => {
name, name,
description, description,
address, address,
fk_coordinates, longitude,
latitude
created, created,
createdBy createdBy
) )
@ -55,7 +55,8 @@ const insertPlaceQuery = ({ description, address, createdBy }) => {
:name, :name,
${descriptionCondition}, ${descriptionCondition},
${addressCondition}, ${addressCondition},
(SELECT id FROM dbmaster.coordinates WHERE latitude = :latitude AND longitude = :longitude), :longitude
:latitude,
:now, :now,
${createdByCondition} ${createdByCondition}
) )
@ -66,7 +67,8 @@ const updatePlaceQuery = ({ name, description, address, latitude, longitude }) =
const nameCondition = name ? 'name = :name,' : ''; const nameCondition = name ? 'name = :name,' : '';
const descriptionCondition = description ? 'description = :description,' : ''; const descriptionCondition = description ? 'description = :description,' : '';
const addressCondition = address ? 'address = :address' : ''; 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 ` return `
UPDATE dbmaster.places AS p UPDATE dbmaster.places AS p
@ -74,7 +76,8 @@ const updatePlaceQuery = ({ name, description, address, latitude, longitude }) =
${nameCondition} ${nameCondition}
${descriptionCondition} ${descriptionCondition}
${addressCondition} ${addressCondition}
${fk_coordinateCondition} ${longitudeCondition}
${latitudeCondition}
WHERE WHERE
p.uuid = :uuid p.uuid = :uuid
AND p.deleted IS NULL AND p.deleted IS NULL

View File

@ -879,7 +879,9 @@ export default(config) => {
* @param {string} uuid.path.required - The unique identifier for the place * @param {string} uuid.path.required - The unique identifier for the place
* @param {string} name.path.required - The name of the place * @param {string} name.path.required - The name of the place
* @param {string} address.path.required - The address 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 {SuccessResponse} 200 - The place object
* @returns {ErrorResponse} 404 - Place not found * @returns {ErrorResponse} 404 - Place not found
* @returns {ErrorResponse} 422 - Unprocessable entity * @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} uuid.path.required - The unique identifier for the place
* @param {string} name.path.required - The name of the place * @param {string} name.path.required - The name of the place
* @param {string} address.path.required - The address 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 {SuccessResponse} 200 - The place object
* @returns {ErrorResponse} 404 - Place not found * @returns {ErrorResponse} 404 - Place not found
* @returns {ErrorResponse} 422 - Unprocessable entity * @returns {ErrorResponse} 422 - Unprocessable entity
@ -950,7 +954,9 @@ export default(config) => {
* @group Places - Operations about places * @group Places - Operations about places
* @param {string} name.path.required - The name of the place * @param {string} name.path.required - The name of the place
* @param {string} address.path.required - The address 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 {SuccessResponse} 200 - Place created successfully
* @returns {ErrorResponse} 400 - Bad request * @returns {ErrorResponse} 400 - Bad request
* @returns {ErrorResponse} 404 - Place not found * @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} uuid.path.required - The unique identifier for the place
* @param {string} name.path.required - The name of the place * @param {string} name.path.required - The name of the place
* @param {string} address.path.required - The address 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 {SuccessResponse} 200 - Place updated successfully
* @returns {ErrorResponse} 400 - Bad request * @returns {ErrorResponse} 400 - Bad request
* @returns {ErrorResponse} 404 - Place not found * @returns {ErrorResponse} 404 - Place not found
@ -1038,159 +1046,6 @@ export default(config) => {
(result, req, res, _) => sendResponseNoContent(result, req, res) (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 //Reports routes
/** /**
* @name GET/users_has_places * @name GET/users_has_places