From fff2948d9222821ff104909f4600b75203bafb9a Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Mon, 22 Sep 2025 15:14:08 -0300 Subject: [PATCH 1/2] [MVPTN-15] feat(CRUD): Crud completo para a tabela g_medida_tipo --- .../g_medida_tipo_delete_action.py | 26 ++++ .../g_medida_tipo_get_by_descricao_action.py | 29 +++++ .../g_medida_tipo_index_action.py | 24 ++++ .../g_medida_tipo_save_action.py | 28 +++++ .../g_medida_tipo_show_action.py | 28 +++++ .../g_medida_tipo_update_action.py | 26 ++++ .../controllers/g_medida_tipo_controller.py | 113 ++++++++++++++++++ .../endpoints/g_medida_tipo_endpoint.py | 108 +++++++++++++++++ .../g_medida_tipo_delete_repository.py | 41 +++++++ ...medida_tipo_get_by_descricao_repository.py | 29 +++++ .../g_medida_tipo_index_repository.py | 23 ++++ .../g_medida_tipo_save_repository.py | 53 ++++++++ .../g_medida_tipo_show_repository.py | 46 +++++++ .../g_medida_tipo_update_repository.py | 50 ++++++++ .../schemas/g_medida_tipo_schema.py | 97 +++++++++++++++ .../go/g_medida_tipo_delete_service.py | 27 +++++ .../go/g_medida_tipo_get_descricao_service.py | 38 ++++++ .../go/g_medida_tipo_index_service.py | 32 +++++ .../go/g_medida_tipo_save_service.py | 70 +++++++++++ .../go/g_medida_tipo_show_service.py | 35 ++++++ .../go/g_medida_tipo_update_service.py | 23 ++++ packages/v1/api.py | 6 + 22 files changed, 952 insertions(+) create mode 100644 packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_delete_action.py create mode 100644 packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_get_by_descricao_action.py create mode 100644 packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_index_action.py create mode 100644 packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_save_action.py create mode 100644 packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_show_action.py create mode 100644 packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_update_action.py create mode 100644 packages/v1/administrativo/controllers/g_medida_tipo_controller.py create mode 100644 packages/v1/administrativo/endpoints/g_medida_tipo_endpoint.py create mode 100644 packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_delete_repository.py create mode 100644 packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_get_by_descricao_repository.py create mode 100644 packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_index_repository.py create mode 100644 packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_save_repository.py create mode 100644 packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_show_repository.py create mode 100644 packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_update_repository.py create mode 100644 packages/v1/administrativo/schemas/g_medida_tipo_schema.py create mode 100644 packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_delete_service.py create mode 100644 packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_get_descricao_service.py create mode 100644 packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_index_service.py create mode 100644 packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_save_service.py create mode 100644 packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_show_service.py create mode 100644 packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_update_service.py diff --git a/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_delete_action.py b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_delete_action.py new file mode 100644 index 0000000..3ff0887 --- /dev/null +++ b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_delete_action.py @@ -0,0 +1,26 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema +from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_delete_repository import DeleteRepository + + +class DeleteAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoIdSchema): + """ + Executa a operação de exclusão no banco de dados. + + Args: + medida_tipo_schema (GMedidaTipoIdSchema): O esquema com o ID a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento do repositório + delete_repository = DeleteRepository() + + # Execução do repositório + return delete_repository.execute(medida_tipo_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_get_by_descricao_action.py b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_get_by_descricao_action.py new file mode 100644 index 0000000..61ddf88 --- /dev/null +++ b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_get_by_descricao_action.py @@ -0,0 +1,29 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoDescricaoSchema +from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_get_by_descricao_repository import GetByDescricaoRepository + + +class GetByDescricaoAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela g_medida_tipo por descrição. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoDescricaoSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + medida_tipo_schema (GMedidaTipoDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento do repositório + show_repository = GetByDescricaoRepository() + + # Execução do repositório + response = show_repository.execute(medida_tipo_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_index_action.py b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_index_action.py new file mode 100644 index 0000000..47b532a --- /dev/null +++ b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_index_action.py @@ -0,0 +1,24 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_index_repository import IndexRepository + +class IndexAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de todos os registros na tabela g_medida_tipo. + """ + + def execute(self): + """ + Executa a operação de listagem no banco de dados. + + Returns: + A lista de todos os registros. + """ + # Instanciamento do repositório + index_repository = IndexRepository() + + # Execução do repositório + response = index_repository.execute() + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_save_action.py b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_save_action.py new file mode 100644 index 0000000..11e3c10 --- /dev/null +++ b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_save_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoSaveSchema +from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_save_repository import SaveRepository + +class SaveAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de salvar um novo registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoSaveSchema): + """ + Executa a operação de salvamento. + + Args: + medida_tipo_schema (GMedidaTipoSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O resultado da operação de salvamento. + """ + # Instanciamento do repositório + save_repository = SaveRepository() + + # Execução do repositório + response = save_repository.execute(medida_tipo_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_show_action.py b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_show_action.py new file mode 100644 index 0000000..08af517 --- /dev/null +++ b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_show_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema +from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_show_repository import ShowRepository + +class ShowAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a exibição + de um registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoIdSchema): + """ + Executa a operação de exibição. + + Args: + medida_tipo_schema (GMedidaTipoIdSchema): O esquema com o ID do registro a ser exibido. + + Returns: + O resultado da operação de exibição. + """ + # Instanciamento do repositório + show_repository = ShowRepository() + + # Execução do repositório + response = show_repository.execute(medida_tipo_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_update_action.py b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_update_action.py new file mode 100644 index 0000000..0eac753 --- /dev/null +++ b/packages/v1/administrativo/actions/g_medida_tipo/g_medida_tipo_update_action.py @@ -0,0 +1,26 @@ +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoUpdateSchema +from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_update_repository import UpdateRepository + + +class UpdateAction: + """ + Service responsável por encapsular a lógica de negócio para a atualização + de um registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_id: int, medida_tipo_schema: GMedidaTipoUpdateSchema): + """ + Executa a operação de atualização. + + Args: + medida_tipo_id (int): O ID do registro a ser atualizado. + medida_tipo_schema (GMedidaTipoUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instância o repositório de atualização + update_repository = UpdateRepository() + + # Chama o método de execução do repositório para realizar a atualização + return update_repository.execute(medida_tipo_id, medida_tipo_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/controllers/g_medida_tipo_controller.py b/packages/v1/administrativo/controllers/g_medida_tipo_controller.py new file mode 100644 index 0000000..6917fa2 --- /dev/null +++ b/packages/v1/administrativo/controllers/g_medida_tipo_controller.py @@ -0,0 +1,113 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.administrativo.schemas.g_medida_tipo_schema import ( + GMedidaTipoSchema, + GMedidaTipoSaveSchema, + GMedidaTipoUpdateSchema, + GMedidaTipoIdSchema, + GMedidaTipoDescricaoSchema +) + +class GMedidaTipoController: + + def __init__(self): + # Action responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_medida_tipo") + pass + + # Lista todos os registros de g_medida_tipo + def index(self): + + # Importação da classe desejada + indexService = self.dynamic_import.service("g_medida_tipo_index_service", "IndexService") + + # Instância da classe service + self.indexService = indexService() + + # Lista todos os registros de g_medida_tipo + return { + 'message': 'Registros de g_medida_tipo localizados com sucesso', + 'data': self.indexService.execute() + } + + + # Busca um registro de g_medida_tipo específico pelo ID + def show(self, medida_tipo_schema: GMedidaTipoIdSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_medida_tipo_show_service', 'ShowService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de g_medida_tipo desejado + return { + 'message': 'Registro de g_medida_tipo localizado com sucesso', + 'data': self.show_service.execute(medida_tipo_schema) + } + + + # Busca um registro de g_medida_tipo pela descrição + def get_by_descricao(self, medida_tipo_schema: GMedidaTipoDescricaoSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('g_medida_tipo_get_descricao_service', 'GetByDescricaoService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de g_medida_tipo desejado + return { + 'message': 'Registro de g_medida_tipo localizado com sucesso', + 'data': self.show_service.execute(medida_tipo_schema, True) + } + + + # Cadastra um novo registro de g_medida_tipo + def save(self, medida_tipo_schema: GMedidaTipoSaveSchema): + + #Importação da classe desejada + save_service = self.dynamic_import.service('g_medida_tipo_save_service', 'SaveService') + + # Instância da classe desejada + self.save_service = save_service() + # Busca e retorna o registro de g_medida_tipo desejado + return { + 'message': 'Registro de g_medida_tipo salvo com sucesso', + 'data': self.save_service.execute(medida_tipo_schema) + } + + # Atualiza os dados de um registro de g_medida_tipo + def update(self, medida_tipo_id: int, medida_tipo_schema: GMedidaTipoUpdateSchema): + + #Importação da classe desejada + update_service = self.dynamic_import.service('g_medida_tipo_update_service', 'UpdateService') + + # Instância da classe desejada + self.update_service = update_service() + + # Busca e retorna o registro de g_medida_tipo desejado + return { + 'message': 'Registro de g_medida_tipo atualizado com sucesso', + 'data': self.update_service.execute(medida_tipo_id, medida_tipo_schema) + } + + # Exclui um registro de g_medida_tipo + def delete(self, medida_tipo_schema: GMedidaTipoIdSchema): + + #Importação da classe desejada + delete_service = self.dynamic_import.service('g_medida_tipo_delete_service', 'DeleteService') + + # Instância da classe desejada + self.delete_service = delete_service() + + # Busca e retorna o registro de g_medida_tipo desejado + return { + 'message': 'Registro de g_medida_tipo removido com sucesso', + 'data': self.delete_service.execute(medida_tipo_schema) + } \ No newline at end of file diff --git a/packages/v1/administrativo/endpoints/g_medida_tipo_endpoint.py b/packages/v1/administrativo/endpoints/g_medida_tipo_endpoint.py new file mode 100644 index 0000000..edc6e7f --- /dev/null +++ b/packages/v1/administrativo/endpoints/g_medida_tipo_endpoint.py @@ -0,0 +1,108 @@ +# Importação de bibliotecas +from typing import Optional +from fastapi import APIRouter, Body, Depends, status +from actions.jwt.get_current_user import get_current_user +from packages.v1.administrativo.controllers.g_medida_tipo_controller import GMedidaTipoController +from packages.v1.administrativo.schemas.g_medida_tipo_schema import ( + GMedidaTipoSchema, + GMedidaTipoSaveSchema, + GMedidaTipoUpdateSchema, + GMedidaTipoIdSchema +) + +# Inicializa o roteador para as rotas do tipo de reconhecimento +router = APIRouter() + +# Instanciamento do controller desejado +g_medida_tipo_controller = GMedidaTipoController() + +# Lista todos os registros de g_medida_tipo +@router.get('/', + status_code=status.HTTP_200_OK, + summary='Lista todos os registros de g_medida_tipo cadastrados', + response_description='Lista todos os registros de g_medida_tipo cadastrados') +async def index(current_user: dict = Depends(get_current_user)): + + # Busca todos os registros de g_medida_tipo cadastrados + response = g_medida_tipo_controller.index() + + # Retorna os dados localizados + return response + + +# Localiza um registro de g_medida_tipo pela descrição +@router.get('/descricao', + status_code=status.HTTP_200_OK, + summary='Busca um registro de g_medida_tipo em específico pela descrição', + response_description='Busca um registro de g_medida_tipo em específico') +async def get_by_descricao(descricao : str, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + medida_tipo_schema = GMedidaTipoSchema(descricao=descricao) + + # Busca um registro de g_medida_tipo específico pela descrição + response = g_medida_tipo_controller.get_by_descricao(medida_tipo_schema) + + # Retorna os dados localizados + return response + + +# Localiza um registro de g_medida_tipo pelo ID +@router.get('/{medida_tipo_id}', + status_code=status.HTTP_200_OK, + summary='Busca um registro de g_medida_tipo em específico pelo ID', + response_description='Busca um registro de g_medida_tipo em específico') +async def show(medida_tipo_id : int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + medida_tipo_schema = GMedidaTipoIdSchema(medida_tipo_id=medida_tipo_id) + + # Busca um registro de g_medida_tipo específico pelo ID + response = g_medida_tipo_controller.show(medida_tipo_schema) + + # Retorna os dados localizados + return response + + +# Cadastro de registro de g_medida_tipo +@router.post('/', + status_code=status.HTTP_201_CREATED, + summary='Cadastra um registro de g_medida_tipo', + response_description='Cadastra um registro de g_medida_tipo') +async def save(medida_tipo_schema: GMedidaTipoSaveSchema, current_user: dict = Depends(get_current_user)): + + # Efetua o cadastro no banco de dados + response = g_medida_tipo_controller.save(medida_tipo_schema) + + # Retorna os dados localizados + return response + + +# Atualiza os dados de um registro de g_medida_tipo +@router.put('/{medida_tipo_id}', + status_code=status.HTTP_200_OK, + summary='Atualiza um registro de g_medida_tipo', + response_description='Atualiza um registro de g_medida_tipo') +async def update(medida_tipo_id: int, medida_tipo_schema: GMedidaTipoUpdateSchema, current_user: dict = Depends(get_current_user)): + + # Efetua a atualização dos dados + response = g_medida_tipo_controller.update(medida_tipo_id, medida_tipo_schema) + + # Retorna os dados localizados + return response + +# Exclui um determinado registro de g_medida_tipo +@router.delete('/{medida_tipo_id}', + status_code=status.HTTP_200_OK, + summary='Remove um registro de g_medida_tipo', + response_description='Remove um registro de g_medida_tipo') +async def delete(medida_tipo_id: int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + medida_tipo_schema = GMedidaTipoIdSchema(medida_tipo_id=medida_tipo_id) + + # Efetua a exclusão do registro de g_medida_tipo + response = g_medida_tipo_controller.delete(medida_tipo_schema) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_delete_repository.py b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_delete_repository.py new file mode 100644 index 0000000..82a5675 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_delete_repository.py @@ -0,0 +1,41 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema +from fastapi import HTTPException, status + +class DeleteRepository(BaseRepository): + """ + Repositório para a operação de exclusão de um registro na tabela + g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoIdSchema): + """ + Executa a consulta SQL para remover um registro pelo ID. + + Args: + medida_tipo_schema (GMedidaTipoIdSchema): O esquema com o ID a ser removido. + + Returns: + O resultado da operação de exclusão. + """ + try: + # Montagem do sql + sql = """ DELETE FROM G_MEDIDA_TIPO WHERE MEDIDA_TIPO_ID = :medida_tipo_id """ + + # Preenchimento de parâmetros + params = { + "medida_tipo_id": medida_tipo_schema.medida_tipo_id + } + + # Execução do sql + response = self.run(sql, params) + + # Retorna o resultado + return response + + except Exception as e: + # Informa que houve uma falha na exclusão + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao excluir G_MEDIDA_TIPO: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_get_by_descricao_repository.py b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_get_by_descricao_repository.py new file mode 100644 index 0000000..9b35fae --- /dev/null +++ b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_get_by_descricao_repository.py @@ -0,0 +1,29 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoDescricaoSchema + +class GetByDescricaoRepository(BaseRepository): + """ + Repositório para a operação de busca de um registro na tabela + g_medida_tipo por descrição. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoDescricaoSchema): + """ + Executa a consulta SQL para buscar um registro pela descrição. + + Args: + medida_tipo_schema (GMedidaTipoDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + Um dicionário contendo os dados do registro ou None se não for encontrado. + """ + # Montagem do SQL + sql = """ SELECT * FROM G_MEDIDA_TIPO WHERE DESCRICAO = :descricao """ + + # Preenchimento de parâmetros + params = { + 'descricao': medida_tipo_schema.descricao + } + + # Execução do sql + return self.fetch_one(sql, params) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_index_repository.py b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_index_repository.py new file mode 100644 index 0000000..abc537e --- /dev/null +++ b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_index_repository.py @@ -0,0 +1,23 @@ +from abstracts.repository import BaseRepository + +class IndexRepository(BaseRepository): + """ + Repositório para a operação de listagem de todos os registros + na tabela g_medida_tipo. + """ + + def execute(self): + """ + Executa a consulta SQL para buscar todos os registros. + + Returns: + Uma lista de dicionários contendo os dados dos registros. + """ + # Montagem do SQL + sql = """ SELECT * FROM G_MEDIDA_TIPO """ + + # Execução do sql + response = self.fetch_all(sql) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_save_repository.py b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_save_repository.py new file mode 100644 index 0000000..c189e21 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_save_repository.py @@ -0,0 +1,53 @@ +from fastapi import HTTPException, status +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoSaveSchema + + +class SaveRepository(BaseRepository): + """ + Repositório para a operação de salvamento de um novo registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoSaveSchema): + """ + Executa a operação de salvamento no banco de dados. + + Args: + medida_tipo_schema (GMedidaTipoSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O registro recém-criado. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + + # Montagem do SQL + sql = """ INSERT INTO G_MEDIDA_TIPO( + MEDIDA_TIPO_ID, + DESCRICAO, + SIGLA + ) VALUES ( + :medida_tipo_id, + :descricao, + :sigla + ) RETURNING *;""" + + # Preenchimento de parâmetros + params = { + 'medida_tipo_id': medida_tipo_schema.medida_tipo_id, + 'descricao': medida_tipo_schema.descricao, + 'sigla': medida_tipo_schema.sigla + } + + # Execução do sql + return self.run_and_return(sql, params) + + except Exception as e: + + # Informa que houve uma falha no salvamento do registro + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao salvar G_MEDIDA_TIPO: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_show_repository.py b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_show_repository.py new file mode 100644 index 0000000..6d4427e --- /dev/null +++ b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_show_repository.py @@ -0,0 +1,46 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema +from fastapi import HTTPException, status + +class ShowRepository(BaseRepository): + """ + Repositório para a operação de exibição de um registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoIdSchema): + """ + Busca um registro específico de G_MEDIDA_TIPO pelo ID. + + Args: + medida_tipo_schema (GMedidaTipoIdSchema): O esquema que contém o ID do registro. + + Returns: + O registro encontrado ou None se não existir. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + # Montagem do SQL + sql = "SELECT * FROM G_MEDIDA_TIPO WHERE MEDIDA_TIPO_ID = :medida_tipo_id" + + # Preenchimento de parâmetros + params = { + 'medida_tipo_id': medida_tipo_schema.medida_tipo_id + } + + # Execução do SQL + result = self.fetch_one(sql, params) + + if not result: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Registro não encontrado" + ) + + return result + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Erro ao buscar registro: {str(e)}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_update_repository.py b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_update_repository.py new file mode 100644 index 0000000..a2e9185 --- /dev/null +++ b/packages/v1/administrativo/repositories/g_medida_tipo/g_medida_tipo_update_repository.py @@ -0,0 +1,50 @@ +from fastapi import HTTPException, status +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoUpdateSchema + + +class UpdateRepository(BaseRepository): + """ + Repositório para a operação de atualização de um registro na tabela + g_medida_tipo. + """ + + def execute(self, medida_tipo_id: int, medida_tipo_schema: GMedidaTipoUpdateSchema): + """ + Executa a operação de atualização no banco de dados. + + Args: + medida_tipo_id (int): O ID do registro a ser atualizado. + medida_tipo_schema (GMedidaTipoUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O registro atualizado. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + # Montagem do SQL + sql = """ UPDATE G_MEDIDA_TIPO SET + DESCRICAO = :descricao, + SIGLA = :sigla + WHERE MEDIDA_TIPO_ID = :medida_tipo_id + RETURNING *;""" + + # Preenchimento de parâmetros + params = { + 'descricao': medida_tipo_schema.descricao, + 'sigla': medida_tipo_schema.sigla, + 'medida_tipo_id': medida_tipo_id + } + + # Execução do sql + return self.run_and_return(sql, params) + + except Exception as e: + + # Informa que houve uma falha na atualização do registro + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao atualizar G_MEDIDA_TIPO: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/schemas/g_medida_tipo_schema.py b/packages/v1/administrativo/schemas/g_medida_tipo_schema.py new file mode 100644 index 0000000..ad7a0e6 --- /dev/null +++ b/packages/v1/administrativo/schemas/g_medida_tipo_schema.py @@ -0,0 +1,97 @@ +from pydantic import BaseModel, field_validator, model_validator +from fastapi import HTTPException, status +from typing import Optional + +# Funções para sanitização de entradas (evitar XSS, SQLi etc.) +from actions.validations.text import Text + +# ---------------------------------------------------- +# Schema base +# ---------------------------------------------------- +class GMedidaTipoSchema(BaseModel): + medida_tipo_id: Optional[int] = None + descricao: Optional[str] = None + sigla: Optional[str] = None + + class Config: + from_attributes = True + + +# ---------------------------------------------------- +# Schema para localizar um G_MEDIDA_TIPO especifico pelo ID (GET) +# ---------------------------------------------------- +class GMedidaTipoIdSchema(BaseModel): + medida_tipo_id: int + + +# ---------------------------------------------------- +# Schema para localizar um G_MEDIDA_TIPO especifico pela descrição (GET) +# ---------------------------------------------------- +class GMedidaTipoDescricaoSchema(BaseModel): + descricao: str + + +# ---------------------------------------------------- +# Schema para criação de novo G_MEDIDA_TIPO (POST) +# ---------------------------------------------------- +class GMedidaTipoSaveSchema(BaseModel): + medida_tipo_id: Optional[int] = None + descricao: str + sigla: str + + # Sanitiza os inputs enviados + @field_validator('descricao', 'sigla') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + if not self.descricao or len(self.descricao.strip()) == 0: + errors.append({'input': 'descricao', 'message': 'A descrição é obrigatória.'}) + + if not self.sigla or len(self.sigla.strip()) == 0: + errors.append({'input': 'sigla', 'message': 'A sigla é obrigatória.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self + + +# ---------------------------------------------------- +# Schema para atualizar G_MEDIDA_TIPO (PUT) +# ---------------------------------------------------- +class GMedidaTipoUpdateSchema(BaseModel): + + descricao: Optional[str] = None + sigla: Optional[str] = None + + # Sanitiza os inputs enviados + @field_validator('descricao', 'sigla') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + if not self.descricao and not self.sigla: + errors.append({'input': 'all', 'message': 'É necessário informar ao menos um campo para alteração.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_delete_service.py b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_delete_service.py new file mode 100644 index 0000000..8f8d872 --- /dev/null +++ b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_delete_service.py @@ -0,0 +1,27 @@ +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema +from packages.v1.administrativo.actions.g_medida_tipo.g_medida_tipo_delete_action import DeleteAction + +class DeleteService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoIdSchema): + """ + Executa a operação de exclusão do registro no banco de dados. + + Args: + medida_tipo_schema (GMedidaTipoIdSchema): O esquema com o ID do registro a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento da ação + delete_action = DeleteAction() + + # Executa a ação em questão + data = delete_action.execute(medida_tipo_schema) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_get_descricao_service.py b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_get_descricao_service.py new file mode 100644 index 0000000..c9ea280 --- /dev/null +++ b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_get_descricao_service.py @@ -0,0 +1,38 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoDescricaoSchema +from packages.v1.administrativo.actions.g_medida_tipo.g_medida_tipo_get_by_descricao_action import GetByDescricaoAction + +class GetByDescricaoService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela g_medida_tipo pela sua descrição. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoDescricaoSchema, messageValidate: bool): + """ + Executa a operação de busca no banco de dados. + + Args: + medida_tipo_schema (GMedidaTipoDescricaoSchema): O esquema com a descrição a ser buscada. + messageValidate (bool): Se True, lança uma exceção HTTP caso o registro não seja encontrado. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento da ação + show_action = GetByDescricaoAction() + + # Executa a ação em questão + data = show_action.execute(medida_tipo_schema) + + if messageValidate: + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de G_MEDIDA_TIPO' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_index_service.py b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_index_service.py new file mode 100644 index 0000000..a3c7c5c --- /dev/null +++ b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_index_service.py @@ -0,0 +1,32 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.actions.g_medida_tipo.g_medida_tipo_index_action import IndexAction + +class IndexService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de registros na tabela g_medida_tipo. + """ + + def execute(self): + """ + Executa a operação de busca de todos os registros no banco de dados. + + Returns: + A lista de registros encontrados. + """ + # Instanciamento da ação + index_action = IndexAction() + + # Executa a busca de todas as ações + data = index_action.execute() + + # Verifica se foram localizados registros + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar os registros de G_MEDIDA_TIPO' + ) + + # Retorna as informações localizadas + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_save_service.py b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_save_service.py new file mode 100644 index 0000000..6d9f7b0 --- /dev/null +++ b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_save_service.py @@ -0,0 +1,70 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from packages.v1.sequencia.services.g_sequencia.generate_service import GenerateService +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoSaveSchema, GMedidaTipoDescricaoSchema +from packages.v1.administrativo.actions.g_medida_tipo.g_medida_tipo_save_action import SaveAction +from fastapi import HTTPException, status + +class SaveService: + + def __init__(self): + # Ação responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("g_medida_tipo") + pass + + # Cadastra o novo G_MEDIDA_TIPO + def execute(self, medida_tipo_schema: GMedidaTipoSaveSchema): + + # Armazena possíveis erros + errors = [] + + # Verifica se a descrição já está sendo utilizada + # Importação de service + descricao_service = self.dynamic_import.service("g_medida_tipo_get_descricao_service", "GetByDescricaoService") + + # Instanciamento da service + self.descricao_service = descricao_service() + + # Verifica se a descrição já está sendo utilizada + self.response = self.descricao_service.execute(GMedidaTipoDescricaoSchema(descricao=medida_tipo_schema.descricao), False) + + # Se houver retorno significa que a descrição já está sendo utilizada + if self.response: + errors.append({'input': 'descricao', 'message': 'a descrição informada já está sendo utilizada.'}) + + # Se houver erros, lança a exceção + if errors: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=errors + ) + + # Verifica se precisa gerar o ID de sequência + if not medida_tipo_schema.medida_tipo_id: + + # Crio um objeto de sequencia + sequencia_schema = GSequenciaSchema() + + # Define os dados para atualizar a sequencia + sequencia_schema.tabela = 'G_MEDIDA_TIPO' + + # Busco a sequência atualizada + generate = GenerateService() + + # Busco a sequência atualizada + sequencia = generate.execute(sequencia_schema) + + # Atualiza os dados da chave primária + medida_tipo_schema.medida_tipo_id = sequencia.sequencia + + # Instanciamento de ações + save_action = SaveAction() + + # Retorna o resultado da operação + return save_action.execute(medida_tipo_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_show_service.py b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_show_service.py new file mode 100644 index 0000000..612c491 --- /dev/null +++ b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_show_service.py @@ -0,0 +1,35 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema +from packages.v1.administrativo.actions.g_medida_tipo.g_medida_tipo_show_action import ShowAction + +class ShowService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela g_medida_tipo. + """ + + def execute(self, medida_tipo_schema: GMedidaTipoIdSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + medida_tipo_schema (GMedidaTipoIdSchema): O esquema com o ID a ser buscado. + + Returns: + O resultado da busca. + """ + # Instanciamento da ação + show_action = ShowAction() + + # Executa a ação em questão + data = show_action.execute(medida_tipo_schema) + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de G_MEDIDA_TIPO' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_update_service.py b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_update_service.py new file mode 100644 index 0000000..29c824b --- /dev/null +++ b/packages/v1/administrativo/services/g_medida_tipo/go/g_medida_tipo_update_service.py @@ -0,0 +1,23 @@ +from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoUpdateSchema +from packages.v1.administrativo.actions.g_medida_tipo.g_medida_tipo_update_action import UpdateAction + +class UpdateService: + """ + Serviço para a operação de atualização de um registro na tabela + g_medida_tipo. + """ + def execute(self, medida_tipo_id : int, medida_tipo_schema: GMedidaTipoUpdateSchema): + """ + Executa a operação de atualização no banco de dados. + + Args: + medida_tipo_schema (GMedidaTipoUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instanciamento de ações + update_action = UpdateAction() + + # Retorna o resultado da operação + return update_action.execute(medida_tipo_id, medida_tipo_schema) \ No newline at end of file diff --git a/packages/v1/api.py b/packages/v1/api.py index 66d34d2..a4c9930 100644 --- a/packages/v1/api.py +++ b/packages/v1/api.py @@ -15,6 +15,7 @@ from packages.v1.administrativo.endpoints import t_censec_endpoint from packages.v1.administrativo.endpoints import t_censec_naturezalitigio_endpoint from packages.v1.administrativo.endpoints import t_censec_qualidade_endpoint from packages.v1.administrativo.endpoints import g_tb_estadocivil_endpoint +from packages.v1.administrativo.endpoints import g_medida_tipo_endpoint # Cria uma instância do APIRouter que vai agregar todas as rotas da API api_router = APIRouter() @@ -85,4 +86,9 @@ api_router.include_router( # Inclui as rotas de g_tb_estadocivil api_router.include_router( g_tb_estadocivil_endpoint.router, prefix="/administrativo/g_tb_estadocivil", tags=["Estado Civil"] +) + +# Inclui as rotas de g_tg_medida_tipob_estadocivil +api_router.include_router( + g_medida_tipo_endpoint.router, prefix="/administrativo/g_medida_tipo", tags=["Tipo de Medidas"] ) \ No newline at end of file From 98b4425c9ad4b7c9a8d541bc921c25887f4a387f Mon Sep 17 00:00:00 2001 From: Kenio de Souza Date: Mon, 22 Sep 2025 16:30:23 -0300 Subject: [PATCH 2/2] [MVPTN-13] feat(CRUD): Crud completo da tabela t_minuta --- .../t_minuta/t_minuta_delete_action.py | 26 ++++ .../t_minuta_get_by_descricao_action.py | 29 ++++ .../actions/t_minuta/t_minuta_index_action.py | 24 ++++ .../actions/t_minuta/t_minuta_save_action.py | 28 ++++ .../actions/t_minuta/t_minuta_show_action.py | 28 ++++ .../t_minuta/t_minuta_update_action.py | 27 ++++ .../controllers/t_minuta_controller.py | 111 +++++++++++++++ .../endpoints/t_minuta_endpoint.py | 103 ++++++++++++++ .../t_minuta/t_minuta_delete_repository.py | 41 ++++++ .../t_minuta_get_by_descricao_repository.py | 35 +++++ .../t_minuta/t_minuta_index_repository.py | 29 ++++ .../t_minuta/t_minuta_save_repository.py | 65 +++++++++ .../t_minuta/t_minuta_show_repository.py | 46 ++++++ .../t_minuta/t_minuta_update_repository.py | 77 ++++++++++ .../administrativo/schemas/t_minuta_schema.py | 132 ++++++++++++++++++ .../t_minuta/go/t_minuta_delete_service.py | 27 ++++ .../go/t_minuta_get_descricao_service.py | 38 +++++ .../t_minuta/go/t_minuta_index_service.py | 32 +++++ .../t_minuta/go/t_minuta_save_service.py | 70 ++++++++++ .../t_minuta/go/t_minuta_show_service.py | 35 +++++ .../t_minuta/go/t_minuta_update_service.py | 23 +++ packages/v1/api.py | 6 + 22 files changed, 1032 insertions(+) create mode 100644 packages/v1/administrativo/actions/t_minuta/t_minuta_delete_action.py create mode 100644 packages/v1/administrativo/actions/t_minuta/t_minuta_get_by_descricao_action.py create mode 100644 packages/v1/administrativo/actions/t_minuta/t_minuta_index_action.py create mode 100644 packages/v1/administrativo/actions/t_minuta/t_minuta_save_action.py create mode 100644 packages/v1/administrativo/actions/t_minuta/t_minuta_show_action.py create mode 100644 packages/v1/administrativo/actions/t_minuta/t_minuta_update_action.py create mode 100644 packages/v1/administrativo/controllers/t_minuta_controller.py create mode 100644 packages/v1/administrativo/endpoints/t_minuta_endpoint.py create mode 100644 packages/v1/administrativo/repositories/t_minuta/t_minuta_delete_repository.py create mode 100644 packages/v1/administrativo/repositories/t_minuta/t_minuta_get_by_descricao_repository.py create mode 100644 packages/v1/administrativo/repositories/t_minuta/t_minuta_index_repository.py create mode 100644 packages/v1/administrativo/repositories/t_minuta/t_minuta_save_repository.py create mode 100644 packages/v1/administrativo/repositories/t_minuta/t_minuta_show_repository.py create mode 100644 packages/v1/administrativo/repositories/t_minuta/t_minuta_update_repository.py create mode 100644 packages/v1/administrativo/schemas/t_minuta_schema.py create mode 100644 packages/v1/administrativo/services/t_minuta/go/t_minuta_delete_service.py create mode 100644 packages/v1/administrativo/services/t_minuta/go/t_minuta_get_descricao_service.py create mode 100644 packages/v1/administrativo/services/t_minuta/go/t_minuta_index_service.py create mode 100644 packages/v1/administrativo/services/t_minuta/go/t_minuta_save_service.py create mode 100644 packages/v1/administrativo/services/t_minuta/go/t_minuta_show_service.py create mode 100644 packages/v1/administrativo/services/t_minuta/go/t_minuta_update_service.py diff --git a/packages/v1/administrativo/actions/t_minuta/t_minuta_delete_action.py b/packages/v1/administrativo/actions/t_minuta/t_minuta_delete_action.py new file mode 100644 index 0000000..8ee03ac --- /dev/null +++ b/packages/v1/administrativo/actions/t_minuta/t_minuta_delete_action.py @@ -0,0 +1,26 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaIdSchema +from packages.v1.administrativo.repositories.t_minuta.t_minuta_delete_repository import DeleteRepository + + +class DeleteAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela t_minuta. + """ + + def execute(self, minuta_schema: TMinutaIdSchema): + """ + Executa a operação de exclusão no banco de dados. + + Args: + minuta_schema (TMinutaIdSchema): O esquema com o ID a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento do repositório + delete_repository = DeleteRepository() + + # Execução do repositório + return delete_repository.execute(minuta_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/actions/t_minuta/t_minuta_get_by_descricao_action.py b/packages/v1/administrativo/actions/t_minuta/t_minuta_get_by_descricao_action.py new file mode 100644 index 0000000..5306e15 --- /dev/null +++ b/packages/v1/administrativo/actions/t_minuta/t_minuta_get_by_descricao_action.py @@ -0,0 +1,29 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaDescricaoSchema +from packages.v1.administrativo.repositories.t_minuta.t_minuta_get_by_descricao_repository import GetByDescricaoRepository + + +class GetByDescricaoAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela t_minuta por descrição. + """ + + def execute(self, minuta_schema: TMinutaDescricaoSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + minuta_schema (TMinutaDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento do repositório + show_repository = GetByDescricaoRepository() + + # Execução do repositório + response = show_repository.execute(minuta_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/t_minuta/t_minuta_index_action.py b/packages/v1/administrativo/actions/t_minuta/t_minuta_index_action.py new file mode 100644 index 0000000..177f96b --- /dev/null +++ b/packages/v1/administrativo/actions/t_minuta/t_minuta_index_action.py @@ -0,0 +1,24 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.repositories.t_minuta.t_minuta_index_repository import IndexRepository + +class IndexAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de todos os registros na tabela t_minuta. + """ + + def execute(self): + """ + Executa a operação de listagem no banco de dados. + + Returns: + A lista de todos os registros. + """ + # Instanciamento do repositório + index_repository = IndexRepository() + + # Execução do repositório + response = index_repository.execute() + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/t_minuta/t_minuta_save_action.py b/packages/v1/administrativo/actions/t_minuta/t_minuta_save_action.py new file mode 100644 index 0000000..6166d51 --- /dev/null +++ b/packages/v1/administrativo/actions/t_minuta/t_minuta_save_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaSaveSchema +from packages.v1.administrativo.repositories.t_minuta.t_minuta_save_repository import SaveRepository + +class SaveAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de salvar um novo registro na tabela t_minuta. + """ + + def execute(self, minuta_schema: TMinutaSaveSchema): + """ + Executa a operação de salvamento. + + Args: + minuta_schema (TMinutaSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O resultado da operação de salvamento. + """ + # Instanciamento do repositório + save_repository = SaveRepository() + + # Execução do repositório + response = save_repository.execute(minuta_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/t_minuta/t_minuta_show_action.py b/packages/v1/administrativo/actions/t_minuta/t_minuta_show_action.py new file mode 100644 index 0000000..07a22f9 --- /dev/null +++ b/packages/v1/administrativo/actions/t_minuta/t_minuta_show_action.py @@ -0,0 +1,28 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaIdSchema +from packages.v1.administrativo.repositories.t_minuta.t_minuta_show_repository import ShowRepository + +class ShowAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a exibição + de um registro na tabela t_minuta. + """ + + def execute(self, minuta_schema: TMinutaIdSchema): + """ + Executa a operação de exibição. + + Args: + minuta_schema (TMinutaIdSchema): O esquema com o ID do registro a ser exibido. + + Returns: + O resultado da operação de exibição. + """ + # Instânciamento do repositório + show_repository = ShowRepository() + + # Execução do repositório + response = show_repository.execute(minuta_schema) + + # Retorno da informação + return response \ No newline at end of file diff --git a/packages/v1/administrativo/actions/t_minuta/t_minuta_update_action.py b/packages/v1/administrativo/actions/t_minuta/t_minuta_update_action.py new file mode 100644 index 0000000..3b8baed --- /dev/null +++ b/packages/v1/administrativo/actions/t_minuta/t_minuta_update_action.py @@ -0,0 +1,27 @@ +from abstracts.action import BaseAction +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaUpdateSchema +from packages.v1.administrativo.repositories.t_minuta.t_minuta_update_repository import UpdateRepository + + +class UpdateAction(BaseAction): + """ + Serviço responsável por encapsular a lógica de negócio para a atualização + de um registro na tabela t_minuta. + """ + + def execute(self, minuta_id: int, minuta_schema: TMinutaUpdateSchema): + """ + Executa a operação de atualização. + + Args: + minuta_id (int): O ID do registro a ser atualizado. + minuta_schema (TMinutaUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instância o repositório de atualização + update_repository = UpdateRepository() + + # Chama o método de execução do repositório para realizar a atualização + return update_repository.execute(minuta_id, minuta_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/controllers/t_minuta_controller.py b/packages/v1/administrativo/controllers/t_minuta_controller.py new file mode 100644 index 0000000..f6f88e6 --- /dev/null +++ b/packages/v1/administrativo/controllers/t_minuta_controller.py @@ -0,0 +1,111 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.administrativo.schemas.t_minuta_schema import ( + TMinutaSchema, + TMinutaSaveSchema, + TMinutaUpdateSchema, + TMinutaIdSchema, + TMinutaDescricaoSchema +) + +class TMinutaController: + + def __init__(self): + # Action responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("t_minuta") + pass + + # Lista todos os registros de minuta + def index(self): + + # Importação da classe desejada + indexService = self.dynamic_import.service("t_minuta_index_service", "IndexService") + + # Instância da classe service + self.indexService = indexService() + + # Lista todos os registros de minuta + return { + 'message': 'Registros de minuta localizados com sucesso', + 'data': self.indexService.execute() + } + + + # Busca um registro de minuta específico pelo ID + def show(self, minuta_schema: TMinutaIdSchema): + + #Importação da classe desejada + show_service = self.dynamic_import.service('t_minuta_show_service', 'ShowService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de minuta desejado + return { + 'message': 'Registro de minuta localizado com sucesso', + 'data': self.show_service.execute(minuta_schema) + } + + # Busca um registro de minuta específico pela descrição + def get_by_descricao(self, descricao: str): + + #Importação da classe desejada + show_service = self.dynamic_import.service('t_minuta_get_descricao_service', 'GetByDescricaoService') + + # Instância da classe desejada + self.show_service = show_service() + + # Busca e retorna o registro de minuta desejado + return { + 'message': 'Registro de minuta localizado com sucesso', + 'data': self.show_service.execute(TMinutaDescricaoSchema(descricao=descricao), True) + } + + # Cadastra um novo registro de minuta + def save(self, minuta_schema: TMinutaSaveSchema): + + #Importação da classe desejada + save_service = self.dynamic_import.service('t_minuta_save_service', 'SaveService') + + # Instância da classe desejada + self.save_service = save_service() + # Busca e retorna o registro de minuta desejado + return { + 'message': 'Registro de minuta salvo com sucesso', + 'data': self.save_service.execute(minuta_schema) + } + + # Atualiza os dados de um registro de minuta + def update(self, minuta_id: int, minuta_schema: TMinutaUpdateSchema): + + #Importação da classe desejada + update_service = self.dynamic_import.service('t_minuta_update_service', 'UpdateService') + + # Instância da classe desejada + self.update_service = update_service() + + # Busca e retorna o registro de minuta desejado + return { + 'message': 'Registro de minuta atualizado com sucesso', + 'data': self.update_service.execute(minuta_id, minuta_schema) + } + + # Exclui um registro de minuta + def delete(self, minuta_schema: TMinutaIdSchema): + + #Importação da classe desejada + delete_service = self.dynamic_import.service('t_minuta_delete_service', 'DeleteService') + + # Instância da classe desejada + self.delete_service = delete_service() + + # Busca e retorna o registro de minuta desejado + return { + 'message': 'Registro de minuta removido com sucesso', + 'data': self.delete_service.execute(minuta_schema) + } \ No newline at end of file diff --git a/packages/v1/administrativo/endpoints/t_minuta_endpoint.py b/packages/v1/administrativo/endpoints/t_minuta_endpoint.py new file mode 100644 index 0000000..03a463f --- /dev/null +++ b/packages/v1/administrativo/endpoints/t_minuta_endpoint.py @@ -0,0 +1,103 @@ +# Importação de bibliotecas +from typing import Optional +from fastapi import APIRouter, Body, Depends, status +from actions.jwt.get_current_user import get_current_user +from packages.v1.administrativo.controllers.t_minuta_controller import TMinutaController +from packages.v1.administrativo.schemas.t_minuta_schema import ( + TMinutaSchema, + TMinutaSaveSchema, + TMinutaUpdateSchema, + TMinutaIdSchema, + TMinutaDescricaoSchema +) + +# Inicializa o roteador para as rotas do tipo de reconhecimento +router = APIRouter() + +# Instanciamento do controller desejado +t_minuta_controller = TMinutaController() + +# Lista todos os registros de minuta +@router.get('/', + status_code=status.HTTP_200_OK, + summary='Lista todos os registros de minuta cadastrados', + response_description='Lista todos os registros de minuta cadastrados') +async def index(current_user: dict = Depends(get_current_user)): + + # Busca todos os registros de minuta cadastrados + response = t_minuta_controller.index() + + # Retorna os dados localizados + return response + + +# Localiza um registro de minuta pela descrição +@router.get('/descricao', + status_code=status.HTTP_200_OK, + summary='Busca um registro de minuta em específico pela descrição', + response_description='Busca um registro de minuta em específico') +async def get_by_descricao(descricao : str, current_user: dict = Depends(get_current_user)): + + # Efetua a busca por descrição + response = t_minuta_controller.get_by_descricao(descricao) + + # Retorna os dados localizados + return response + + +# Localiza um registro de minuta pelo ID +@router.get('/{minuta_id}', + status_code=status.HTTP_200_OK, + summary='Busca um registro de minuta em específico pelo ID', + response_description='Busca um registro de minuta em específico') +async def show(minuta_id: int, current_user: dict = Depends(get_current_user)): + + # Efetua a busca por ID + response = t_minuta_controller.show(TMinutaIdSchema(minuta_id=minuta_id)) + + # Retorna os dados localizados + return response + + +# Cadastra um registro de minuta +@router.post('/', + status_code=status.HTTP_201_CREATED, + summary='Cadastra um registro de minuta', + response_description='Cadastra um registro de minuta') +async def save(minuta_schema: TMinutaSaveSchema, current_user: dict = Depends(get_current_user)): + + # Efetua o cadastro no banco de dados + response = t_minuta_controller.save(minuta_schema) + + # Retorna os dados localizados + return response + + +# Atualiza os dados de um registro de minuta +@router.put('/{minuta_id}', + status_code=status.HTTP_200_OK, + summary='Atualiza um registro de minuta', + response_description='Atualiza um registro de minuta') +async def update(minuta_id: int, minuta_schema: TMinutaUpdateSchema, current_user: dict = Depends(get_current_user)): + + # Efetua a atualização dos dados + response = t_minuta_controller.update(minuta_id, minuta_schema) + + # Retorna os dados localizados + return response + +# Exclui um determinado registro de minuta +@router.delete('/{minuta_id}', + status_code=status.HTTP_200_OK, + summary='Remove um registro de minuta', + response_description='Remove um registro de minuta') +async def delete(minuta_id: int, current_user: dict = Depends(get_current_user)): + + # Cria o schema com os dados recebidos + minuta_schema = TMinutaIdSchema(minuta_id=minuta_id) + + # Efetua a exclusão do registro + response = t_minuta_controller.delete(minuta_schema) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/t_minuta/t_minuta_delete_repository.py b/packages/v1/administrativo/repositories/t_minuta/t_minuta_delete_repository.py new file mode 100644 index 0000000..a2a80a5 --- /dev/null +++ b/packages/v1/administrativo/repositories/t_minuta/t_minuta_delete_repository.py @@ -0,0 +1,41 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaIdSchema +from fastapi import HTTPException, status + +class DeleteRepository(BaseRepository): + """ + Repositório para a operação de exclusão de um registro na tabela + t_minuta. + """ + + def execute(self, minuta_schema: TMinutaIdSchema): + """ + Executa a consulta SQL para remover um registro pelo ID. + + Args: + minuta_schema (TMinutaIdSchema): O esquema com o ID a ser removido. + + Returns: + O resultado da operação de exclusão. + """ + try: + # Montagem do sql + sql = """ DELETE FROM T_MINUTA WHERE MINUTA_ID = :minuta_id """ + + # Preenchimento de parâmetros + params = { + "minuta_id": minuta_schema.minuta_id + } + + # Execução do sql + response = self.run(sql, params) + + # Retorna o resultado + return response + + except Exception as e: + # Informa que houve uma falha na exclusão + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao excluir MINUTA: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/t_minuta/t_minuta_get_by_descricao_repository.py b/packages/v1/administrativo/repositories/t_minuta/t_minuta_get_by_descricao_repository.py new file mode 100644 index 0000000..e4a9c74 --- /dev/null +++ b/packages/v1/administrativo/repositories/t_minuta/t_minuta_get_by_descricao_repository.py @@ -0,0 +1,35 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaDescricaoSchema + +class GetByDescricaoRepository(BaseRepository): + """ + Repositório para a operação de busca de um registro na tabela + t_minuta por descrição. + """ + + def execute(self, minuta_schema: TMinutaDescricaoSchema): + """ + Executa a consulta SQL para buscar um registro pela descrição. + + Args: + minuta_schema (TMinutaDescricaoSchema): O esquema com a descrição a ser buscada. + + Returns: + Um dicionário contendo os dados do registro ou None se não for encontrado. + """ + # Montagem do SQL + sql = """ SELECT MINUTA_ID, + ATO_TIPO_ID, + NATUREZA_ID, + DESCRICAO, + PROTEGIDA, + SITUACAO + FROM T_MINUTA WHERE DESCRICAO = :descricao """ + + # Preenchimento de parâmetros + params = { + 'descricao': minuta_schema.descricao + } + + # Execução do sql + return self.fetch_one(sql, params) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/t_minuta/t_minuta_index_repository.py b/packages/v1/administrativo/repositories/t_minuta/t_minuta_index_repository.py new file mode 100644 index 0000000..e65a230 --- /dev/null +++ b/packages/v1/administrativo/repositories/t_minuta/t_minuta_index_repository.py @@ -0,0 +1,29 @@ +from abstracts.repository import BaseRepository + +class IndexRepository(BaseRepository): + """ + Repositório para a operação de listagem de todos os registros + na tabela t_minuta. + """ + + def execute(self): + """ + Executa a consulta SQL para buscar todos os registros. + + Returns: + Uma lista de dicionários contendo os dados dos registros. + """ + # Montagem do SQL + sql = """ SELECT MINUTA_ID, + ATO_TIPO_ID, + NATUREZA_ID, + DESCRICAO, + PROTEGIDA, + SITUACAO + FROM T_MINUTA """ + + # Execução do sql + response = self.fetch_all(sql) + + # Retorna os dados localizados + return response \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/t_minuta/t_minuta_save_repository.py b/packages/v1/administrativo/repositories/t_minuta/t_minuta_save_repository.py new file mode 100644 index 0000000..9cd817f --- /dev/null +++ b/packages/v1/administrativo/repositories/t_minuta/t_minuta_save_repository.py @@ -0,0 +1,65 @@ +from fastapi import HTTPException, status +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaSaveSchema + + +class SaveRepository(BaseRepository): + """ + Repositório para a operação de salvamento de um novo registro na tabela t_minuta. + """ + + def execute(self, minuta_schema: TMinutaSaveSchema): + """ + Executa a operação de salvamento no banco de dados. + + Args: + minuta_schema (TMinutaSaveSchema): O esquema com os dados a serem salvos. + + Returns: + O registro recém-criado. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + + # Montagem do SQL + sql = """ INSERT INTO T_MINUTA( + MINUTA_ID, + ATO_TIPO_ID, + NATUREZA_ID, + DESCRICAO, + TEXTO, + PROTEGIDA, + SITUACAO + ) VALUES ( + :minuta_id, + :ato_tipo_id, + :natureza_id, + :descricao, + :texto, + :protegida, + :situacao + ) RETURNING *;""" + + # Preenchimento de parâmetros + params = { + 'minuta_id': minuta_schema.minuta_id, + 'ato_tipo_id': minuta_schema.ato_tipo_id, + 'natureza_id': minuta_schema.natureza_id, + 'descricao': minuta_schema.descricao, + 'texto': minuta_schema.texto, + 'protegida': minuta_schema.protegida, + 'situacao': minuta_schema.situacao + } + + # Execução do sql + return self.run_and_return(sql, params) + + except Exception as e: + + # Informa que houve uma falha no salvamento do registro + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao salvar MINUTA: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/t_minuta/t_minuta_show_repository.py b/packages/v1/administrativo/repositories/t_minuta/t_minuta_show_repository.py new file mode 100644 index 0000000..fc3caf5 --- /dev/null +++ b/packages/v1/administrativo/repositories/t_minuta/t_minuta_show_repository.py @@ -0,0 +1,46 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaIdSchema +from fastapi import HTTPException, status + +class ShowRepository(BaseRepository): + """ + Repositório para a operação de exibição de um registro na tabela t_minuta. + """ + + def execute(self, minuta_schema: TMinutaIdSchema): + """ + Busca um registro específico de MINUTA pelo ID. + + Args: + minuta_schema (TMinutaIdSchema): O esquema que contém o ID do registro. + + Returns: + O registro encontrado ou None se não existir. + + Raises: + HTTPException: Caso ocorra um erro na execução da query. + """ + try: + # Montagem do SQL + sql = "SELECT * FROM T_MINUTA WHERE MINUTA_ID = :minuta_id" + + # Preenchimento de parâmetros + params = { + 'minuta_id': minuta_schema.minuta_id + } + + # Execução do SQL + result = self.fetch_one(sql, params) + + if not result: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Registro não encontrado" + ) + + return result + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Erro ao buscar registro: {str(e)}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/repositories/t_minuta/t_minuta_update_repository.py b/packages/v1/administrativo/repositories/t_minuta/t_minuta_update_repository.py new file mode 100644 index 0000000..14ec282 --- /dev/null +++ b/packages/v1/administrativo/repositories/t_minuta/t_minuta_update_repository.py @@ -0,0 +1,77 @@ +from abstracts.repository import BaseRepository +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaUpdateSchema +from fastapi import HTTPException, status + +class UpdateRepository(BaseRepository): + """ + Repositório para a operação de atualização na tabela T_MINUTA. + """ + + def execute(self, minuta_id: int, minuta_schema: TMinutaUpdateSchema): + """ + Executa a atualização de um registro na tabela. + + Args: + minuta_id (int): O ID do registro a ser atualizado. + minuta_schema (TMinutaUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O registro atualizado. + + Raises: + HTTPException: Se o registro não for encontrado ou ocorrer um erro na atualização. + """ + try: + updates = [] + params = {} + + if minuta_schema.ato_tipo_id is not None: + updates.append("ATO_TIPO_ID = :ato_tipo_id") + params["ato_tipo_id"] = minuta_schema.ato_tipo_id + + if minuta_schema.natureza_id is not None: + updates.append("NATUREZA_ID = :natureza_id") + params["natureza_id"] = minuta_schema.natureza_id + + if minuta_schema.descricao is not None: + updates.append("DESCRICAO = :descricao") + params["descricao"] = minuta_schema.descricao + + if minuta_schema.texto is not None: + updates.append("TEXTO = :texto") + params["texto"] = minuta_schema.texto + + if minuta_schema.protegida is not None: + updates.append("PROTEGIDA = :protegida") + params["protegida"] = minuta_schema.protegida + + if minuta_schema.situacao is not None: + updates.append("SITUACAO = :situacao") + params["situacao"] = minuta_schema.situacao + + if not updates: + return False + + params["minuta_id"] = minuta_id + sql = f"UPDATE T_MINUTA SET {', '.join(updates)} WHERE minuta_id = :minuta_id RETURNING *;" + + # Executa a query + result = self.run_and_return(sql, params) + + if not result.minuta_id: + # Informa que não existe o registro a ser modificado + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail='Nenhuma MINUTA localizada para esta solicitação' + ) + + # Se houver um resultado, a atualização foi bem-sucedida + if result: + return result + + except Exception as e: + # Informa que houve uma falha na atualização + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Erro ao atualizar a MINUTA: {e}" + ) \ No newline at end of file diff --git a/packages/v1/administrativo/schemas/t_minuta_schema.py b/packages/v1/administrativo/schemas/t_minuta_schema.py new file mode 100644 index 0000000..cfba52f --- /dev/null +++ b/packages/v1/administrativo/schemas/t_minuta_schema.py @@ -0,0 +1,132 @@ +from pydantic import BaseModel, field_validator, model_validator +from fastapi import HTTPException, status +from typing import Optional + +# Funções para sanitização de entradas (evitar XSS, SQLi etc.) +from actions.validations.text import Text + +# ---------------------------------------------------- +# Schema base +# ---------------------------------------------------- +class TMinutaSchema(BaseModel): + minuta_id: Optional[int] = None + ato_tipo_id: Optional[int] = None + natureza_id: Optional[int] = None + descricao: Optional[str] = None + texto: Optional[bytes] = None + protegida: Optional[str] = None + situacao: Optional[str] = None + + class Config: + from_attributes = True + + +# ---------------------------------------------------- +# Schema para localizar uma MINUTA especifica pelo ID (GET) +# ---------------------------------------------------- +class TMinutaIdSchema(BaseModel): + minuta_id: int + + +# ---------------------------------------------------- +# Schema para localizar uma MINUTA especifico pela descrição (GET) +# ---------------------------------------------------- +class TMinutaDescricaoSchema(BaseModel): + descricao: str + + +# ---------------------------------------------------- +# Schema para criação de nova MINUTA (POST) +# ---------------------------------------------------- +class TMinutaSaveSchema(BaseModel): + minuta_id: Optional[int] = None + ato_tipo_id: int + natureza_id: int + descricao: str + texto: bytes + protegida: str + situacao: str + + # Sanitiza os inputs enviados + @field_validator('descricao', 'protegida', 'situacao') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Validação para campos BLOB + @field_validator('texto') + def validate_blob(cls, v): + if not isinstance(v, bytes): + raise ValueError('O campo de texto deve ser do tipo bytes.') + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + if not self.ato_tipo_id: + errors.append({'input': 'ato_tipo_id', 'message': 'O tipo de ato é obrigatório.'}) + + if not self.natureza_id: + errors.append({'input': 'natureza_id', 'message': 'A natureza é obrigatória.'}) + + if not self.descricao or len(self.descricao.strip()) == 0: + errors.append({'input': 'descricao', 'message': 'A descrição é obrigatória.'}) + + if not self.texto: + errors.append({'input': 'texto', 'message': 'O texto é obrigatório.'}) + + if not self.protegida or len(self.protegida.strip()) == 0: + errors.append({'input': 'protegida', 'message': 'O campo protegida é obrigatório.'}) + + if not self.situacao or len(self.situacao.strip()) == 0: + errors.append({'input': 'situacao', 'message': 'A situação é obrigatória.'}) + + if errors: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=errors + ) + + return self + + +# ---------------------------------------------------- +# Schema para atualizar MINUTA (PUT) +# ---------------------------------------------------- +class TMinutaUpdateSchema(BaseModel): + ato_tipo_id: Optional[int] = None + natureza_id: Optional[int] = None + descricao: Optional[str] = None + texto: Optional[bytes] = None + protegida: Optional[str] = None + situacao: Optional[str] = None + + # Sanitiza os inputs enviados + @field_validator('descricao', 'protegida', 'situacao') + def sanitize_fields(cls, v): + if v: + return Text.sanitize_input(v) + return v + + # Validação para campos BLOB + @field_validator('texto') + def validate_blob(cls, v): + if not isinstance(v, bytes): + raise ValueError('O campo de texto deve ser do tipo bytes.') + return v + + # Verifica se os campos obrigatórios foram enviados + @model_validator(mode='after') + def validate_all_fields(self): + errors = [] + + if not self.ato_tipo_id and not self.natureza_id and not self.descricao and not self.texto and not self.protegida and not self.situacao: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="Pelo menos um campo deve ser fornecido para a atualização." + ) + + return self \ No newline at end of file diff --git a/packages/v1/administrativo/services/t_minuta/go/t_minuta_delete_service.py b/packages/v1/administrativo/services/t_minuta/go/t_minuta_delete_service.py new file mode 100644 index 0000000..fba1be3 --- /dev/null +++ b/packages/v1/administrativo/services/t_minuta/go/t_minuta_delete_service.py @@ -0,0 +1,27 @@ +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaIdSchema +from packages.v1.administrativo.actions.t_minuta.t_minuta_delete_action import DeleteAction + +class DeleteService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de exclusão de um registro na tabela t_minuta. + """ + + def execute(self, minuta_schema: TMinutaIdSchema): + """ + Executa a operação de exclusão do registro no banco de dados. + + Args: + minuta_schema (TMinutaIdSchema): O esquema com o ID do registro a ser excluído. + + Returns: + O resultado da operação de exclusão. + """ + # Instanciamento da ação + delete_action = DeleteAction() + + # Executa a ação em questão + data = delete_action.execute(minuta_schema) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/t_minuta/go/t_minuta_get_descricao_service.py b/packages/v1/administrativo/services/t_minuta/go/t_minuta_get_descricao_service.py new file mode 100644 index 0000000..f0c205e --- /dev/null +++ b/packages/v1/administrativo/services/t_minuta/go/t_minuta_get_descricao_service.py @@ -0,0 +1,38 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaDescricaoSchema +from packages.v1.administrativo.actions.t_minuta.t_minuta_get_by_descricao_action import GetByDescricaoAction + +class GetByDescricaoService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela t_minuta pela sua descrição. + """ + + def execute(self, minuta_schema: TMinutaDescricaoSchema, messageValidate: bool): + """ + Executa a operação de busca no banco de dados. + + Args: + minuta_schema (TMinutaDescricaoSchema): O esquema com a descrição a ser buscada. + messageValidate (bool): Se True, lança uma exceção HTTP caso o registro não seja encontrado. + + Returns: + O registro encontrado ou None. + """ + # Instanciamento da ação + show_action = GetByDescricaoAction() + + # Executa a ação em questão + data = show_action.execute(minuta_schema) + + if messageValidate: + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de MINUTA' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/t_minuta/go/t_minuta_index_service.py b/packages/v1/administrativo/services/t_minuta/go/t_minuta_index_service.py new file mode 100644 index 0000000..2c1456f --- /dev/null +++ b/packages/v1/administrativo/services/t_minuta/go/t_minuta_index_service.py @@ -0,0 +1,32 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.actions.t_minuta.t_minuta_index_action import IndexAction + +class IndexService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de listagem de registros na tabela t_minuta. + """ + + def execute(self): + """ + Executa a operação de busca de todos os registros no banco de dados. + + Returns: + A lista de registros encontrados. + """ + # Instanciamento da ação + index_action = IndexAction() + + # Executa a busca de todas as ações + data = index_action.execute() + + # Verifica se foram localizados registros + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar os registros de MINUTA' + ) + + # Retorna as informações localizadas + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/t_minuta/go/t_minuta_save_service.py b/packages/v1/administrativo/services/t_minuta/go/t_minuta_save_service.py new file mode 100644 index 0000000..df22d77 --- /dev/null +++ b/packages/v1/administrativo/services/t_minuta/go/t_minuta_save_service.py @@ -0,0 +1,70 @@ +from actions.dynamic_import.dynamic_import import DynamicImport +from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema +from packages.v1.sequencia.services.g_sequencia.generate_service import GenerateService +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaSaveSchema, TMinutaDescricaoSchema +from packages.v1.administrativo.actions.t_minuta.t_minuta_save_action import SaveAction +from fastapi import HTTPException, status + +class SaveService: + + def __init__(self): + # Ação responsável por carregar as services de acordo com o estado + self.dynamic_import = DynamicImport() + + # Define o pacote que deve ser carregado + self.dynamic_import.set_package("administrativo") + + # Define a tabela que o pacote pertence + self.dynamic_import.set_table("t_minuta") + pass + + # Cadastra a nova MINUTA + def execute(self, minuta_schema: TMinutaSaveSchema): + + # Armazena possíveis erros + errors = [] + + # Verifica se a descrição já está sendo utilizada + # Importação de service + descricao_service = self.dynamic_import.service("t_minuta_get_descricao_service", "GetByDescricaoService") + + # Instanciamento da service + self.descricao_service = descricao_service() + + # Verifica se a descrição já está sendo utilizada + self.response = self.descricao_service.execute(TMinutaDescricaoSchema(descricao=minuta_schema.descricao), False) + + # Se houver retorno significa que a descrição já está sendo utilizada + if self.response: + errors.append({'input': 'descricao', 'message': 'a descrição informada já está sendo utilizada.'}) + + # Se houver erros, lança a exceção + if errors: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=errors + ) + + # Verifica se precisa gerar o ID de sequência + if not minuta_schema.minuta_id: + + # Crio um objeto de sequencia + sequencia_schema = GSequenciaSchema() + + # Define os dados para atualizar a sequencia + sequencia_schema.tabela = 'T_MINUTA' + + # Busco a sequência atualizada + generate = GenerateService() + + # Busco a sequência atualizada + sequencia = generate.execute(sequencia_schema) + + # Atualiza os dados da chave primária + minuta_schema.minuta_id = sequencia.sequencia + + # Instanciamento de ações + save_action = SaveAction() + + # Retorna o resultado da operação + return save_action.execute(minuta_schema) \ No newline at end of file diff --git a/packages/v1/administrativo/services/t_minuta/go/t_minuta_show_service.py b/packages/v1/administrativo/services/t_minuta/go/t_minuta_show_service.py new file mode 100644 index 0000000..429343e --- /dev/null +++ b/packages/v1/administrativo/services/t_minuta/go/t_minuta_show_service.py @@ -0,0 +1,35 @@ +from fastapi import HTTPException, status +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaIdSchema +from packages.v1.administrativo.actions.t_minuta.t_minuta_show_action import ShowAction + +class ShowService: + """ + Serviço responsável por encapsular a lógica de negócio para a operação + de busca de um registro na tabela t_minuta. + """ + + def execute(self, minuta_schema: TMinutaIdSchema): + """ + Executa a operação de busca no banco de dados. + + Args: + minuta_schema (TMinutaIdSchema): O esquema com o ID a ser buscado. + + Returns: + O resultado da busca. + """ + # Instanciamento da ação + show_action = ShowAction() + + # Executa a ação em questão + data = show_action.execute(minuta_schema) + + if not data: + # Retorna uma exceção + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail='Não foi possível localizar o registro de MINUTA' + ) + + # Retorno da informação + return data \ No newline at end of file diff --git a/packages/v1/administrativo/services/t_minuta/go/t_minuta_update_service.py b/packages/v1/administrativo/services/t_minuta/go/t_minuta_update_service.py new file mode 100644 index 0000000..b1f17dc --- /dev/null +++ b/packages/v1/administrativo/services/t_minuta/go/t_minuta_update_service.py @@ -0,0 +1,23 @@ +from packages.v1.administrativo.schemas.t_minuta_schema import TMinutaUpdateSchema +from packages.v1.administrativo.actions.t_minuta.t_minuta_update_action import UpdateAction + +class UpdateService: + """ + Serviço para a operação de atualização de um registro na tabela + t_minuta. + """ + def execute(self, minuta_id : int, minuta_schema: TMinutaUpdateSchema): + """ + Executa a operação de atualização no banco de dados. + + Args: + minuta_schema (TMinutaUpdateSchema): O esquema com os dados a serem atualizados. + + Returns: + O resultado da operação de atualização. + """ + # Instanciamento de ações + update_action = UpdateAction() + + # Retorna o resultado da operação + return update_action.execute(minuta_id, minuta_schema) \ No newline at end of file diff --git a/packages/v1/api.py b/packages/v1/api.py index a4c9930..23b2220 100644 --- a/packages/v1/api.py +++ b/packages/v1/api.py @@ -16,6 +16,7 @@ from packages.v1.administrativo.endpoints import t_censec_naturezalitigio_endpoi from packages.v1.administrativo.endpoints import t_censec_qualidade_endpoint from packages.v1.administrativo.endpoints import g_tb_estadocivil_endpoint from packages.v1.administrativo.endpoints import g_medida_tipo_endpoint +from packages.v1.administrativo.endpoints import t_minuta_endpoint # Cria uma instância do APIRouter que vai agregar todas as rotas da API api_router = APIRouter() @@ -91,4 +92,9 @@ api_router.include_router( # Inclui as rotas de g_tg_medida_tipob_estadocivil api_router.include_router( g_medida_tipo_endpoint.router, prefix="/administrativo/g_medida_tipo", tags=["Tipo de Medidas"] +) + +# Inclui as rotas de g_tg_medida_tipob_estadocivil +api_router.include_router( + t_minuta_endpoint.router, prefix="/administrativo/t_minuta", tags=["Minutas"] ) \ No newline at end of file