diff --git a/src/controllers/locais-coleta-controller.js b/src/controllers/locais-coleta-controller.js index 0467ed91..84274376 100644 --- a/src/controllers/locais-coleta-controller.js +++ b/src/controllers/locais-coleta-controller.js @@ -4,7 +4,7 @@ import models from '../models'; import codigos from '../resources/codigos-http'; const { - Relevo, Solo, Vegetacao, LocalColeta, Cidade, FaseSucessional, sequelize, + Relevo, Solo, Vegetacao, LocalColeta, Cidade, FaseSucessional, Estado, Pais, sequelize, } = models; export const cadastrarSolo = (request, response, next) => { @@ -133,7 +133,7 @@ export const cadastrarLocalColeta = async (request, response, next) => { export const buscarLocaisColeta = async (request, response, next) => { try { - const { cidadeId } = request.query; + const { cidade_id: cidadeId } = request.query; const { limite, pagina, offset } = request.paginacao; const where = {}; @@ -144,7 +144,15 @@ export const buscarLocaisColeta = async (request, response, next) => { const { count, rows } = await LocalColeta.findAndCountAll({ where, include: [ - { model: Cidade }, + { model: Cidade, + include: [ + { model: Estado, + include: [ + Pais, + ], + }, + ], + }, { model: FaseSucessional }, ], limit: limite, @@ -164,4 +172,107 @@ export const buscarLocaisColeta = async (request, response, next) => { } }; +export const buscarLocalColetaPorId = async (request, response, next) => { + try { + const { id } = request.params; + + const localColeta = await LocalColeta.findOne({ + where: { id }, + include: [ + { model: Cidade, + include: [ + { model: Estado, + include: [ + Pais, + ], + }, + ], + }, + { model: FaseSucessional }, + ], + }); + + if (!localColeta) { + response.status(404).json({ + mensagem: 'Local de coleta não encontrado.', + }); + return; + } + + response.status(200).json(localColeta); + } catch (error) { + next(error); + } +}; + +export const atualizarLocalColeta = async (request, response, next) => { + try { + const { id } = request.params; + const dados = pick(request.body, ['descricao', 'complemento', 'cidade_id', 'fase_sucessional_id']); + + const [updated] = await LocalColeta.update(dados, { + where: { id }, + }); + + if (updated === 0) { + response.status(404).json({ + mensagem: 'Local de coleta não encontrado.', + }); + return; + } + + const localColetaAtualizado = await LocalColeta.findOne({ + where: { id }, + include: [ + { model: Cidade }, + { model: FaseSucessional }, + ], + }); + + response.status(200).json(localColetaAtualizado); + } catch (error) { + next(error); + } +}; + +export const deletarLocalColeta = async (request, response, next) => { + try { + const { id } = request.params; + + const localColeta = await LocalColeta.findOne({ + where: { id }, + }); + + if (!localColeta) { + response.status(404).json({ + mensagem: 'Local de coleta não encontrado.', + }); + return; + } + + const { Tombo } = models; + const tombosAssociados = await Tombo.count({ + where: { + local_coleta_id: id, + ativo: true, + }, + }); + + if (tombosAssociados > 0) { + response.status(400).json({ + mensagem: `Não é possível excluir o local de coleta. Existem ${tombosAssociados} tombo(s) associado(s) a este local.`, + }); + return; + } + + await LocalColeta.destroy({ + where: { id }, + }); + + response.status(204).send(); + + } catch (error) { + next(error); + } +}; export default {}; diff --git a/src/controllers/tombos-controller.js b/src/controllers/tombos-controller.js index 5b05f1e9..b220aab0 100644 --- a/src/controllers/tombos-controller.js +++ b/src/controllers/tombos-controller.js @@ -104,7 +104,7 @@ export const cadastro = (request, response, next) => { return undefined; }) .then(() => { - if(!localidade?.complemento){ + if (!localidade?.complemento) { throw new BadRequestExeption(400); } return LocalColeta.findOne({ @@ -275,7 +275,7 @@ export const cadastro = (request, response, next) => { coletor_id: coletor, }; - if(paisagem.descricao) { + if (paisagem.descricao) { jsonTombo.descricao = paisagem.descricao; } diff --git a/src/routes/locais.js b/src/routes/locais.js index b095a036..3a535c21 100644 --- a/src/routes/locais.js +++ b/src/routes/locais.js @@ -336,4 +336,189 @@ export default app => { validacoesMiddleware(localColetaListagemEsquema), controller.buscarLocaisColeta, ]); + /** + * @swagger + * /locais-coleta/{id}: + * get: + * summary: Busca um local de coleta pelo ID + * tags: [Locais] + * description: Retorna os dados de um local de coleta específico. + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: ID do local de coleta + * responses: + * 200: + * description: Dados do local de coleta encontrados + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: integer + * descricao: + * type: string + * complemento: + * type: string + * nullable: true + * cidade_id: + * type: integer + * fase_sucessional_id: + * type: integer + * nullable: true + * cidade: + * type: object + * properties: + * id: + * type: integer + * nome: + * type: string + * fase_sucessional: + * type: object + * nullable: true + * properties: + * id: + * type: integer + * nome: + * type: string + * '401': + * $ref: '#/components/responses/Unauthorized' + * '403': + * $ref: '#/components/responses/Forbidden' + * '404': + * $ref: '#/components/responses/NotFound' + * '500': + * $ref: '#/components/responses/InternalServerError' + * put: + * summary: Atualiza um local de coleta + * tags: [Locais] + * description: Atualiza os dados de um local de coleta existente. + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: ID do local de coleta + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * descricao: + * type: string + * description: Descrição do local de coleta + * complemento: + * type: string + * description: Complemento do local de coleta + * cidade_id: + * type: integer + * description: ID da cidade + * fase_sucessional_id: + * type: integer + * description: ID da fase sucessional + * required: + * - descricao + * - cidade_id + * example: + * descricao: "Próximo ao córrego" + * complemento: "Entrada pelo portão principal" + * cidade_id: 2 + * fase_sucessional_id: 3 + * responses: + * 200: + * description: Local de coleta atualizado com sucesso + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: integer + * descricao: + * type: string + * complemento: + * type: string + * cidade_id: + * type: integer + * fase_sucessional_id: + * type: integer + * '400': + * $ref: '#/components/responses/BadRequest' + * '401': + * $ref: '#/components/responses/Unauthorized' + * '403': + * $ref: '#/components/responses/Forbidden' + * '404': + * $ref: '#/components/responses/NotFound' + * '500': + * $ref: '#/components/responses/InternalServerError' + */ + app.route('/locais-coleta/:id') + .get([ + tokensMiddleware([ + TIPOS_USUARIOS.CURADOR, + TIPOS_USUARIOS.OPERADOR, + TIPOS_USUARIOS.IDENTIFICADOR, + ]), + controller.buscarLocalColetaPorId, + ]) + .put([ + tokensMiddleware([ + TIPOS_USUARIOS.CURADOR, + TIPOS_USUARIOS.OPERADOR, + ]), + validacoesMiddleware(localColetaCadastroEsquema), + controller.atualizarLocalColeta, + ]) + /** + * @swagger + * /locais-coleta/{id}: + * delete: + * summary: Remove um local de coleta + * tags: [Locais] + * description: Remove um local de coleta pelo ID. Verifica se não há tombos associados antes de remover. + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * description: ID do local de coleta + * responses: + * 204: + * description: Local de coleta removido com sucesso + * '400': + * description: Não é possível excluir - existem tombos associados + * content: + * application/json: + * schema: + * type: object + * properties: + * mensagem: + * type: string + * example: + * mensagem: "Não é possível excluir o local de coleta. Existem 5 tombo(s) associado(s) a este local." + * '401': + * $ref: '#/components/responses/Unauthorized' + * '403': + * $ref: '#/components/responses/Forbidden' + * '404': + * $ref: '#/components/responses/NotFound' + * '500': + * $ref: '#/components/responses/InternalServerError' + */ + .delete([ + tokensMiddleware([ + TIPOS_USUARIOS.CURADOR, + TIPOS_USUARIOS.OPERADOR, + ]), + controller.deletarLocalColeta, + ]); };