Ajuste main.py
This commit is contained in:
parent
f8b97d2907
commit
2cd63069be
108 changed files with 5387 additions and 144 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# abstracts/repository.py
|
||||
from sqlalchemy.orm import Session
|
||||
from database.postgres import SessionLocal
|
||||
from database.mysql import SessionLocal
|
||||
|
||||
|
||||
class BaseRepository:
|
||||
|
|
|
|||
|
|
@ -1,20 +1,60 @@
|
|||
import json
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
|
||||
class Config:
|
||||
"""Classe responsável por carregar arquivos JSON e substituir variáveis de ambiente."""
|
||||
|
||||
@staticmethod
|
||||
def _resolve_env_vars(value):
|
||||
"""
|
||||
Substitui placeholders ${VAR} por valores das variáveis de ambiente.
|
||||
Funciona recursivamente para dicionários, listas e strings.
|
||||
"""
|
||||
if isinstance(value, str):
|
||||
# Procura padrões como ${VAR_NAME}
|
||||
pattern = re.compile(r"\$\{([^}^{]+)\}")
|
||||
matches = pattern.findall(value)
|
||||
for var in matches:
|
||||
env_value = os.getenv(var)
|
||||
if env_value is None:
|
||||
raise ValueError(f"Variável de ambiente '{var}' não definida.")
|
||||
value = value.replace(f"${{{var}}}", env_value)
|
||||
return value
|
||||
|
||||
elif isinstance(value, dict):
|
||||
return {k: Config._resolve_env_vars(v) for k, v in value.items()}
|
||||
|
||||
elif isinstance(value, list):
|
||||
return [Config._resolve_env_vars(v) for v in value]
|
||||
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def get(name: str):
|
||||
# Caminho absoluto do arquivo atual
|
||||
"""
|
||||
Carrega um arquivo JSON de configuração e substitui variáveis de ambiente.
|
||||
|
||||
Args:
|
||||
name (str): Nome do arquivo dentro de /config (ex: "database/mysql.json")
|
||||
|
||||
Returns:
|
||||
SimpleNamespace: Objeto com os valores resolvidos acessíveis via ponto.
|
||||
"""
|
||||
base_dir = Path(__file__).resolve().parent
|
||||
config_path = base_dir.parent.parent / "config" / name
|
||||
|
||||
# Caminho absoluto para o config.json (subindo dois níveis e entrando em config/)
|
||||
config_path = base_dir.parent.parent / 'config' / name
|
||||
# Lê o arquivo JSON
|
||||
with open(config_path, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Carrega o JSON como objeto acessível por ponto
|
||||
with open(config_path, 'r') as f:
|
||||
config = json.load(f, object_hook=lambda d: SimpleNamespace(**d))
|
||||
# Substitui variáveis de ambiente
|
||||
resolved_data = Config._resolve_env_vars(data)
|
||||
|
||||
return config
|
||||
# Retorna como objeto acessível por ponto
|
||||
return json.loads(
|
||||
json.dumps(resolved_data), object_hook=lambda d: SimpleNamespace(**d)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from actions.config.config import Config
|
|||
from typing import Optional, Any, Type
|
||||
|
||||
|
||||
|
||||
class DynamicImport:
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
|
@ -18,7 +17,7 @@ class DynamicImport:
|
|||
def set_table(self, table: str):
|
||||
self.table = table
|
||||
|
||||
def service(self, name: str, class_name : str) -> Type[Any]:
|
||||
def service(self, name: str, class_name: str) -> Type[Any]:
|
||||
try:
|
||||
# Define o nome do Módulo
|
||||
module_file = f"{name}"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from passlib.context import CryptContext
|
|||
# Cria uma instância do contexto de criptografia
|
||||
# O esquema usado é 'bcrypt', que é seguro e amplamente aceito
|
||||
# O parâmetro 'deprecated="auto"' marca versões antigas como inseguras, se aplicável
|
||||
CRYPTO = CryptContext(schemes=['bcrypt'], deprecated='auto')
|
||||
CRYPTO = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
|
||||
class Security:
|
||||
|
|
@ -19,9 +19,8 @@ class Security:
|
|||
"""
|
||||
return CRYPTO.identify(senha)
|
||||
|
||||
|
||||
# Verifica se uma senha fornecida corresponde ao hash armazenado
|
||||
def verify_senha_api(plain_senha_api: str, hashed_senha_api: str) -> bool:
|
||||
def verify_password(plain_senha_api: str, hashed_senha_api: str) -> bool:
|
||||
"""
|
||||
Compara a senha fornecida em texto puro com o hash armazenado.
|
||||
|
||||
|
|
@ -31,9 +30,8 @@ class Security:
|
|||
"""
|
||||
return CRYPTO.verify(plain_senha_api, hashed_senha_api)
|
||||
|
||||
|
||||
# Gera o hash de uma senha fornecida
|
||||
def hash_senha_api(plain_senha_api: str) -> str:
|
||||
def hash_password(plain_senha_api: str) -> str:
|
||||
"""
|
||||
Gera e retorna o hash da senha fornecida.
|
||||
|
||||
|
|
|
|||
15
config/database/mysql.json
Normal file
15
config/database/mysql.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"host": "${DB_HOST}",
|
||||
"port": "${DB_PORT}",
|
||||
"name": "${DB_NAME}",
|
||||
"user": "${DB_USER}",
|
||||
"password": "${DB_PASSWORD}",
|
||||
"aeskey": "${AES_KEY}",
|
||||
"charset": "utf8mb4",
|
||||
"pool": {
|
||||
"pre_ping": true,
|
||||
"size": 5,
|
||||
"max_overflow": 10
|
||||
},
|
||||
"debug": false
|
||||
}
|
||||
50
database/mysql.py
Normal file
50
database/mysql.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker, declarative_base
|
||||
from actions.config.config import Config
|
||||
|
||||
# === BASE ORM ===
|
||||
# Essa base é herdada por todos os modelos (tabelas) do SQLAlchemy.
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
def get_database_settings():
|
||||
"""
|
||||
Lê e retorna as configurações do arquivo database/mysql.json,
|
||||
com substituição automática das variáveis de ambiente (${VAR}).
|
||||
"""
|
||||
return Config.get("database/mysql.json")
|
||||
|
||||
|
||||
def get_mysql_engine():
|
||||
"""
|
||||
Cria e retorna a engine de conexão com o banco MySQL.
|
||||
A engine é responsável por gerenciar o pool de conexões.
|
||||
"""
|
||||
db = get_database_settings()
|
||||
|
||||
# === Monta a string DSN (Data Source Name) ===
|
||||
dsn = (
|
||||
f"mysql+pymysql://{db.user}:{db.password}@"
|
||||
f"{db.host}:{db.port}/{db.name}?charset={db.charset}"
|
||||
)
|
||||
|
||||
# === Cria a engine SQLAlchemy ===
|
||||
engine = create_engine(
|
||||
dsn,
|
||||
echo=bool(getattr(db, "debug", False)), # Exibe SQLs no log se habilitado
|
||||
pool_pre_ping=bool(db.pool.pre_ping), # Testa conexões antes de usar
|
||||
pool_size=int(db.pool.size), # Tamanho do pool de conexões
|
||||
max_overflow=int(db.pool.max_overflow), # Conexões extras permitidas
|
||||
connect_args={"connect_timeout": 10}, # Timeout de conexão
|
||||
)
|
||||
|
||||
return engine
|
||||
|
||||
|
||||
# === Engine global ===
|
||||
# Criada uma única vez durante o ciclo de vida da aplicação.
|
||||
engine = get_mysql_engine()
|
||||
|
||||
# === Sessão ORM ===
|
||||
# Cada request da aplicação cria uma instância de SessionLocal.
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
36
main.py
36
main.py
|
|
@ -3,30 +3,36 @@ import os
|
|||
import sys
|
||||
|
||||
# Adiciona o diretório atual (onde está o main.py) ao sys.path
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||
|
||||
# Importa a classe principal do FastAPI
|
||||
from fastapi import FastAPI, Request
|
||||
from pathlib import Path
|
||||
|
||||
# Importa o middleware de CORS
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
# Importa middleware de captura de erros junto ao banco de dados
|
||||
from middlewares.error_handler import database_error_handler
|
||||
|
||||
# Importa o roteador principal da API versão 1
|
||||
from packages.v1.api import api_router
|
||||
from packages.v1.system.service.startup_check_service import \
|
||||
StartupCheckService
|
||||
from packages.v1.system.service.startup_check_service import StartupCheckService
|
||||
|
||||
# Importa as configurações globais da aplicação
|
||||
from actions.log.log import Log
|
||||
from actions.config.config import Config
|
||||
from actions.system.handlers import register_exception_handlers
|
||||
|
||||
config = Config.get('app.json')
|
||||
config = Config.get("app.json")
|
||||
|
||||
# Instancia o app FastAPI com um título personalizado
|
||||
app = FastAPI(title='Mirror | Orius')
|
||||
app = FastAPI(title="Mirror | Orius")
|
||||
|
||||
# Adiciona o middleware global de erro
|
||||
# app.middleware("http")(database_error_handler)
|
||||
|
||||
# Controle de erros personalizados
|
||||
register_exception_handlers(app)
|
||||
|
|
@ -40,6 +46,7 @@ app.add_middleware(
|
|||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def on_startup():
|
||||
|
||||
|
|
@ -49,18 +56,19 @@ async def on_startup():
|
|||
# Exibe o amarzenamento do servidor
|
||||
print(startupCheckService.execute())
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def log_tempo_requisicao(request: Request, call_next):
|
||||
|
||||
# Ação responsavel por registrar o log de requisição
|
||||
log = Log()
|
||||
config = Config.get('app.json')
|
||||
config = Config.get("app.json")
|
||||
|
||||
# Obtem os dados da requisição
|
||||
log_data = {
|
||||
"method": request.method,
|
||||
"url": str(request.url),
|
||||
"headers": dict(request.headers)
|
||||
"headers": dict(request.headers),
|
||||
}
|
||||
|
||||
# Gera o nome do arquivo
|
||||
|
|
@ -74,16 +82,18 @@ async def log_tempo_requisicao(request: Request, call_next):
|
|||
|
||||
return response
|
||||
|
||||
|
||||
# Inclui as rotas da versão 1 da API com prefixo definido em settings (ex: /api/v1)
|
||||
app.include_router(api_router, prefix=config.url)
|
||||
|
||||
# Executa o servidor com Uvicorn se este arquivo for executado diretamente
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(
|
||||
"main:app", # Caminho do app para execução
|
||||
host="0.0.0.0", # Disponibiliza a aplicação externamente
|
||||
port=8000, # Porta padrão
|
||||
log_level='info', # Define o nível de log para desenvolvimento
|
||||
reload=True # Ativa auto-reload durante desenvolvimento
|
||||
"main:app", # Caminho do app para execução
|
||||
host="0.0.0.0", # Disponibiliza a aplicação externamente
|
||||
port=8000, # Porta padrão
|
||||
log_level="info", # Define o nível de log para desenvolvimento
|
||||
reload=True, # Ativa auto-reload durante desenvolvimento
|
||||
)
|
||||
|
|
|
|||
58
middlewares/error_handler.py
Normal file
58
middlewares/error_handler.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# middlewares/error_handler.py
|
||||
from fastapi import Request
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlalchemy.exc import OperationalError, IntegrityError
|
||||
import pymysql
|
||||
|
||||
|
||||
async def database_error_handler(request: Request, call_next):
|
||||
"""
|
||||
Middleware para capturar erros de banco de dados e retornar respostas JSON amigáveis.
|
||||
"""
|
||||
try:
|
||||
response = await call_next(request)
|
||||
return response
|
||||
|
||||
except OperationalError as e:
|
||||
# Erros de conexão (ex: Access denied, banco inexistente)
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"success": False,
|
||||
"error": "Database connection failed",
|
||||
"details": str(e.orig) if hasattr(e, "orig") else str(e),
|
||||
},
|
||||
)
|
||||
|
||||
except IntegrityError as e:
|
||||
# Erros de integridade (ex: unique constraint, foreign key)
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={
|
||||
"success": False,
|
||||
"error": "Database integrity error",
|
||||
"details": str(e.orig) if hasattr(e, "orig") else str(e),
|
||||
},
|
||||
)
|
||||
|
||||
except pymysql.err.OperationalError as e:
|
||||
# Erro específico do PyMySQL (ex: senha errada)
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"success": False,
|
||||
"error": "MySQL Operational Error",
|
||||
"details": str(e),
|
||||
},
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
# Qualquer outro erro genérico
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"success": False,
|
||||
"error": "Internal Server Error",
|
||||
"details": str(e),
|
||||
},
|
||||
)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
from packages.v1.administrativo.repositories.ato_documento.ato_documento_delete_repository import (
|
||||
DeleteRepository,
|
||||
)
|
||||
|
||||
|
||||
class DeleteAction:
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
delete_repository = DeleteRepository()
|
||||
|
||||
return delete_repository.execute(ato_documento_schema)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.repositories.ato_documento.ato_documento_index_repository import (
|
||||
IndexRepository,
|
||||
)
|
||||
|
||||
|
||||
class IndexAction(BaseAction):
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Instânciamento do repositório sql
|
||||
index_repository = IndexRepository()
|
||||
|
||||
# Execução do sql
|
||||
response = index_repository.execute()
|
||||
|
||||
# Retorno da informação
|
||||
return response
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoSaveSchema,
|
||||
)
|
||||
from packages.v1.administrativo.repositories.ato_documento.ato_documento_save_repository import (
|
||||
SaveRepository,
|
||||
)
|
||||
|
||||
|
||||
class SaveAction:
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSaveSchema):
|
||||
|
||||
save_repository = SaveRepository()
|
||||
|
||||
return save_repository.execute(ato_documento_schema)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
from packages.v1.administrativo.repositories.ato_documento.ato_documento_show_repository import (
|
||||
ShowRepository,
|
||||
)
|
||||
|
||||
|
||||
class ShowAction(BaseAction):
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento do repositório sql
|
||||
show_repository = ShowRepository()
|
||||
|
||||
# Execução do sql
|
||||
response = show_repository.execute(ato_documento_schema)
|
||||
|
||||
# Retorno da informação
|
||||
return response
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoUpdateSchema,
|
||||
)
|
||||
from packages.v1.administrativo.repositories.ato_documento.ato_documento_update_repository import (
|
||||
UpdateRepository,
|
||||
)
|
||||
|
||||
|
||||
class UpdateAction:
|
||||
|
||||
def execute(
|
||||
self, ato_documento_id: int, ato_documento_schema: AtoDocumentoUpdateSchema
|
||||
):
|
||||
|
||||
update_repository = UpdateRepository()
|
||||
|
||||
return update_repository.execute(ato_documento_id, ato_documento_schema)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
from packages.v1.administrativo.repositories.ato_documento.ato_principal_show_repository import (
|
||||
ShowRepository,
|
||||
)
|
||||
|
||||
|
||||
class ShowAction:
|
||||
|
||||
# O método execute espera um schema que contenha o ID do principal
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento do repositório
|
||||
show_repository = ShowRepository()
|
||||
|
||||
# Execução do repositório
|
||||
return show_repository.execute(ato_documento_schema)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
from packages.v1.administrativo.repositories.ato_parte.ato_parte_delete_repository import (
|
||||
DeleteRepository,
|
||||
)
|
||||
|
||||
|
||||
class DeleteAction:
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
delete_repository = DeleteRepository()
|
||||
|
||||
return delete_repository.execute(ato_parte_schema)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.repositories.ato_parte.ato_parte_index_repository import (
|
||||
IndexRepository,
|
||||
)
|
||||
|
||||
|
||||
class IndexAction(BaseAction):
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Instânciamento do repositório sql
|
||||
index_repository = IndexRepository()
|
||||
|
||||
# Execução do sql
|
||||
response = index_repository.execute()
|
||||
|
||||
# Retorno da informação
|
||||
return response
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteSaveSchema,
|
||||
)
|
||||
from packages.v1.administrativo.repositories.ato_parte.ato_parte_save_repository import (
|
||||
SaveRepository,
|
||||
)
|
||||
|
||||
|
||||
class SaveAction:
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSaveSchema):
|
||||
|
||||
save_repository = SaveRepository()
|
||||
|
||||
return save_repository.execute(ato_parte_schema)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
from packages.v1.administrativo.repositories.ato_parte.ato_parte_show_repository import (
|
||||
ShowRepository,
|
||||
)
|
||||
|
||||
|
||||
class ShowAction(BaseAction):
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Instânciamento do repositório sql
|
||||
show_repository = ShowRepository()
|
||||
|
||||
# Execução do sql
|
||||
response = show_repository.execute(ato_parte_schema)
|
||||
|
||||
# Retorno da informação
|
||||
return response
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteUpdateSchema,
|
||||
)
|
||||
from packages.v1.administrativo.repositories.ato_parte.ato_parte_update_repository import (
|
||||
UpdateRepository,
|
||||
)
|
||||
|
||||
|
||||
class UpdateAction:
|
||||
|
||||
def execute(self, ato_parte_id: int, ato_parte_schema: AtoParteUpdateSchema):
|
||||
|
||||
update_repository = UpdateRepository()
|
||||
|
||||
return update_repository.execute(ato_parte_id, ato_parte_schema)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
from packages.v1.administrativo.repositories.ato_parte.ato_principal_show_repository import (
|
||||
ShowRepository,
|
||||
)
|
||||
|
||||
|
||||
class AtoPartePrincipalShowAction:
|
||||
|
||||
# O método execute espera um schema que contenha o ID do principal
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Instânciamento do repositório
|
||||
show_repository = ShowRepository()
|
||||
|
||||
# Execução do repositório
|
||||
return show_repository.execute(ato_parte_schema)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from packages.v1.administrativo.schemas.ato_principal_schema import AtoPrincipalIdSchema
|
||||
from packages.v1.administrativo.repositories.ato_principal.ato_principal_delete_repository import (
|
||||
DeleteRepository,
|
||||
)
|
||||
|
||||
|
||||
class DeleteAction:
|
||||
|
||||
def execute(self, ato_principal_schema: AtoPrincipalIdSchema):
|
||||
|
||||
delete_repository = DeleteRepository()
|
||||
|
||||
return delete_repository.execute(ato_principal_schema)
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.repositories.ato_principal.ato_principal_index_repository import AtoPrincipalIndexRepository
|
||||
from packages.v1.administrativo.repositories.ato_principal.ato_principal_index_repository import (
|
||||
IndexRepository,
|
||||
)
|
||||
|
||||
|
||||
class AtoPrincipalIndexAction(BaseAction):
|
||||
class IndexAction(BaseAction):
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Instânciamento de repositório
|
||||
ato_principal_index_repository = AtoPrincipalIndexRepository()
|
||||
ato_principal_index_repository = IndexRepository()
|
||||
|
||||
# Retorna todos produtos
|
||||
return ato_principal_index_repository.execute()
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSaveSchema,
|
||||
)
|
||||
from packages.v1.administrativo.repositories.ato_principal.ato_principal_save_repository import (
|
||||
SaveRepository,
|
||||
)
|
||||
|
||||
|
||||
class SaveAction:
|
||||
|
||||
def execute(self, ato_principal_schema: AtoPrincipalSaveSchema):
|
||||
|
||||
save_repository = SaveRepository()
|
||||
|
||||
return save_repository.execute(ato_principal_schema)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from typing import List
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSaveSchema,
|
||||
)
|
||||
from packages.v1.administrativo.repositories.ato_principal.ato_principal_save_multiple_repository import (
|
||||
SaveMultipleRepository,
|
||||
)
|
||||
|
||||
|
||||
class SaveMultipleAction:
|
||||
|
||||
def execute(self, atos_principais: List[AtoPrincipalSaveSchema]):
|
||||
save_repository = SaveMultipleRepository()
|
||||
|
||||
# A lista completa é passada diretamente para o Repository.
|
||||
# O Repository é a única camada que deve iterar.
|
||||
results = save_repository.execute(atos_principais)
|
||||
|
||||
return results
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import AtoPrincipalSchema
|
||||
from packages.v1.administrativo.repositories.ato_principal.ato_principal_show_repository import (
|
||||
ShowRepository,
|
||||
)
|
||||
|
||||
|
||||
class ShowAction(BaseAction):
|
||||
|
||||
def execute(self, ato_principal_schema: AtoPrincipalSchema):
|
||||
|
||||
# Instânciamento do repositório sql
|
||||
show_repository = ShowRepository()
|
||||
|
||||
# Execução do sql
|
||||
response = show_repository.execute(ato_principal_schema)
|
||||
|
||||
# Retorno da informação
|
||||
return response
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalUpdateSchema,
|
||||
)
|
||||
from packages.v1.administrativo.repositories.ato_principal.ato_principal_update_repository import (
|
||||
UpdateRepository,
|
||||
)
|
||||
|
||||
|
||||
class UpdateAction:
|
||||
|
||||
def execute(
|
||||
self, ato_principal_id: int, ato_principal_schema: AtoPrincipalUpdateSchema
|
||||
):
|
||||
|
||||
update_repository = UpdateRepository()
|
||||
|
||||
return update_repository.execute(ato_principal_id, ato_principal_schema)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioIdSchema
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_delete_repository import (
|
||||
DeleteRepository,
|
||||
)
|
||||
|
||||
|
||||
class DeleteAction:
|
||||
|
||||
def execute(self, usuario_schema: UsuarioIdSchema):
|
||||
|
||||
delete_repository = DeleteRepository()
|
||||
|
||||
return delete_repository.execute(usuario_schema)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioAuthenticateSchema
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_get_by_authenticate_repository import (
|
||||
GetByAuthenticateRepository,
|
||||
)
|
||||
|
||||
|
||||
class GetByAuthenticateAction(BaseAction):
|
||||
|
||||
def execute(self, usuario_authenticate_schema: UsuarioAuthenticateSchema):
|
||||
|
||||
# Instânciamento do repositório de busca pelo authenticate
|
||||
get_by_authenticate_repository = GetByAuthenticateRepository()
|
||||
|
||||
# Execução do repositório
|
||||
return get_by_authenticate_repository.execute(usuario_authenticate_schema)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioEmailSchema
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_get_by_email_repository import (
|
||||
GetByUsuarioEmailRepository,
|
||||
)
|
||||
|
||||
|
||||
class GetByUsuarioEmailAction(BaseAction):
|
||||
|
||||
def execute(self, usuario_schema=UsuarioEmailSchema):
|
||||
|
||||
# Importação do repositório
|
||||
get_by_email_repository = GetByUsuarioEmailRepository()
|
||||
|
||||
# Execução do repositório
|
||||
return get_by_email_repository.execute(usuario_schema)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioSchema
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_get_by_usuario_id_repository import (
|
||||
GetByUsuarioIdRepository,
|
||||
)
|
||||
|
||||
|
||||
class GetByUsuarioIdAction:
|
||||
|
||||
def execute(self, usuario_schema=UsuarioSchema):
|
||||
|
||||
# Importação do repositório
|
||||
get_by_usuario_id_repository = GetByUsuarioIdRepository()
|
||||
|
||||
# Execução do repositório
|
||||
return get_by_usuario_id_repository.execute(usuario_schema)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_index_repository import (
|
||||
IndexRepository,
|
||||
)
|
||||
|
||||
|
||||
class IndexAction(BaseAction):
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Instânciamento do repositório sql
|
||||
index_repository = IndexRepository()
|
||||
|
||||
# Execução do sql
|
||||
response = index_repository.execute()
|
||||
|
||||
# Retorno da informação
|
||||
return response
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioSaveSchema
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_save_repository import (
|
||||
SaveRepository,
|
||||
)
|
||||
|
||||
|
||||
class SaveAction:
|
||||
|
||||
def execute(self, usuario_schema: UsuarioSaveSchema):
|
||||
|
||||
save_repository = SaveRepository()
|
||||
|
||||
return save_repository.execute(usuario_schema)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from abstracts.action import BaseAction
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioSchema
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_show_repository import (
|
||||
ShowRepository,
|
||||
)
|
||||
|
||||
|
||||
class ShowAction(BaseAction):
|
||||
|
||||
def execute(self, usuario_schema: UsuarioSchema):
|
||||
|
||||
# Instânciamento do repositório sql
|
||||
show_repository = ShowRepository()
|
||||
|
||||
# Execução do sql
|
||||
response = show_repository.execute(usuario_schema)
|
||||
|
||||
# Retorno da informação
|
||||
return response
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioUpdateSchema
|
||||
from packages.v1.administrativo.repositories.usuario.usuario_update_repository import (
|
||||
UpdateRepository,
|
||||
)
|
||||
|
||||
|
||||
class UpdateAction:
|
||||
|
||||
def execute(self, usuario_id: int, usuario_schema: UsuarioUpdateSchema):
|
||||
|
||||
save_repository = UpdateRepository()
|
||||
|
||||
return save_repository.execute(usuario_id, usuario_schema)
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
from actions.dynamic_import.dynamic_import import DynamicImport
|
||||
from packages.v1.administrativo.services.ato_documento.ato_documento_index_service import (
|
||||
IndexService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_documento.ato_documento_save_service import (
|
||||
SaveService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_documento.ato_documento_show_service import (
|
||||
ShowService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_documento.ato_principal_show_service import (
|
||||
ShowAtoPrincipalService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_documento.ato_documento_update_service import (
|
||||
UpdateService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_documento.ato_documento_delete_service import (
|
||||
DeleteService,
|
||||
)
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoSchema,
|
||||
AtoDocumentoSaveSchema,
|
||||
AtoDocumentoUpdateSchema,
|
||||
AtoDocumentoIdSchema,
|
||||
)
|
||||
|
||||
|
||||
class AtoDocumentoController:
|
||||
|
||||
def __init__(self):
|
||||
# Action responsável por carregar as services de acodo 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("ato_documento")
|
||||
pass
|
||||
|
||||
# Lista todos os documentos
|
||||
def index(self):
|
||||
|
||||
# Instânciamento da classe service
|
||||
index_service = IndexService()
|
||||
|
||||
# Lista todos os documentos
|
||||
return {
|
||||
"message": "Documentos localizados com sucesso",
|
||||
"data": index_service.execute(),
|
||||
}
|
||||
|
||||
# Busca um documento especifico pelo ID do ato principal
|
||||
def showAtoPrincipal(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
show_service = ShowAtoPrincipalService()
|
||||
|
||||
# Busca e retorna o documento desejado
|
||||
return {
|
||||
"message": "Documento localizado com sucesso",
|
||||
"data": show_service.execute(ato_documento_schema),
|
||||
}
|
||||
|
||||
# Busca um documento especifico pelo ID
|
||||
def show(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
show_service = ShowService()
|
||||
|
||||
# Busca e retorna o documento desejado
|
||||
return {
|
||||
"message": "Documento localizado com sucesso",
|
||||
"data": show_service.execute(ato_documento_schema),
|
||||
}
|
||||
|
||||
# Cadastra um novo documento
|
||||
def save(self, ato_documento_schema: AtoDocumentoSaveSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
save_service = SaveService()
|
||||
|
||||
# Busca e retorna o documento desejado
|
||||
return {
|
||||
"message": "Documento salvo com sucesso",
|
||||
"data": save_service.execute(ato_documento_schema),
|
||||
}
|
||||
|
||||
# Atualiza os dados de um documento
|
||||
def update(
|
||||
self, ato_documento_id: int, ato_documento_schema: AtoDocumentoUpdateSchema
|
||||
):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
update_service = UpdateService()
|
||||
|
||||
# Busca e retorna o documento desejado
|
||||
return {
|
||||
"message": "Documento atualizado com sucesso",
|
||||
"data": update_service.execute(ato_documento_id, ato_documento_schema),
|
||||
}
|
||||
|
||||
# Exclui um documento
|
||||
def delete(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
delete_service = DeleteService()
|
||||
|
||||
# Busca e retorna o documento desejado
|
||||
return {
|
||||
"message": "Documento removido com sucesso",
|
||||
"data": delete_service.execute(ato_documento_schema),
|
||||
}
|
||||
111
packages/v1/administrativo/controllers/ato_parte_controller.py
Normal file
111
packages/v1/administrativo/controllers/ato_parte_controller.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
from actions.dynamic_import.dynamic_import import DynamicImport
|
||||
from packages.v1.administrativo.services.ato_parte.ato_parte_index_service import (
|
||||
IndexService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_parte.ato_parte_save_service import (
|
||||
SaveService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_parte.ato_parte_show_service import (
|
||||
ShowService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_parte.ato_principal_show_service import (
|
||||
AtoPrincipalShowService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_parte.ato_parte_update_service import (
|
||||
UpdateService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_parte.ato_parte_delete_service import (
|
||||
DeleteService,
|
||||
)
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteSchema,
|
||||
AtoParteSaveSchema,
|
||||
AtoParteUpdateSchema,
|
||||
AtoParteIdSchema,
|
||||
)
|
||||
|
||||
|
||||
class AtoParteController:
|
||||
|
||||
def __init__(self):
|
||||
# Action responsável por carregar as services de acodo 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("ato_parte")
|
||||
pass
|
||||
|
||||
# Lista todas as partes
|
||||
def index(self):
|
||||
|
||||
# Instânciamento da classe service
|
||||
index_service = IndexService()
|
||||
|
||||
# Lista todas as partes
|
||||
return {
|
||||
"message": "Partes localizadas com sucesso",
|
||||
"data": index_service.execute(),
|
||||
}
|
||||
|
||||
# Busca uma parte especifica pelo ID do ato principal
|
||||
def showAtoPrincipal(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
show_service = AtoPrincipalShowService()
|
||||
|
||||
# Busca e retorna a parte desejada
|
||||
return {
|
||||
"message": "Parte localizada com sucesso",
|
||||
"data": show_service.execute(ato_parte_schema),
|
||||
}
|
||||
|
||||
# Busca uma parte especifica pelo ID
|
||||
def show(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
show_service = ShowService()
|
||||
|
||||
# Busca e retorna a parte desejada
|
||||
return {
|
||||
"message": "Parte localizada com sucesso",
|
||||
"data": show_service.execute(ato_parte_schema),
|
||||
}
|
||||
|
||||
# Cadastra uma nova parte
|
||||
def save(self, ato_parte_schema: AtoParteSaveSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
save_service = SaveService()
|
||||
|
||||
# Busca e retorna a parte desejada
|
||||
return {
|
||||
"message": "Parte salva com sucesso",
|
||||
"data": save_service.execute(ato_parte_schema),
|
||||
}
|
||||
|
||||
# Atualiza os dados de uma parte
|
||||
def update(self, ato_parte_id: int, ato_parte_schema: AtoParteUpdateSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
update_service = UpdateService()
|
||||
|
||||
# Busca e retorna a parte desejada
|
||||
return {
|
||||
"message": "Parte atualizada com sucesso",
|
||||
"data": update_service.execute(ato_parte_id, ato_parte_schema),
|
||||
}
|
||||
|
||||
# Exclui uma parte
|
||||
def delete(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
delete_service = DeleteService()
|
||||
|
||||
# Busca e retorna a parte desejada
|
||||
return {
|
||||
"message": "Parte removida com sucesso",
|
||||
"data": delete_service.execute(ato_parte_schema),
|
||||
}
|
||||
|
|
@ -1,20 +1,124 @@
|
|||
# Importação de bibliotecas
|
||||
from actions.dynamic_import.dynamic_import import DynamicImport
|
||||
from packages.v1.administrativo.services.ato_principal.go.ato_principal_index_service import AtoPrincipalIndexService
|
||||
|
||||
# Importa os serviços com o prefixo 'ato_principal'
|
||||
from packages.v1.administrativo.services.ato_principal.ato_principal_index_service import (
|
||||
IndexService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_principal.ato_principal_save_service import (
|
||||
SaveService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_principal.ato_principal_save_multiple_service import (
|
||||
SaveMultipleService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_principal.ato_principal_show_service import (
|
||||
ShowService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_principal.ato_principal_update_service import (
|
||||
UpdateService,
|
||||
)
|
||||
from packages.v1.administrativo.services.ato_principal.ato_principal_delete_service import (
|
||||
DeleteService,
|
||||
)
|
||||
|
||||
# Importa os Schemas com o prefixo 'ato_principal'
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSchema,
|
||||
AtoPrincipalSaveSchema,
|
||||
AtoPrincipalUpdateSchema,
|
||||
AtoPrincipalIdSchema,
|
||||
)
|
||||
|
||||
|
||||
# Mantendo o padrão de nome de classe
|
||||
class AtoPrincipalController:
|
||||
"""
|
||||
Controller responsável pelas operações CRUD da entidade Ato Principal.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Action responsável por carregar as services de acodo 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 (agora 'ato_principal')
|
||||
self.dynamic_import.set_table("ato_principal")
|
||||
pass
|
||||
|
||||
# Lista todos os atos principais
|
||||
def index(self):
|
||||
|
||||
# Importação da classe desejad
|
||||
ato_principal_index_service = AtoPrincipalIndexService()
|
||||
# Instânciamento da classe service
|
||||
index_service = IndexService()
|
||||
|
||||
# Intânciamento da classe service
|
||||
self.index_service = ato_principal_index_service
|
||||
|
||||
# Lista todos os produtos
|
||||
# Lista todos os atos principais
|
||||
return {
|
||||
'message' : 'Registros localizados com sucesso',
|
||||
'data': self.index_service.execute()
|
||||
"message": "Atos Principais localizados com sucesso",
|
||||
"data": index_service.execute(),
|
||||
}
|
||||
|
||||
# Busca um ato principal especifica pelo ID
|
||||
# Note: O método 'showAtoPrincipal' foi removido por não se aplicar
|
||||
# à entidade principal.
|
||||
def show(self, ato_principal_schema: AtoPrincipalSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
show_service = ShowService()
|
||||
|
||||
# Busca e retorna o ato principal desejado
|
||||
return {
|
||||
"message": "Ato Principal localizado com sucesso",
|
||||
"data": show_service.execute(ato_principal_schema),
|
||||
}
|
||||
|
||||
# Cadastra um novo ato principal
|
||||
def save(self, ato_principal_schema: AtoPrincipalSaveSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
save_service = SaveService()
|
||||
|
||||
# Salva e retorna o ato principal
|
||||
return {
|
||||
"message": "Ato Principal salvo com sucesso",
|
||||
"data": save_service.execute(ato_principal_schema),
|
||||
}
|
||||
|
||||
# Cadastra múltiplos itens
|
||||
def save_multiple(self, atos_principais: list[AtoPrincipalSaveSchema]):
|
||||
# A lista completa é passada diretamente para o Service.
|
||||
# O Service e o Action também devem ser corrigidos para parar de iterar.
|
||||
save_service = SaveMultipleService()
|
||||
|
||||
responses = save_service.execute(atos_principais)
|
||||
|
||||
return {
|
||||
"message": "Processamento de múltiplos atos concluído",
|
||||
"results": responses, # O Service já retorna a lista de resultados
|
||||
}
|
||||
|
||||
# Atualiza os dados de um ato principal
|
||||
def update(
|
||||
self, ato_principal_id: int, ato_principal_schema: AtoPrincipalUpdateSchema
|
||||
):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
update_service = UpdateService()
|
||||
|
||||
# Atualiza e retorna o ato principal
|
||||
return {
|
||||
"message": "Ato Principal atualizado com sucesso",
|
||||
"data": update_service.execute(ato_principal_id, ato_principal_schema),
|
||||
}
|
||||
|
||||
# Exclui um ato principal
|
||||
def delete(self, ato_principal_schema: AtoPrincipalSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
delete_service = DeleteService()
|
||||
|
||||
# Exclui e retorna a parte desejada
|
||||
return {
|
||||
"message": "Ato Principal removido com sucesso",
|
||||
"data": delete_service.execute(ato_principal_schema),
|
||||
}
|
||||
145
packages/v1/administrativo/controllers/usuario_controller.py
Normal file
145
packages/v1/administrativo/controllers/usuario_controller.py
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
from actions.dynamic_import.dynamic_import import DynamicImport
|
||||
from packages.v1.administrativo.services.usuario.usuario_authenticate_service import (
|
||||
AuthenticateService,
|
||||
)
|
||||
from packages.v1.administrativo.services.usuario.usuario_me_service import (
|
||||
MeService,
|
||||
)
|
||||
from packages.v1.administrativo.services.usuario.usuario_index_service import (
|
||||
IndexService,
|
||||
)
|
||||
from packages.v1.administrativo.services.usuario.usuario_save_service import (
|
||||
SaveService,
|
||||
)
|
||||
from packages.v1.administrativo.services.usuario.usuario_get_email_service import (
|
||||
GetEmailService,
|
||||
)
|
||||
from packages.v1.administrativo.services.usuario.usuario_show_service import (
|
||||
ShowService,
|
||||
)
|
||||
from packages.v1.administrativo.services.usuario.usuario_update_service import (
|
||||
UpdateService,
|
||||
)
|
||||
from packages.v1.administrativo.services.usuario.usuario_delete_service import (
|
||||
DeleteService,
|
||||
)
|
||||
from packages.v1.administrativo.schemas.usuario_schema import (
|
||||
UsuarioSchema,
|
||||
UsuarioAuthenticateSchema,
|
||||
UsuarioSaveSchema,
|
||||
UsuarioUpdateSchema,
|
||||
UsuarioEmailSchema,
|
||||
UsuarioIdSchema,
|
||||
)
|
||||
|
||||
|
||||
class UsuarioController:
|
||||
|
||||
def __init__(self):
|
||||
# Action responsável por carregar as services de acodo 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("usuario")
|
||||
pass
|
||||
|
||||
# Efetua o acesso junto ao sistema por um determinado usuário
|
||||
def authenticate(self, user_authenticate_schema: UsuarioAuthenticateSchema):
|
||||
|
||||
# Importação de service de Authenticate
|
||||
authenticate_service = AuthenticateService()
|
||||
|
||||
# Retorna o usuário logado
|
||||
return {
|
||||
"message": "Usuário localizado com sucesso",
|
||||
"data": {"token": authenticate_service.execute(user_authenticate_schema)},
|
||||
}
|
||||
|
||||
# Carrega os dados do usuário logado
|
||||
def me(self, current_user):
|
||||
|
||||
# Instânciamento da service
|
||||
me_service = MeService()
|
||||
|
||||
# Retorna o usuário logado
|
||||
return {
|
||||
"message": "Usuário localizado com sucesso",
|
||||
"data": me_service.execute(current_user),
|
||||
}
|
||||
|
||||
# Lista todos os usuários
|
||||
def index(self):
|
||||
|
||||
# Instânciamento da classe service
|
||||
indexService = IndexService()
|
||||
|
||||
# Lista todos os usuários
|
||||
return {
|
||||
"message": "Usuários localizados com sucesso",
|
||||
"data": indexService.execute(),
|
||||
}
|
||||
|
||||
# Busca um usuário especifico pelo ID
|
||||
def show(self, usuario_schema: UsuarioSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
show_service = ShowService()
|
||||
|
||||
# Busca e retorna o usuário desejado
|
||||
return {
|
||||
"message": "Usuário localizado com sucesso",
|
||||
"data": show_service.execute(usuario_schema),
|
||||
}
|
||||
|
||||
# Busca um usuário especifico pelo e-mail
|
||||
def getEmail(self, usuario_schema: UsuarioEmailSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
get_email_service = GetEmailService()
|
||||
|
||||
# Busca e retorna o usuário desejado
|
||||
return {
|
||||
"message": "E-mail localizado com sucesso",
|
||||
"data": get_email_service.execute(
|
||||
usuario_schema, True
|
||||
), # True para retornar a mensagem de erro caso não localize o usuario
|
||||
}
|
||||
|
||||
# Cadastra um novo usuário
|
||||
def save(self, usuario_schema: UsuarioSaveSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
save_service = SaveService()
|
||||
|
||||
# Busca e retorna o usuário desejado
|
||||
return {
|
||||
"message": "Usuário salvo com sucesso",
|
||||
"data": save_service.execute(usuario_schema),
|
||||
}
|
||||
|
||||
# Atualiza os dados de um usuário
|
||||
def update(self, usuario_id: int, usuario_schema: UsuarioUpdateSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
update_service = UpdateService()
|
||||
|
||||
# Busca e retorna o usuário desejado
|
||||
return {
|
||||
"message": "Usuário atualizado com sucesso",
|
||||
"data": update_service.execute(usuario_id, usuario_schema),
|
||||
}
|
||||
|
||||
# Exclui um usuário
|
||||
def delete(self, usuario_schema: UsuarioIdSchema):
|
||||
|
||||
# Instânciamento da classe desejada
|
||||
delete_service = DeleteService()
|
||||
|
||||
# Busca e retorna o usuário desejado
|
||||
return {
|
||||
"message": "Usuário removido com sucesso",
|
||||
"data": delete_service.execute(usuario_schema),
|
||||
}
|
||||
133
packages/v1/administrativo/endpoints/ato_documento_endpoint.py
Normal file
133
packages/v1/administrativo/endpoints/ato_documento_endpoint.py
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# Importação de bibliotecas
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, Depends, status
|
||||
from actions.jwt.get_current_user import get_current_user
|
||||
from packages.v1.administrativo.controllers.ato_documento_controller import (
|
||||
AtoDocumentoController,
|
||||
)
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoSchema,
|
||||
AtoDocumentoSaveSchema,
|
||||
AtoDocumentoUpdateSchema,
|
||||
AtoDocumentoIdSchema,
|
||||
)
|
||||
|
||||
# Inicializa o roteador para as rotas de ato_documento
|
||||
router = APIRouter()
|
||||
|
||||
# Instânciamento do controller desejado
|
||||
ato_documento_controller = AtoDocumentoController()
|
||||
|
||||
|
||||
# Lista todos os documentos
|
||||
@router.get(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Lista todos os documentos cadastrados",
|
||||
response_description="Lista todos os documentos cadastrados",
|
||||
)
|
||||
async def index(current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Busca todos os documentos cadastrados
|
||||
response = ato_documento_controller.index()
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Localiza um documento pelo ato_principal_id
|
||||
@router.get(
|
||||
"/ato_principal/{ato_principal_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca um registro em especifico pelo ID do ato principal",
|
||||
response_description="Busca um registro em especifico",
|
||||
)
|
||||
async def showAtoPrincipal(
|
||||
ato_principal_id: int, current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_documento_schema = AtoDocumentoSchema(ato_principal_id=ato_principal_id)
|
||||
|
||||
# Busca um documento especifico pelo ID
|
||||
response = ato_documento_controller.showAtoPrincipal(ato_documento_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Localiza um documento pelo ID
|
||||
@router.get(
|
||||
"/{ato_documento_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca um registro em especifico pelo ID do documento",
|
||||
response_description="Busca um registro em especifico",
|
||||
)
|
||||
async def show(ato_documento_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_documento_schema = AtoDocumentoSchema(ato_documento_id=ato_documento_id)
|
||||
|
||||
# Busca um documento especifico pelo ID
|
||||
response = ato_documento_controller.show(ato_documento_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Cadastro de documentos
|
||||
@router.post(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Cadastra um documento",
|
||||
response_description="Cadastra um documento",
|
||||
)
|
||||
async def save(
|
||||
ato_documento_schema: AtoDocumentoSaveSchema,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
|
||||
# Efetua o cadastro do documento junto ao banco de dados
|
||||
response = ato_documento_controller.save(ato_documento_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Atualiza os dados de documento
|
||||
@router.put(
|
||||
"/{ato_documento_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Atualiza um documento",
|
||||
response_description="Atualiza um documento",
|
||||
)
|
||||
async def update(
|
||||
ato_documento_id: int,
|
||||
ato_documento_schema: AtoDocumentoUpdateSchema,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
|
||||
# Efetua a atualização dos dados do documento
|
||||
response = ato_documento_controller.update(ato_documento_id, ato_documento_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Exclui um determinado documento
|
||||
@router.delete(
|
||||
"/{ato_documento_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Remove um documento",
|
||||
response_description="Remove um documento",
|
||||
)
|
||||
async def delete(ato_documento_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_documento_schema = AtoDocumentoSchema(ato_documento_id=ato_documento_id)
|
||||
|
||||
# Efetua a exclusão de um determinado documento
|
||||
response = ato_documento_controller.delete(ato_documento_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
133
packages/v1/administrativo/endpoints/ato_parte_endpoint.py
Normal file
133
packages/v1/administrativo/endpoints/ato_parte_endpoint.py
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# Importação de bibliotecas
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, Depends, status
|
||||
from actions.jwt.get_current_user import get_current_user
|
||||
from packages.v1.administrativo.controllers.ato_parte_controller import (
|
||||
AtoParteController,
|
||||
)
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteSchema,
|
||||
AtoParteSaveSchema,
|
||||
AtoParteUpdateSchema,
|
||||
AtoParteIdSchema,
|
||||
)
|
||||
|
||||
# Inicializa o roteador para as rotas de ato_parte
|
||||
router = APIRouter()
|
||||
|
||||
# Instânciamento do controller desejado
|
||||
ato_parte_controller = AtoParteController()
|
||||
|
||||
|
||||
# Lista todas as partes
|
||||
@router.get(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Lista todas as partes cadastradas",
|
||||
response_description="Lista todas as partes cadastradas",
|
||||
)
|
||||
async def index(current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Busca todas as partes cadastradas
|
||||
response = ato_parte_controller.index()
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Localiza uma parte pelo ato_principal_id
|
||||
@router.get(
|
||||
"/ato_principal/{ato_principal_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca um registro em especifico pelo ID do ato principal",
|
||||
response_description="Busca um registro em especifico",
|
||||
)
|
||||
async def showAtoPrincipal(
|
||||
ato_principal_id: int, current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_parte_schema = AtoParteSchema(ato_principal_id=ato_principal_id)
|
||||
|
||||
# Busca uma parte especifica pelo ID do ato principal
|
||||
response = ato_parte_controller.showAtoPrincipal(ato_parte_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Localiza uma parte pelo ID
|
||||
@router.get(
|
||||
"/{ato_parte_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca um registro em especifico pelo ID da parte",
|
||||
response_description="Busca um registro em especifico",
|
||||
)
|
||||
async def show(ato_parte_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_parte_schema = AtoParteSchema(ato_parte_id=ato_parte_id)
|
||||
|
||||
# Busca uma parte especifica pelo ID
|
||||
response = ato_parte_controller.show(ato_parte_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Cadastro de partes
|
||||
@router.post(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Cadastra uma parte",
|
||||
response_description="Cadastra uma parte",
|
||||
)
|
||||
async def save(
|
||||
ato_parte_schema: AtoParteSaveSchema,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
|
||||
# Efetua o cadastro da parte junto ao banco de dados
|
||||
response = ato_parte_controller.save(ato_parte_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Atualiza os dados de uma parte
|
||||
@router.put(
|
||||
"/{ato_parte_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Atualiza uma parte",
|
||||
response_description="Atualiza uma parte",
|
||||
)
|
||||
async def update(
|
||||
ato_parte_id: int,
|
||||
ato_parte_schema: AtoParteUpdateSchema,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
|
||||
# Efetua a atualização dos dados da parte
|
||||
response = ato_parte_controller.update(ato_parte_id, ato_parte_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Exclui uma determinada parte
|
||||
@router.delete(
|
||||
"/{ato_parte_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Remove uma parte",
|
||||
response_description="Remove uma parte",
|
||||
)
|
||||
async def delete(ato_parte_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_parte_schema = AtoParteSchema(ato_parte_id=ato_parte_id)
|
||||
|
||||
# Efetua a exclusão de uma determinada parte
|
||||
response = ato_parte_controller.delete(ato_parte_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
|
@ -1,22 +1,132 @@
|
|||
# Importação de bibliotecas
|
||||
from typing import List
|
||||
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.ato_principal_controller import AtoPrincipalController
|
||||
from packages.v1.administrativo.controllers.ato_principal_controller import (
|
||||
AtoPrincipalController,
|
||||
)
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSchema,
|
||||
AtoPrincipalSaveSchema,
|
||||
AtoPrincipalUpdateSchema,
|
||||
AtoPrincipalIdSchema,
|
||||
)
|
||||
|
||||
# Inicializar o roteaodr para as rotas de produtos
|
||||
# Inicializa o roteador para as rotas de ato principal
|
||||
router = APIRouter()
|
||||
|
||||
# Instãnciamento do controller desejado
|
||||
# Instânciamento do controller desejado
|
||||
ato_principal_controller = AtoPrincipalController()
|
||||
|
||||
@router.get("/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca itens com filtros opcionais",
|
||||
response_description="Lista de itens encontrados com base nos critérios de busca.")
|
||||
async def index():
|
||||
|
||||
# Busca todos os produtos cadastrados
|
||||
# Lista todos os atos principais
|
||||
@router.get(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Lista todos os atos principais cadastrados",
|
||||
response_description="Lista todos os atos principais cadastrados",
|
||||
)
|
||||
async def index(current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Busca todos os atos principais cadastrados
|
||||
response = ato_principal_controller.index()
|
||||
|
||||
# Retornar os dados localizados
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Localiza um ato principal pelo ID
|
||||
@router.get(
|
||||
"/{ato_principal_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca um registro em especifico pelo ID do ato principal",
|
||||
response_description="Busca um registro em especifico",
|
||||
)
|
||||
async def show(ato_principal_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_principal_schema = AtoPrincipalIdSchema(ato_principal_id=ato_principal_id)
|
||||
|
||||
# Busca um ato principal especifico pelo ID
|
||||
response = ato_principal_controller.show(ato_principal_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Cadastro de múltiplos itens
|
||||
@router.post(
|
||||
"/batch",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Cadastra múltiplos atos principais",
|
||||
response_description="Cadastra vários atos principais de uma vez",
|
||||
)
|
||||
async def save_multiple(
|
||||
atos_principais: List[AtoPrincipalSaveSchema],
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
# A lista completa (List[AtoPrincipalSaveSchema]) é passada
|
||||
# DIRETAMENTE para o controller (que a passará ao Service, Action e Repository).
|
||||
# O loop de iteração deve estar APENAS no Repository.
|
||||
responses = ato_principal_controller.save_multiple(atos_principais)
|
||||
|
||||
return {"success": True, "data": responses}
|
||||
|
||||
|
||||
# Cadastro de ato principal
|
||||
@router.post(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Cadastra um ato principal",
|
||||
response_description="Cadastra um ato principal",
|
||||
)
|
||||
async def save(
|
||||
ato_principal_schema: AtoPrincipalSaveSchema,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
|
||||
# Efetua o cadastro do ato principal junto ao banco de dados
|
||||
response = ato_principal_controller.save(ato_principal_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Atualiza os dados de ato principal
|
||||
@router.put(
|
||||
"/{ato_principal_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Atualiza um ato principal",
|
||||
response_description="Atualiza um ato principal",
|
||||
)
|
||||
async def update(
|
||||
ato_principal_id: int,
|
||||
ato_principal_schema: AtoPrincipalUpdateSchema,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
|
||||
# Efetua a atualização dos dados de ato principal
|
||||
response = ato_principal_controller.update(ato_principal_id, ato_principal_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Exclui um determinado ato principal
|
||||
@router.delete(
|
||||
"/{ato_principal_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Remove um ato principal",
|
||||
response_description="Remove um ato principal",
|
||||
)
|
||||
async def delete(ato_principal_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
ato_principal_schema = AtoPrincipalIdSchema(ato_principal_id=ato_principal_id)
|
||||
|
||||
# Efetua a exclusão de um determinado ato principal
|
||||
response = ato_principal_controller.delete(ato_principal_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
164
packages/v1/administrativo/endpoints/usuario_endpoint.py
Normal file
164
packages/v1/administrativo/endpoints/usuario_endpoint.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# 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.usuario_controller import UsuarioController
|
||||
from packages.v1.administrativo.schemas.usuario_schema import (
|
||||
UsuarioSchema,
|
||||
UsuarioAuthenticateSchema,
|
||||
UsuarioSaveSchema,
|
||||
UsuarioUpdateSchema,
|
||||
UsuarioEmailSchema,
|
||||
UsuarioIdSchema,
|
||||
)
|
||||
|
||||
# Inicializa o roteador para as rotas de usuário
|
||||
router = APIRouter()
|
||||
|
||||
# Instânciamento do controller desejado
|
||||
user_controller = UsuarioController()
|
||||
|
||||
|
||||
# Autenticação de usuário
|
||||
@router.post(
|
||||
"/authenticate",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Cria o token de acesso do usuário",
|
||||
response_description="Retorna o token de acesso do usuário",
|
||||
)
|
||||
async def index(user_authenticate_schema: UsuarioAuthenticateSchema):
|
||||
|
||||
# Efetua a autenticação de um usuário junto ao sistema
|
||||
response = user_controller.authenticate(user_authenticate_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Dados do usuário logado
|
||||
@router.get(
|
||||
"/me",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Retorna os dados do usuário que efetuou o login",
|
||||
response_description="Dados do usuário que efetuou o login",
|
||||
)
|
||||
async def me(current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Busca os dados do usuário logado
|
||||
response = user_controller.me(current_user)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Lista todos os usuários
|
||||
@router.get(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Lista todos os usuário cadastrados",
|
||||
response_description="Lista todos os usuário cadastrados",
|
||||
)
|
||||
async def index(current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Busca todos os usuários cadastrados
|
||||
response = user_controller.index()
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Localiza um usuário pelo email
|
||||
@router.get(
|
||||
"/email/{email}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca um registro em especifico por e-mail informado",
|
||||
response_description="Busca um registro em especifico",
|
||||
)
|
||||
async def getEmail(email: str, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
usuario_schema = UsuarioEmailSchema(email=email)
|
||||
|
||||
print(usuario_schema)
|
||||
|
||||
# Busca um usuário especifico pelo e-mail
|
||||
response = user_controller.getEmail(usuario_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Localiza um usuário pelo ID
|
||||
@router.get(
|
||||
"/{usuario_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Busca um registro em especifico pelo ID do usuário",
|
||||
response_description="Busca um registro em especifico",
|
||||
)
|
||||
async def show(usuario_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
usuario_schema = UsuarioIdSchema(usuario_id=usuario_id)
|
||||
|
||||
# Busca um usuário especifico pelo ID
|
||||
response = user_controller.show(usuario_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Cadastro de usuários
|
||||
@router.post(
|
||||
"/",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Cadastra um usuário",
|
||||
response_description="Cadastra um usuário",
|
||||
)
|
||||
async def save(
|
||||
usuario_schema: UsuarioSaveSchema, current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
|
||||
# Efetua o cadastro do usuário junto ao banco de dados
|
||||
response = user_controller.save(usuario_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Atualiza os dados de usuário
|
||||
@router.put(
|
||||
"/{usuario_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Atualiza um usuário",
|
||||
response_description="Atualiza um usuário",
|
||||
)
|
||||
async def update(
|
||||
usuario_id: int,
|
||||
usuario_schema: UsuarioUpdateSchema,
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
|
||||
# Efetua a atualização dos dados de usuário
|
||||
response = user_controller.update(usuario_id, usuario_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
|
||||
|
||||
# Exclui um determinado usuário
|
||||
@router.delete(
|
||||
"/{usuario_id}",
|
||||
status_code=status.HTTP_200_OK,
|
||||
summary="Remove um usuário",
|
||||
response_description="Remove um usuário",
|
||||
)
|
||||
async def delete(usuario_id: int, current_user: dict = Depends(get_current_user)):
|
||||
|
||||
# Cria o schema com os dados recebidos
|
||||
usuario_schema = UsuarioIdSchema(usuario_id=usuario_id)
|
||||
|
||||
# Efetua a exclusão de um determinado usuário
|
||||
response = user_controller.delete(usuario_schema)
|
||||
|
||||
# Retorna os dados localizados
|
||||
return response
|
||||
62
packages/v1/administrativo/models/ato_documento_model.py
Normal file
62
packages/v1/administrativo/models/ato_documento_model.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# packages/v1/administrativo/models/ato_documento_model.py
|
||||
# Gerado a partir da DDL da tabela 'ato_documento'
|
||||
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
BigInteger,
|
||||
String,
|
||||
DateTime,
|
||||
Text, # Necessário para o campo 'url'
|
||||
ForeignKey, # Necessário para a chave estrangeira
|
||||
)
|
||||
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
# Importa Base do MySQL (assumindo que o caminho 'database.mysql' é o correto)
|
||||
from database.mysql import Base
|
||||
|
||||
|
||||
class AtoDocumento(Base):
|
||||
"""
|
||||
Representa o modelo da tabela 'ato_documento' no banco de dados MySQL.
|
||||
Mapeia a DDL fornecida.
|
||||
"""
|
||||
|
||||
__tablename__ = "ato_documento"
|
||||
|
||||
# ato_documento_id bigint unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY
|
||||
ato_documento_id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||
|
||||
# ato_principal_id bigint NOT NULL, FOREIGN KEY
|
||||
# Mapeamento da chave estrangeira
|
||||
ato_principal_id = Column(
|
||||
BigInteger, ForeignKey("ato_principal.ato_principal_id"), nullable=False
|
||||
)
|
||||
|
||||
# url text NOT NULL (URL pública HTTPS do documento)
|
||||
url = Column(Text, nullable=False)
|
||||
|
||||
# nome_documento varchar(255) NOT NULL (Nome do arquivo PDF)
|
||||
nome_documento = Column(String(255), nullable=False)
|
||||
|
||||
# tipo_documento varchar(50) NOT NULL (Tipo textual do documento)
|
||||
tipo_documento = Column(String(50), nullable=False)
|
||||
|
||||
# created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
created_at = Column(DateTime, server_default=func.now(), nullable=False)
|
||||
|
||||
# updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
updated_at = Column(
|
||||
DateTime,
|
||||
server_default=func.now(), # Default CURRENT_TIMESTAMP
|
||||
onupdate=func.now(), # ON UPDATE CURRENT_TIMESTAMP
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
"""Representação legível do objeto."""
|
||||
return (
|
||||
f"<AtoDocumento(ato_documento_id={self.ato_documento_id}, "
|
||||
f"ato_principal_id={self.ato_principal_id}, "
|
||||
f"tipo_documento='{self.tipo_documento}')>"
|
||||
)
|
||||
61
packages/v1/administrativo/models/ato_parte_model.py
Normal file
61
packages/v1/administrativo/models/ato_parte_model.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# packages/v1/administrativo/models/ato_parte_model.py
|
||||
# Gerado a partir da DDL da tabela 'ato_parte'
|
||||
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
BigInteger,
|
||||
String,
|
||||
DateTime,
|
||||
ForeignKey,
|
||||
)
|
||||
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
# Importa Base do MySQL (assumindo que o caminho 'database.mysql' é o correto)
|
||||
from database.mysql import Base
|
||||
|
||||
|
||||
class AtoParte(Base):
|
||||
"""
|
||||
Representa o modelo da tabela 'ato_parte' no banco de dados MySQL.
|
||||
Mapeia a DDL fornecida.
|
||||
"""
|
||||
|
||||
__tablename__ = "ato_parte"
|
||||
|
||||
# ato_parte_id bigint NOT NULL AUTO_INCREMENT, PRIMARY KEY
|
||||
ato_parte_id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||
|
||||
# ato_principal_id bigint NOT NULL, FOREIGN KEY
|
||||
# Mapeamento da chave estrangeira
|
||||
ato_principal_id = Column(
|
||||
BigInteger, ForeignKey("ato_principal.ato_principal_id"), nullable=False
|
||||
)
|
||||
|
||||
# nome varchar(255) NOT NULL (Nome completo da parte envolvida no ato.)
|
||||
nome = Column(String(255), nullable=False)
|
||||
|
||||
# telefone varchar(20) DEFAULT NULL (Telefone da parte com DDI e DDD.)
|
||||
telefone = Column(String(20), nullable=True)
|
||||
|
||||
# cpf_cnpj varchar(20) NOT NULL (CPF ou CNPJ da parte, contendo apenas números.)
|
||||
cpf_cnpj = Column(String(20), nullable=False)
|
||||
|
||||
# created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
created_at = Column(DateTime, server_default=func.now(), nullable=False)
|
||||
|
||||
# updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
updated_at = Column(
|
||||
DateTime,
|
||||
server_default=func.now(), # Default CURRENT_TIMESTAMP
|
||||
onupdate=func.now(), # ON UPDATE CURRENT_TIMESTAMP
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
"""Representação legível do objeto."""
|
||||
return (
|
||||
f"<AtoParte(ato_parte_id={self.ato_parte_id}, "
|
||||
f"ato_principal_id={self.ato_principal_id}, "
|
||||
f"nome='{self.nome}')>"
|
||||
)
|
||||
|
|
@ -11,26 +11,36 @@ from sqlalchemy import (
|
|||
ForeignKey,
|
||||
CheckConstraint,
|
||||
)
|
||||
from sqlalchemy.dialects.postgresql import INET
|
||||
|
||||
# No MySQL, usaremos String(45) para armazenar endereços IPv4/IPv6
|
||||
from sqlalchemy.sql import func
|
||||
from database.postgres import Base
|
||||
|
||||
# Atualize para importar Base do MySQL
|
||||
from database.mysql import Base
|
||||
|
||||
|
||||
class AtoPrincipal(Base):
|
||||
"""
|
||||
Representa o modelo da tabela 'ato_principal' no banco de dados PostgreSQL.
|
||||
Representa o modelo da tabela 'ato_principal' no banco de dados MySQL.
|
||||
"""
|
||||
|
||||
__tablename__ = "ato_principal"
|
||||
|
||||
ato_principal_id = Column(BigInteger, primary_key=True, autoincrement=True, index=True)
|
||||
# ID principal do ato
|
||||
ato_principal_id = Column(
|
||||
BigInteger, primary_key=True, autoincrement=True, index=True
|
||||
)
|
||||
|
||||
# Relacionamento com o próprio ato (auto-relacionamento)
|
||||
origem_ato_principal_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey("ato_principal.ato_principal_id", ondelete="SET NULL", onupdate="CASCADE"),
|
||||
ForeignKey(
|
||||
"ato_principal.ato_principal_id", ondelete="SET NULL", onupdate="CASCADE"
|
||||
),
|
||||
nullable=True,
|
||||
)
|
||||
|
||||
# Campos principais
|
||||
identificacao_pedido_cgj = Column(BigInteger, nullable=False)
|
||||
tipo_ato = Column(Integer, nullable=False)
|
||||
codigo_selo = Column(String(50), nullable=False, unique=True)
|
||||
|
|
@ -38,19 +48,36 @@ class AtoPrincipal(Base):
|
|||
nome_civil_ato = Column(String(255), nullable=False)
|
||||
nome_serventuario_praticou_ato = Column(String(255), nullable=False)
|
||||
data_solicitacao = Column(DateTime(timezone=True), nullable=False)
|
||||
ip_maquina = Column(INET, nullable=True)
|
||||
|
||||
# Substituído INET por String(45)
|
||||
# O tamanho 45 cobre IPv6, IPv4 e localhost
|
||||
ip_maquina = Column(String(45), nullable=True)
|
||||
|
||||
# Conteúdo principal do ato
|
||||
inteiro_teor = Column(Text, nullable=False)
|
||||
|
||||
# Valores financeiros
|
||||
valor_entrada = Column(Numeric(12, 2), nullable=True, default=0)
|
||||
emolumento = Column(Numeric(12, 2), nullable=False)
|
||||
taxa_judiciaria = Column(Numeric(12, 2), nullable=False)
|
||||
fundos_estaduais = Column(Numeric(12, 2), nullable=False)
|
||||
|
||||
# Protocolos opcionais
|
||||
protocolo_protesto = Column(String(50), nullable=True)
|
||||
protocolo_imovel = Column(String(50), nullable=True)
|
||||
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
|
||||
# Controle de auditoria
|
||||
created_at = Column(
|
||||
DateTime(timezone=True), server_default=func.now(), nullable=False
|
||||
)
|
||||
updated_at = Column(
|
||||
DateTime(timezone=True),
|
||||
server_default=func.now(),
|
||||
onupdate=func.now(),
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
# Constraints e índices adicionais
|
||||
# Mantém constraint de valores positivos
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"(COALESCE(valor_entrada, 0) >= 0) AND (emolumento >= 0) AND (taxa_judiciaria >= 0) AND (fundos_estaduais >= 0)",
|
||||
|
|
@ -59,6 +86,7 @@ class AtoPrincipal(Base):
|
|||
)
|
||||
|
||||
def __repr__(self):
|
||||
"""Representação legível do objeto."""
|
||||
return (
|
||||
f"<AtoPrincipal(id={self.ato_principal_id}, "
|
||||
f"codigo_ato='{self.codigo_ato}', selo='{self.codigo_selo}', tipo={self.tipo_ato})>"
|
||||
|
|
|
|||
59
packages/v1/administrativo/models/usuario_model.py
Normal file
59
packages/v1/administrativo/models/usuario_model.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# packages/v1/administrativo/models/usuario_model.py
|
||||
# Gerado a partir da DDL corrigida da tabela 'usuario'
|
||||
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
BigInteger, # Alterado para BigInteger para usuario_id e IDs de auditoria
|
||||
String,
|
||||
DateTime,
|
||||
# Não há Text, Numeric ou CheckConstraint nesta DDL
|
||||
)
|
||||
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
# Importa Base do MySQL (assumindo que o caminho 'database.mysql' é o correto)
|
||||
from database.mysql import Base
|
||||
|
||||
|
||||
class Usuario(Base):
|
||||
"""
|
||||
Representa o modelo da tabela 'usuario' no banco de dados MySQL.
|
||||
Mapeia a DDL corrigida.
|
||||
"""
|
||||
|
||||
__tablename__ = "usuario"
|
||||
|
||||
# usuario_id bigint NOT NULL AUTO_INCREMENT, PRIMARY KEY
|
||||
usuario_id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||
|
||||
# Campos principais (varchar)
|
||||
nome = Column(String(255), nullable=True)
|
||||
email = Column(String(255), nullable=True)
|
||||
username = Column(String(120), nullable=True)
|
||||
password = Column(String(255), nullable=True)
|
||||
|
||||
# status varchar(1) NOT NULL DEFAULT 'A'
|
||||
status = Column(String(1), nullable=False, default="A")
|
||||
|
||||
# date_register datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
date_register = Column(DateTime(), server_default=func.now(), nullable=False)
|
||||
|
||||
# date_update datetime DEFAULT NULL
|
||||
date_update = Column(DateTime(), onupdate=func.now(), nullable=True)
|
||||
|
||||
# usuario_id_create bigint DEFAULT NULL
|
||||
user_id_create = Column(BigInteger, nullable=True)
|
||||
|
||||
# user_id_update bigint DEFAULT NULL
|
||||
user_id_update = Column(BigInteger, nullable=True)
|
||||
|
||||
# Não há __table_args__ (como CheckConstraint) na DDL original
|
||||
|
||||
def __repr__(self):
|
||||
"""Representação legível do objeto."""
|
||||
return (
|
||||
f"<Usuario(usuario_id={self.usuario_id}, "
|
||||
f"username='{self.username}', "
|
||||
f"email='{self.email}', "
|
||||
f"status='{self.status}')>"
|
||||
)
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.ato_documento_model import AtoDocumento
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
|
||||
|
||||
class DeleteRepository:
|
||||
"""
|
||||
Classe responsável por excluir documentos no banco de dados.
|
||||
Segue a mesma metodologia do SaveRepository/UpdateRepository:
|
||||
- abre sessão
|
||||
- busca registro
|
||||
- trata not found
|
||||
- deleta/commita
|
||||
- rollback em erro
|
||||
- fecha sessão
|
||||
"""
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Buscar documento
|
||||
documento_db = (
|
||||
db.query(AtoDocumento)
|
||||
.filter(
|
||||
AtoDocumento.ato_documento_id
|
||||
== ato_documento_schema.ato_documento_id
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not documento_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Documento não encontrado.",
|
||||
)
|
||||
|
||||
# 2. Excluir (delete físico)
|
||||
db.delete(documento_db)
|
||||
db.commit()
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Documento excluído com sucesso!",
|
||||
"data": {
|
||||
"ato_documento_id": ato_documento_schema.ato_documento_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao excluir documento: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_documento_model import AtoDocumento
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoSchema,
|
||||
)
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
# Mantemos a referência a AES_KEY por consistência do ambiente, mas não a utilizamos.
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class IndexRepository:
|
||||
def execute(self):
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Executa a query, selecionando todos os campos de ato_documento
|
||||
result = db.query(
|
||||
AtoDocumento.ato_documento_id,
|
||||
AtoDocumento.ato_principal_id,
|
||||
func.AES_DECRYPT(AtoDocumento.url, AES_KEY).label("url"),
|
||||
func.AES_DECRYPT(AtoDocumento.nome_documento, AES_KEY).label(
|
||||
"nome_documento"
|
||||
),
|
||||
func.AES_DECRYPT(AtoDocumento.tipo_documento, AES_KEY).label(
|
||||
"tipo_documento"
|
||||
),
|
||||
AtoDocumento.created_at,
|
||||
AtoDocumento.updated_at,
|
||||
).all()
|
||||
|
||||
# Converte os models SQLAlchemy em schemas Pydantic
|
||||
data = [AtoDocumentoSchema.model_validate(obj) for obj in result]
|
||||
|
||||
return data
|
||||
|
||||
finally:
|
||||
# Fecha a sessão após o uso (evita vazamento de conexão)
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import os
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.ato_documento_model import AtoDocumento
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoSaveSchema,
|
||||
)
|
||||
|
||||
# pega do mesmo lugar que o engine pega
|
||||
DB_SETTINGS = get_database_settings()
|
||||
|
||||
# A chave AES não é utilizada neste modelo, mas é mantida por consistência do ambiente
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class SaveRepository:
|
||||
"""
|
||||
Classe responsável por salvar (inserir) novos documentos no banco de dados.
|
||||
"""
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSaveSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# Não há verificações de unicidade específicas para documentos neste contexto.
|
||||
|
||||
# 1) monta o objeto com os dados fornecidos pelo schema
|
||||
new_documento = AtoDocumento(
|
||||
ato_principal_id=ato_documento_schema.ato_principal_id,
|
||||
)
|
||||
|
||||
# Criptografa os dados sensiveis
|
||||
new_documento.url = func.AES_ENCRYPT(ato_documento_schema.url, AES_KEY)
|
||||
new_documento.nome_documento = func.AES_ENCRYPT(
|
||||
ato_documento_schema.nome_documento, AES_KEY
|
||||
)
|
||||
new_documento.tipo_documento = func.AES_ENCRYPT(
|
||||
ato_documento_schema.tipo_documento, AES_KEY
|
||||
)
|
||||
|
||||
# 2) persiste
|
||||
db.add(new_documento)
|
||||
db.commit()
|
||||
db.refresh(new_documento)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Documento criado com sucesso!",
|
||||
"data": {
|
||||
"ato_documento_id": new_documento.ato_documento_id,
|
||||
"ato_principal_id": new_documento.ato_principal_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao salvar documento: {e}",
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
from typing import Optional
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_documento_model import AtoDocumento
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
# AES_KEY não é utilizada neste modelo, mas mantemos o padrão de importação
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class ShowRepository:
|
||||
"""
|
||||
Repositório responsável por buscar um documento pelo ID.
|
||||
Retorna `AtoDocumentoSchema` se encontrar, senão `None`.
|
||||
"""
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. pega o ID que veio do schema
|
||||
ato_documento_id_to_find = ato_documento_schema.ato_documento_id
|
||||
|
||||
# 2. busca no banco, selecionando todos os campos da DDL
|
||||
result = (
|
||||
db.query(
|
||||
AtoDocumento.ato_documento_id,
|
||||
AtoDocumento.ato_principal_id,
|
||||
func.AES_DECRYPT(AtoDocumento.url, AES_KEY).label("url"),
|
||||
func.AES_DECRYPT(AtoDocumento.nome_documento, AES_KEY).label(
|
||||
"nome_documento"
|
||||
),
|
||||
func.AES_DECRYPT(AtoDocumento.tipo_documento, AES_KEY).label(
|
||||
"tipo_documento"
|
||||
),
|
||||
AtoDocumento.created_at,
|
||||
AtoDocumento.updated_at,
|
||||
)
|
||||
.filter(AtoDocumento.ato_documento_id == ato_documento_id_to_find)
|
||||
.first()
|
||||
)
|
||||
|
||||
# 3. se não achou, devolve None (comportamento de SHOW)
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
# 4. se achou, converte para pydantic
|
||||
return AtoDocumentoSchema.model_validate(result)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
from datetime import datetime
|
||||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_documento_model import AtoDocumento
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoUpdateSchema,
|
||||
)
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
# Mantemos a referência a AES_KEY por consistência do ambiente, mas não a utilizamos.
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class UpdateRepository:
|
||||
"""
|
||||
Classe responsável por atualizar documentos no banco de dados.
|
||||
"""
|
||||
|
||||
def execute(
|
||||
self, ato_documento_id: int, ato_documento_schema: AtoDocumentoUpdateSchema
|
||||
):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Busca o documento existente
|
||||
documento_db = (
|
||||
db.query(AtoDocumento)
|
||||
.filter(AtoDocumento.ato_documento_id == ato_documento_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not documento_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Documento não encontrado.",
|
||||
)
|
||||
|
||||
# 2. Atualiza os campos se o valor foi fornecido no schema
|
||||
|
||||
# ato_principal_id (bigint NOT NULL)
|
||||
if ato_documento_schema.ato_principal_id is not None:
|
||||
documento_db.ato_principal_id = ato_documento_schema.ato_principal_id
|
||||
|
||||
# url (text NOT NULL)
|
||||
if ato_documento_schema.url is not None:
|
||||
documento_db.url = func.AES_ENCRYPT(ato_documento_schema.url, AES_KEY)
|
||||
|
||||
# nome_documento (varchar(255) NOT NULL)
|
||||
if ato_documento_schema.nome_documento is not None:
|
||||
documento_db.nome_documento = func.AES_ENCRYPT(
|
||||
ato_documento_schema.nome_documento, AES_KEY
|
||||
)
|
||||
|
||||
# tipo_documento (varchar(50) NOT NULL)
|
||||
if ato_documento_schema.tipo_documento is not None:
|
||||
documento_db.tipo_documento = func.AES_ENCRYPT(
|
||||
ato_documento_schema.tipo_documento, AES_KEY
|
||||
)
|
||||
|
||||
# Nota: updated_at é atualizado automaticamente pelo ORM (onupdate=func.now())
|
||||
|
||||
# 3. Persiste as alterações
|
||||
db.add(documento_db)
|
||||
db.commit()
|
||||
db.refresh(documento_db)
|
||||
|
||||
# 4. Retorna o resultado
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Documento atualizado com sucesso!",
|
||||
"data": {
|
||||
"ato_documento_id": documento_db.ato_documento_id,
|
||||
"ato_principal_id": documento_db.ato_principal_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao atualizar documento: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_documento_model import AtoDocumento
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
# A chave AES não é necessária para este model, mas mantemos as configurações por consistência
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class ShowRepository:
|
||||
|
||||
# O esquema de entrada deve conter o ato_documento_id para a busca
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
|
||||
# 1. Obtém o ID do documento
|
||||
ato_principal_id_to_find = ato_documento_schema.ato_principal_id
|
||||
|
||||
# 2. Executa a query com filtro, selecionando todos os campos do DDL
|
||||
result = (
|
||||
db.query(
|
||||
AtoDocumento.ato_documento_id,
|
||||
AtoDocumento.ato_principal_id,
|
||||
func.AES_DECRYPT(AtoDocumento.url, AES_KEY).label("url"),
|
||||
func.AES_DECRYPT(AtoDocumento.nome_documento, AES_KEY).label(
|
||||
"nome_documento"
|
||||
),
|
||||
func.AES_DECRYPT(AtoDocumento.tipo_documento, AES_KEY).label(
|
||||
"tipo_documento"
|
||||
),
|
||||
AtoDocumento.created_at,
|
||||
AtoDocumento.updated_at,
|
||||
)
|
||||
.filter(AtoDocumento.ato_principal_id == ato_principal_id_to_find)
|
||||
.all()
|
||||
)
|
||||
|
||||
# 3. Verifica se o documento foi encontrado
|
||||
if not result:
|
||||
# Lança uma exceção HTTP 404 (Not Found) se não houver resultado
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Documento '{ato_principal_id_to_find}' não encontrado.",
|
||||
)
|
||||
|
||||
# 4. Converte os models SQLAlchemy em schemas Pydantic
|
||||
data = [AtoDocumentoSchema.model_validate(obj) for obj in result]
|
||||
|
||||
return data
|
||||
|
||||
finally:
|
||||
# Fecha a sessão após o uso (evita vazamento de conexão)
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.ato_parte_model import AtoParte
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
|
||||
|
||||
class DeleteRepository:
|
||||
"""
|
||||
Classe responsável por excluir partes (pessoas físicas ou jurídicas) no banco de dados.
|
||||
Segue a mesma metodologia do SaveRepository/UpdateRepository:
|
||||
- abre sessão
|
||||
- busca registro
|
||||
- trata not found
|
||||
- deleta/commita
|
||||
- rollback em erro
|
||||
- fecha sessão
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Buscar a parte pelo ID
|
||||
parte_db = (
|
||||
db.query(AtoParte)
|
||||
.filter(AtoParte.ato_parte_id == ato_parte_schema.ato_parte_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not parte_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Parte não encontrada.",
|
||||
)
|
||||
|
||||
# 2. Excluir (delete físico)
|
||||
db.delete(parte_db)
|
||||
db.commit()
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Parte excluída com sucesso!",
|
||||
"data": {
|
||||
"ato_parte_id": ato_parte_schema.ato_parte_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao excluir parte: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_parte_model import AtoParte
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteSchema,
|
||||
)
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
# Mantemos a referência a AES_KEY por consistência do ambiente, mas não a utilizamos.
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class IndexRepository:
|
||||
"""
|
||||
Classe responsável por listar todas as partes cadastradas.
|
||||
"""
|
||||
|
||||
def execute(self):
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Executa a query, selecionando todos os campos de ato_parte
|
||||
result = db.query(
|
||||
AtoParte.ato_parte_id,
|
||||
AtoParte.ato_principal_id,
|
||||
func.AES_DECRYPT(AtoParte.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(AtoParte.telefone, AES_KEY).label("telefone"),
|
||||
func.AES_DECRYPT(AtoParte.cpf_cnpj, AES_KEY).label("cpf_cnpj"),
|
||||
AtoParte.created_at,
|
||||
AtoParte.updated_at,
|
||||
).all()
|
||||
|
||||
# Converte os models SQLAlchemy em schemas Pydantic
|
||||
data = [AtoParteSchema.model_validate(obj) for obj in result]
|
||||
|
||||
return data
|
||||
|
||||
finally:
|
||||
# Fecha a sessão após o uso (evita vazamento de conexão)
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
import os
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from packages.v1.administrativo.models.ato_parte_model import AtoParte
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteSaveSchema,
|
||||
)
|
||||
|
||||
# pega do mesmo lugar que o engine pega
|
||||
DB_SETTINGS = get_database_settings()
|
||||
|
||||
# A chave AES não é utilizada neste modelo, mas é mantida por consistência do ambiente
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class SaveRepository:
|
||||
"""
|
||||
Classe responsável por salvar (inserir) novas partes (pessoas físicas ou jurídicas) no banco de dados.
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSaveSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1) monta o objeto com os dados fornecidos pelo schema
|
||||
new_parte = AtoParte(
|
||||
ato_principal_id=ato_parte_schema.ato_principal_id,
|
||||
)
|
||||
|
||||
# Para os campos sensíveis (nomes, telefones, cpf/cnpj), atribui expressão SQL para criptografia
|
||||
new_parte.nome = func.AES_ENCRYPT(ato_parte_schema.nome, AES_KEY)
|
||||
new_parte.telefone = func.AES_ENCRYPT(ato_parte_schema.telefone, AES_KEY)
|
||||
new_parte.cpf_cnpj = func.AES_ENCRYPT(ato_parte_schema.cpf_cnpj, AES_KEY)
|
||||
|
||||
# 2) persiste
|
||||
db.add(new_parte)
|
||||
db.commit()
|
||||
db.refresh(new_parte)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Parte criada com sucesso!",
|
||||
"data": {
|
||||
"ato_parte_id": new_parte.ato_parte_id,
|
||||
"ato_principal_id": new_parte.ato_principal_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao salvar parte: {e}",
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
from typing import Optional
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_parte_model import AtoParte
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
# AES_KEY não é utilizada neste modelo, mas mantemos o padrão de importação
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class ShowRepository:
|
||||
"""
|
||||
Repositório responsável por buscar uma parte (pessoa física ou jurídica) pelo ID.
|
||||
Retorna `AtoParteSchema` se encontrar, senão `None`.
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Pega o ID que veio do schema
|
||||
ato_parte_id_to_find = ato_parte_schema.ato_parte_id
|
||||
|
||||
# 2. Busca no banco, selecionando todos os campos da DDL
|
||||
result = (
|
||||
db.query(
|
||||
AtoParte.ato_parte_id,
|
||||
AtoParte.ato_principal_id,
|
||||
func.AES_DECRYPT(AtoParte.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(AtoParte.telefone, AES_KEY).label("telefone"),
|
||||
func.AES_DECRYPT(AtoParte.cpf_cnpj, AES_KEY).label("cpf_cnpj"),
|
||||
AtoParte.created_at,
|
||||
AtoParte.updated_at,
|
||||
)
|
||||
.filter(AtoParte.ato_parte_id == ato_parte_id_to_find)
|
||||
.first()
|
||||
)
|
||||
|
||||
# 3. Se não achou, devolve None (comportamento de SHOW)
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
# 4. Se achou, converte para pydantic
|
||||
return AtoParteSchema.model_validate(result)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
from datetime import datetime
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from packages.v1.administrativo.models.ato_parte_model import AtoParte
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteUpdateSchema,
|
||||
)
|
||||
|
||||
# pega do mesmo lugar que o engine pega
|
||||
DB_SETTINGS = get_database_settings()
|
||||
|
||||
# A chave AES não é utilizada neste modelo, mas é mantida por consistência do ambiente
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class UpdateRepository:
|
||||
"""
|
||||
Classe responsável por atualizar partes no banco de dados.
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_id: int, ato_parte_schema: AtoParteUpdateSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Busca a parte existente
|
||||
parte_db = (
|
||||
db.query(AtoParte).filter(AtoParte.ato_parte_id == ato_parte_id).first()
|
||||
)
|
||||
|
||||
if not parte_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Parte não encontrada.",
|
||||
)
|
||||
|
||||
# 2. Atualiza os campos se o valor foi fornecido no schema
|
||||
|
||||
# ato_principal_id (bigint NOT NULL)
|
||||
if ato_parte_schema.ato_principal_id is not None:
|
||||
parte_db.ato_principal_id = ato_parte_schema.ato_principal_id
|
||||
|
||||
# nome (varchar(255) NOT NULL)
|
||||
if ato_parte_schema.nome is not None:
|
||||
parte_db.nome = func.AES_ENCRYPT(ato_parte_schema.nome, AES_KEY)
|
||||
|
||||
# telefone (varchar(20) DEFAULT NULL)
|
||||
if ato_parte_schema.telefone is not None:
|
||||
parte_db.telefone = func.AES_ENCRYPT(ato_parte_schema.telefone, AES_KEY)
|
||||
|
||||
# cpf_cnpj (varchar(20) NOT NULL)
|
||||
if ato_parte_schema.cpf_cnpj is not None:
|
||||
parte_db.cpf_cnpj = func.AES_ENCRYPT(ato_parte_schema.cpf_cnpj, AES_KEY)
|
||||
|
||||
# Nota: updated_at é atualizado automaticamente pelo ORM (onupdate=func.now() ou similar)
|
||||
|
||||
# 3. Persiste as alterações
|
||||
db.add(parte_db)
|
||||
db.commit()
|
||||
db.refresh(parte_db)
|
||||
|
||||
# 4. Retorna o resultado
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Parte atualizada com sucesso!",
|
||||
"data": {
|
||||
"ato_parte_id": parte_db.ato_parte_id,
|
||||
"ato_principal_id": parte_db.ato_principal_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao atualizar parte: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_parte_model import AtoParte
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
# A chave AES não é necessária para este model, mas mantemos as configurações por consistência
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class ShowRepository:
|
||||
"""
|
||||
Classe responsável por buscar partes de um ato principal no banco de dados.
|
||||
"""
|
||||
|
||||
# O esquema de entrada deve conter o ato_principal_id para a busca
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
|
||||
# 1. Obtém o ID do ato principal
|
||||
ato_principal_id_to_find = ato_parte_schema.ato_principal_id
|
||||
|
||||
# 2. Executa a query com filtro, selecionando todos os campos do DDL
|
||||
result = (
|
||||
db.query(
|
||||
AtoParte.ato_parte_id,
|
||||
AtoParte.ato_principal_id,
|
||||
func.AES_DECRYPT(AtoParte.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(AtoParte.telefone, AES_KEY).label("telefone"),
|
||||
func.AES_DECRYPT(AtoParte.cpf_cnpj, AES_KEY).label("cpf_cnpj"),
|
||||
AtoParte.created_at,
|
||||
AtoParte.updated_at,
|
||||
)
|
||||
.filter(AtoParte.ato_principal_id == ato_principal_id_to_find)
|
||||
.all()
|
||||
)
|
||||
|
||||
# 3. Verifica se o resultado foi encontrado
|
||||
if not result:
|
||||
# Lança uma exceção HTTP 404 (Not Found) se não houver resultado
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Nenhuma parte encontrada para o ato principal ID '{ato_principal_id_to_find}'.",
|
||||
)
|
||||
|
||||
# 4. Converte os models SQLAlchemy em schemas Pydantic
|
||||
# Nota: É importante que o schema 'AtoParteSchema' esteja pronto para receber todos os campos.
|
||||
data = [AtoParteSchema.model_validate(obj) for obj in result]
|
||||
|
||||
return data
|
||||
|
||||
finally:
|
||||
# Fecha a sessão após o uso (evita vazamento de conexão)
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.ato_principal_model import AtoPrincipal
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import AtoPrincipalIdSchema
|
||||
|
||||
|
||||
class DeleteRepository:
|
||||
"""
|
||||
Classe responsável por excluir atos principais no banco de dados.
|
||||
Segue a mesma metodologia do SaveRepository/UpdateRepository:
|
||||
- abre sessão
|
||||
- busca registro
|
||||
- trata not found
|
||||
- deleta/commita
|
||||
- rollback em erro
|
||||
- fecha sessão
|
||||
"""
|
||||
|
||||
def execute(self, ato_principal_schema: AtoPrincipalIdSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Buscar ato principal
|
||||
ato_principal_db = (
|
||||
db.query(AtoPrincipal)
|
||||
.filter(
|
||||
AtoPrincipal.ato_principal_id
|
||||
== ato_principal_schema.ato_principal_id
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not ato_principal_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Ato principal não encontrado.",
|
||||
)
|
||||
|
||||
# 2. Excluir (delete físico)
|
||||
db.delete(ato_principal_db)
|
||||
db.commit()
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Ato principal excluído com sucesso!",
|
||||
"data": {
|
||||
"ato_principal_id": ato_principal_schema.ato_principal_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao excluir ato principal: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -1,18 +1,49 @@
|
|||
from database.postgres import SessionLocal
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_principal_model import AtoPrincipal
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import AtoPrincipalResponseSchema
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSchema,
|
||||
)
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class AtoPrincipalIndexRepository:
|
||||
class IndexRepository:
|
||||
def execute(self):
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Executa a query
|
||||
result = db.query(AtoPrincipal).all()
|
||||
result = db.query(
|
||||
AtoPrincipal.ato_principal_id,
|
||||
AtoPrincipal.origem_ato_principal_id,
|
||||
AtoPrincipal.identificacao_pedido_cgj,
|
||||
AtoPrincipal.tipo_ato,
|
||||
AtoPrincipal.codigo_selo,
|
||||
AtoPrincipal.codigo_ato,
|
||||
func.AES_DECRYPT(AtoPrincipal.nome_civil_ato, AES_KEY).label(
|
||||
"nome_civil_ato"
|
||||
),
|
||||
func.AES_DECRYPT(
|
||||
AtoPrincipal.nome_serventuario_praticou_ato, AES_KEY
|
||||
).label("nome_serventuario_praticou_ato"),
|
||||
AtoPrincipal.data_solicitacao,
|
||||
AtoPrincipal.ip_maquina,
|
||||
AtoPrincipal.inteiro_teor,
|
||||
AtoPrincipal.valor_entrada,
|
||||
AtoPrincipal.emolumento,
|
||||
AtoPrincipal.taxa_judiciaria,
|
||||
AtoPrincipal.fundos_estaduais,
|
||||
AtoPrincipal.protocolo_protesto,
|
||||
AtoPrincipal.protocolo_imovel,
|
||||
AtoPrincipal.created_at,
|
||||
AtoPrincipal.updated_at,
|
||||
).all()
|
||||
|
||||
# Converte os models SQLAlchemy em schemas Pydantic
|
||||
data = [AtoPrincipalResponseSchema.model_validate(obj) for obj in result]
|
||||
data = [AtoPrincipalSchema.model_validate(obj) for obj in result]
|
||||
|
||||
return data
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,200 @@
|
|||
from typing import List, Optional
|
||||
from fastapi import HTTPException, status
|
||||
import traceback
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import Session # Importação para tipagem da session
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from packages.v1.administrativo.models.ato_principal_model import AtoPrincipal
|
||||
from packages.v1.administrativo.models.ato_parte_model import AtoParte
|
||||
from packages.v1.administrativo.models.ato_documento_model import AtoDocumento
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSaveSchema,
|
||||
)
|
||||
|
||||
# Configuração da Chave AES
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class SaveMultipleRepository:
|
||||
"""
|
||||
Repositório para salvar múltiplos atos principais com suas partes e documentos,
|
||||
usando criptografia nativa do MySQL via AES_ENCRYPT.
|
||||
Implementa lógica recursiva para atos vinculados.
|
||||
"""
|
||||
|
||||
def _save_single_recursive_transaction(
|
||||
self,
|
||||
db: Session,
|
||||
ato_schema: AtoPrincipalSaveSchema,
|
||||
parent_ato_principal_id: Optional[int] = None,
|
||||
) -> AtoPrincipal:
|
||||
"""
|
||||
Salva um único Ato Principal, seus filhos (partes/documentos) e
|
||||
chama recursivamente o salvamento dos atos vinculados.
|
||||
"""
|
||||
codigo_selo = ato_schema.codigo_selo
|
||||
|
||||
# 1. Pré-processamento e Criptografia
|
||||
ato_data = ato_schema.model_dump(
|
||||
exclude_unset=True,
|
||||
exclude={"ato_partes", "ato_documentos", "atos_vinculados"},
|
||||
)
|
||||
|
||||
# Define o ID de origem se for um ato vinculado
|
||||
if parent_ato_principal_id is not None:
|
||||
ato_data["origem_ato_principal_id"] = parent_ato_principal_id
|
||||
elif ato_data.get("origem_ato_principal_id") is None:
|
||||
ato_data["origem_ato_principal_id"] = None
|
||||
|
||||
# Verifica duplicidade usando descriptografia
|
||||
existing_ato = (
|
||||
db.query(AtoPrincipal)
|
||||
.filter(func.aes_decrypt(AtoPrincipal.codigo_selo, AES_KEY) == codigo_selo)
|
||||
.first()
|
||||
)
|
||||
|
||||
if existing_ato:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=f"O Código do Selo '{codigo_selo}' já está cadastrado.",
|
||||
)
|
||||
|
||||
campos_criptografar = [
|
||||
"nome_civil_ato",
|
||||
"nome_serventuario_praticou_ato",
|
||||
]
|
||||
|
||||
# Criptografa os campos de texto necessários
|
||||
for campo in campos_criptografar:
|
||||
valor = ato_data.get(campo)
|
||||
if isinstance(valor, str) and valor.strip():
|
||||
ato_data[campo] = func.aes_encrypt(valor, AES_KEY)
|
||||
elif campo not in ato_data or valor is None:
|
||||
ato_data[campo] = None
|
||||
|
||||
# 2. Criação e Persistência do Ato Principal
|
||||
new_ato = AtoPrincipal(**ato_data)
|
||||
db.add(new_ato)
|
||||
db.flush()
|
||||
new_ato_id = new_ato.ato_principal_id
|
||||
|
||||
# 3. Salva os Filhos Diretos: Ato Partes
|
||||
for parte in ato_schema.ato_partes:
|
||||
parte_data = parte.model_dump(exclude_unset=True)
|
||||
|
||||
parte_campos_criptografar = ["nome", "telefone", "cpf_cnpj"]
|
||||
|
||||
for campo in parte_campos_criptografar:
|
||||
valor = parte_data.get(campo)
|
||||
# A validação/conversão para string já foi feita pelo Pydantic,
|
||||
# mas mantemos a checagem de tipo e strip para segurança antes da criptografia
|
||||
if isinstance(valor, str) and valor.strip():
|
||||
parte_data[campo] = func.aes_encrypt(valor, AES_KEY)
|
||||
else:
|
||||
parte_data[campo] = None
|
||||
|
||||
new_parte = AtoParte(**parte_data, ato_principal_id=new_ato_id)
|
||||
db.add(new_parte)
|
||||
|
||||
# 4. Salva os Filhos Diretos: Ato Documentos
|
||||
for doc in ato_schema.ato_documentos:
|
||||
doc_data = doc.model_dump(exclude_unset=True)
|
||||
|
||||
doc_campos_criptografar = ["url", "nome_documento", "tipo_documento"]
|
||||
|
||||
for campo in doc_campos_criptografar:
|
||||
valor = doc_data.get(campo)
|
||||
if isinstance(valor, str) and valor.strip():
|
||||
doc_data[campo] = func.aes_encrypt(valor, AES_KEY)
|
||||
else:
|
||||
doc_data[campo] = None
|
||||
|
||||
new_documento = AtoDocumento(**doc_data, ato_principal_id=new_ato_id)
|
||||
db.add(new_documento)
|
||||
|
||||
# 5. Lógica Recursiva para Atos Vinculados (Estrutura de loop idêntica)
|
||||
if ato_schema.atos_vinculados:
|
||||
print(f"--- Iniciando salvamento recursivo para {new_ato_id} ---")
|
||||
|
||||
# A iteração é semelhante, mas o que é executado é a chamada recursiva
|
||||
for linked_ato_schema in ato_schema.atos_vinculados:
|
||||
# O ato vinculado é persistido chamando a rotina de salvamento completa
|
||||
self._save_single_recursive_transaction(
|
||||
db,
|
||||
linked_ato_schema,
|
||||
parent_ato_principal_id=new_ato_id,
|
||||
)
|
||||
|
||||
print(f"--- Fim do salvamento recursivo para {new_ato_id} ---")
|
||||
|
||||
return new_ato
|
||||
|
||||
# Método principal (chamado pela Action)
|
||||
def execute(self, atos_principais: List[AtoPrincipalSaveSchema]):
|
||||
db = SessionLocal()
|
||||
results = []
|
||||
|
||||
# 1. Checa a chave AES
|
||||
if not AES_KEY:
|
||||
db.close()
|
||||
raise Exception("A chave AES (aeskey) não está configurada.")
|
||||
|
||||
# 2. Loop principal: Cada iteração é uma transação completa (incluindo recursão)
|
||||
for ato_schema in atos_principais:
|
||||
codigo_selo_log = getattr(ato_schema, "codigo_selo", "SELO_INDISPONÍVEL")
|
||||
|
||||
try:
|
||||
# A rotina completa de salvamento (incluindo filhos e recursão) é encapsulada
|
||||
saved_ato = self._save_single_recursive_transaction(
|
||||
db,
|
||||
ato_schema,
|
||||
parent_ato_principal_id=None, # Ato de nível superior
|
||||
)
|
||||
|
||||
# ---------- COMMIT final para a transação completa (Ato Principal + Filhos + Atos Vinculados) ----------
|
||||
db.commit()
|
||||
|
||||
# Retorno de sucesso
|
||||
ato_result = {
|
||||
"success": True,
|
||||
"message": "Ato Principal e vinculados salvos com sucesso",
|
||||
"data": {
|
||||
"ato_principal_id": saved_ato.ato_principal_id,
|
||||
"codigo_selo": codigo_selo_log,
|
||||
"tipo_ato": saved_ato.tipo_ato,
|
||||
},
|
||||
}
|
||||
results.append(ato_result)
|
||||
|
||||
# Tratamento de erro específico para duplicidade ou HTTP
|
||||
except HTTPException as he:
|
||||
db.rollback()
|
||||
results.append(
|
||||
{
|
||||
"success": False,
|
||||
"error": he.detail,
|
||||
"data": {"codigo_selo": codigo_selo_log},
|
||||
}
|
||||
)
|
||||
|
||||
# Tratamento de erro genérico
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
|
||||
# Log completo do erro
|
||||
print("====")
|
||||
print(f"ERRO DE PERSISTÊNCIA NO SELO: {codigo_selo_log}")
|
||||
traceback.print_exc()
|
||||
print("----")
|
||||
|
||||
results.append(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Erro ao salvar o registro. Verifique o formato dos dados ou os logs do servidor.",
|
||||
"data": {"codigo_selo": codigo_selo_log},
|
||||
}
|
||||
)
|
||||
|
||||
db.close()
|
||||
return results
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
import os
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.ato_principal_model import AtoPrincipal
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSaveSchema,
|
||||
)
|
||||
|
||||
# pega do mesmo lugar que o engine pega
|
||||
DB_SETTINGS = get_database_settings()
|
||||
|
||||
# pega aeskey de forma compatível com SimpleNamespace
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class SaveRepository:
|
||||
"""
|
||||
Classe responsável por salvar (inserir) novos atos principais no banco de dados.
|
||||
Campos de nome criptografados via AES_ENCRYPT (nativo MySQL) usando só ORM.
|
||||
"""
|
||||
|
||||
def execute(self, ato_principal_schema: AtoPrincipalSaveSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1) verifica codigo_selo (texto puro)
|
||||
existing_by_selo = (
|
||||
db.query(AtoPrincipal)
|
||||
.filter(AtoPrincipal.codigo_selo == ato_principal_schema.codigo_selo)
|
||||
.first()
|
||||
)
|
||||
if existing_by_selo:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Já existe um ato principal com esse código de selo.",
|
||||
)
|
||||
|
||||
# 2) verifica codigo_ato (texto puro)
|
||||
existing_by_codigo = (
|
||||
db.query(AtoPrincipal)
|
||||
.filter(AtoPrincipal.codigo_ato == ato_principal_schema.codigo_ato)
|
||||
.first()
|
||||
)
|
||||
if existing_by_codigo:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Já existe um ato principal com esse código de ato.",
|
||||
)
|
||||
|
||||
# 3) monta o objeto com todos os campos da DDL
|
||||
new_ato = AtoPrincipal(
|
||||
origem_ato_principal_id=ato_principal_schema.origem_ato_principal_id,
|
||||
identificacao_pedido_cgj=ato_principal_schema.identificacao_pedido_cgj,
|
||||
tipo_ato=ato_principal_schema.tipo_ato,
|
||||
codigo_selo=ato_principal_schema.codigo_selo,
|
||||
codigo_ato=ato_principal_schema.codigo_ato,
|
||||
data_solicitacao=ato_principal_schema.data_solicitacao,
|
||||
ip_maquina=ato_principal_schema.ip_maquina,
|
||||
inteiro_teor=ato_principal_schema.inteiro_teor,
|
||||
valor_entrada=ato_principal_schema.valor_entrada,
|
||||
emolumento=ato_principal_schema.emolumento,
|
||||
taxa_judiciaria=ato_principal_schema.taxa_judiciaria,
|
||||
fundos_estaduais=ato_principal_schema.fundos_estaduais,
|
||||
protocolo_protesto=ato_principal_schema.protocolo_protesto,
|
||||
protocolo_imovel=ato_principal_schema.protocolo_imovel,
|
||||
)
|
||||
|
||||
# 4) para os campos sensíveis (nomes), atribui expressão SQL para criptografia
|
||||
new_ato.nome_civil_ato = func.AES_ENCRYPT(
|
||||
ato_principal_schema.nome_civil_ato, AES_KEY
|
||||
)
|
||||
new_ato.nome_serventuario_praticou_ato = func.AES_ENCRYPT(
|
||||
ato_principal_schema.nome_serventuario_praticou_ato, AES_KEY
|
||||
)
|
||||
|
||||
# 5) persiste
|
||||
db.add(new_ato)
|
||||
db.commit()
|
||||
db.refresh(new_ato)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Ato principal criado com sucesso!",
|
||||
"data": {
|
||||
"ato_principal_id": new_ato.ato_principal_id,
|
||||
"codigo_selo": ato_principal_schema.codigo_selo,
|
||||
"codigo_ato": ato_principal_schema.codigo_ato,
|
||||
"nome_civil_ato": ato_principal_schema.nome_civil_ato,
|
||||
"data_solicitacao": ato_principal_schema.data_solicitacao.isoformat(),
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao salvar ato principal: {e}",
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
from typing import Optional
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.ato_principal_model import AtoPrincipal
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import AtoPrincipalSchema
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalIdSchema,
|
||||
) # Assumindo um schema para receber o ID
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
# A chave AES (AES_KEY) não será utilizada neste repositório,
|
||||
# pois nenhum campo da tabela 'ato_principal' parece requerer
|
||||
# criptografia/decriptografia no banco de dados, ao contrário
|
||||
# do 'usuario' original.
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class ShowRepository:
|
||||
"""
|
||||
Repositório responsável por buscar um ato principal pelo ato_principal_id.
|
||||
Retorna `AtoPrincipalSchema` se encontrar, senão `None`.
|
||||
"""
|
||||
|
||||
# O esquema de entrada deve ser aquele que contém o ID necessário.
|
||||
def execute(
|
||||
self, ato_principal_id_schema: AtoPrincipalIdSchema
|
||||
) -> Optional[AtoPrincipalSchema]:
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. pega o ID que veio do schema de entrada
|
||||
# Ajuste: Assumindo que o schema de entrada (AtoPrincipalIdSchema) tem o campo 'ato_principal_id'
|
||||
ato_principal_id_to_find = ato_principal_id_schema.ato_principal_id
|
||||
|
||||
# 2. busca no banco, selecionando explicitamente todos os campos da DDL
|
||||
result = (
|
||||
db.query(
|
||||
AtoPrincipal.ato_principal_id,
|
||||
AtoPrincipal.origem_ato_principal_id,
|
||||
AtoPrincipal.identificacao_pedido_cgj,
|
||||
AtoPrincipal.tipo_ato,
|
||||
AtoPrincipal.codigo_selo,
|
||||
AtoPrincipal.codigo_ato,
|
||||
func.AES_DECRYPT(AtoPrincipal.nome_civil_ato, AES_KEY).label(
|
||||
"nome_civil_ato"
|
||||
),
|
||||
func.AES_DECRYPT(
|
||||
AtoPrincipal.nome_serventuario_praticou_ato, AES_KEY
|
||||
).label("nome_serventuario_praticou_ato"),
|
||||
AtoPrincipal.data_solicitacao,
|
||||
AtoPrincipal.ip_maquina,
|
||||
AtoPrincipal.inteiro_teor,
|
||||
AtoPrincipal.valor_entrada,
|
||||
AtoPrincipal.emolumento,
|
||||
AtoPrincipal.taxa_judiciaria,
|
||||
AtoPrincipal.fundos_estaduais,
|
||||
AtoPrincipal.protocolo_protesto,
|
||||
AtoPrincipal.protocolo_imovel,
|
||||
AtoPrincipal.created_at,
|
||||
AtoPrincipal.updated_at,
|
||||
)
|
||||
.filter(AtoPrincipal.ato_principal_id == ato_principal_id_to_find)
|
||||
.first()
|
||||
)
|
||||
|
||||
# 3. se não achou, devolve None
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
# 4. se achou, converte para pydantic
|
||||
# (Assumindo que AtoPrincipalSchema tem Config.from_attributes = True)
|
||||
return AtoPrincipalSchema.model_validate(result)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from packages.v1.administrativo.models.ato_principal_model import AtoPrincipal
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalUpdateSchema,
|
||||
)
|
||||
|
||||
# pega as configurações do banco
|
||||
DB_SETTINGS = get_database_settings()
|
||||
# pega a chave AES do banco (mesma usada no save)
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class UpdateRepository:
|
||||
"""
|
||||
Classe responsável por atualizar atos principais no banco de dados.
|
||||
Campos de nome são criptografados com AES_ENCRYPT (nativo MySQL).
|
||||
"""
|
||||
|
||||
def execute(
|
||||
self, ato_principal_id: int, ato_principal_schema: AtoPrincipalUpdateSchema
|
||||
) -> Dict[str, Any]:
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Busca o ato principal existente
|
||||
ato_principal_db = (
|
||||
db.query(AtoPrincipal)
|
||||
.filter(AtoPrincipal.ato_principal_id == ato_principal_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not ato_principal_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Ato principal não encontrado.",
|
||||
)
|
||||
|
||||
# 2. Verifica duplicidade de codigo_selo e codigo_ato
|
||||
if ato_principal_schema.codigo_selo or ato_principal_schema.codigo_ato:
|
||||
duplicidade_selo = None
|
||||
if ato_principal_schema.codigo_selo:
|
||||
duplicidade_selo = (
|
||||
db.query(AtoPrincipal)
|
||||
.filter(AtoPrincipal.ato_principal_id != ato_principal_id)
|
||||
.filter(
|
||||
AtoPrincipal.codigo_selo == ato_principal_schema.codigo_selo
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
duplicidade_ato = None
|
||||
if ato_principal_schema.codigo_ato and not duplicidade_selo:
|
||||
duplicidade_ato = (
|
||||
db.query(AtoPrincipal)
|
||||
.filter(AtoPrincipal.ato_principal_id != ato_principal_id)
|
||||
.filter(
|
||||
AtoPrincipal.codigo_ato == ato_principal_schema.codigo_ato
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if duplicidade_selo or duplicidade_ato:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Já existe outro ato principal com este código de selo ou código de ato.",
|
||||
)
|
||||
|
||||
# 3. Atualiza campos comuns (não criptografados)
|
||||
if ato_principal_schema.origem_ato_principal_id is not None:
|
||||
ato_principal_db.origem_ato_principal_id = (
|
||||
ato_principal_schema.origem_ato_principal_id
|
||||
)
|
||||
|
||||
if ato_principal_schema.identificacao_pedido_cgj is not None:
|
||||
ato_principal_db.identificacao_pedido_cgj = (
|
||||
ato_principal_schema.identificacao_pedido_cgj
|
||||
)
|
||||
|
||||
if ato_principal_schema.tipo_ato is not None:
|
||||
ato_principal_db.tipo_ato = ato_principal_schema.tipo_ato
|
||||
|
||||
if ato_principal_schema.codigo_selo is not None:
|
||||
ato_principal_db.codigo_selo = ato_principal_schema.codigo_selo
|
||||
|
||||
if ato_principal_schema.codigo_ato is not None:
|
||||
ato_principal_db.codigo_ato = ato_principal_schema.codigo_ato
|
||||
|
||||
if ato_principal_schema.data_solicitacao is not None:
|
||||
ato_principal_db.data_solicitacao = (
|
||||
ato_principal_schema.data_solicitacao
|
||||
)
|
||||
|
||||
if ato_principal_schema.ip_maquina is not None:
|
||||
ato_principal_db.ip_maquina = ato_principal_schema.ip_maquina
|
||||
|
||||
if ato_principal_schema.inteiro_teor is not None:
|
||||
ato_principal_db.inteiro_teor = ato_principal_schema.inteiro_teor
|
||||
|
||||
if ato_principal_schema.valor_entrada is not None:
|
||||
ato_principal_db.valor_entrada = ato_principal_schema.valor_entrada
|
||||
|
||||
if ato_principal_schema.emolumento is not None:
|
||||
ato_principal_db.emolumento = ato_principal_schema.emolumento
|
||||
|
||||
if ato_principal_schema.taxa_judiciaria is not None:
|
||||
ato_principal_db.taxa_judiciaria = ato_principal_schema.taxa_judiciaria
|
||||
|
||||
if ato_principal_schema.fundos_estaduais is not None:
|
||||
ato_principal_db.fundos_estaduais = (
|
||||
ato_principal_schema.fundos_estaduais
|
||||
)
|
||||
|
||||
if ato_principal_schema.protocolo_protesto is not None:
|
||||
ato_principal_db.protocolo_protesto = (
|
||||
ato_principal_schema.protocolo_protesto
|
||||
)
|
||||
|
||||
if ato_principal_schema.protocolo_imovel is not None:
|
||||
ato_principal_db.protocolo_imovel = (
|
||||
ato_principal_schema.protocolo_imovel
|
||||
)
|
||||
|
||||
# 4. Atualiza campos criptografados se enviados
|
||||
if ato_principal_schema.nome_civil_ato is not None:
|
||||
ato_principal_db.nome_civil_ato = func.AES_ENCRYPT(
|
||||
ato_principal_schema.nome_civil_ato, AES_KEY
|
||||
)
|
||||
|
||||
if ato_principal_schema.nome_serventuario_praticou_ato is not None:
|
||||
ato_principal_db.nome_serventuario_praticou_ato = func.AES_ENCRYPT(
|
||||
ato_principal_schema.nome_serventuario_praticou_ato, AES_KEY
|
||||
)
|
||||
|
||||
# 5. Atualiza o timestamp de modificação
|
||||
ato_principal_db.updated_at = datetime.now()
|
||||
|
||||
# 6. Persiste as alterações
|
||||
db.add(ato_principal_db)
|
||||
db.commit()
|
||||
db.refresh(ato_principal_db)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Ato principal atualizado com sucesso!",
|
||||
"data": {
|
||||
"ato_principal_id": ato_principal_db.ato_principal_id,
|
||||
"codigo_selo": ato_principal_db.codigo_selo,
|
||||
"codigo_ato": ato_principal_db.codigo_ato,
|
||||
"identificacao_pedido_cgj": ato_principal_db.identificacao_pedido_cgj,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao atualizar ato principal: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioIdSchema
|
||||
|
||||
|
||||
class DeleteRepository:
|
||||
"""
|
||||
Classe responsável por excluir usuários no banco de dados.
|
||||
Segue a mesma metodologia do SaveRepository/UpdateRepository:
|
||||
- abre sessão
|
||||
- busca registro
|
||||
- trata not found
|
||||
- deleta/commita
|
||||
- rollback em erro
|
||||
- fecha sessão
|
||||
"""
|
||||
|
||||
def execute(self, usuario_schema: UsuarioIdSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. Buscar usuário
|
||||
usuario_db = (
|
||||
db.query(Usuario)
|
||||
.filter(Usuario.usuario_id == usuario_schema.usuario_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not usuario_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Usuário não encontrado.",
|
||||
)
|
||||
|
||||
# 2. Excluir (delete físico)
|
||||
db.delete(usuario_db)
|
||||
db.commit()
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Usuário excluído com sucesso!",
|
||||
"data": {
|
||||
"usuario_id": usuario_schema.usuario_id,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao excluir usuário: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import (
|
||||
UsuarioAuthenticateSchema,
|
||||
)
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class GetByAuthenticateRepository:
|
||||
|
||||
def execute(self, user_authenticate_schema: UsuarioAuthenticateSchema):
|
||||
"""
|
||||
Busca um usuário pelo email fornecido no schema e retorna seus dados.
|
||||
Retorna HTTP 404 se não encontrado.
|
||||
"""
|
||||
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# 1. Obtém o email do schema de autenticação
|
||||
username_to_find = user_authenticate_schema.username
|
||||
|
||||
# 2. Executa a query com filtro
|
||||
# Substituímos .all() por .filter() e .first()
|
||||
# Usamos Usuario.username para acessar a coluna do Model
|
||||
result = (
|
||||
db.query(
|
||||
Usuario.usuario_id,
|
||||
func.AES_DECRYPT(Usuario.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY).label("email"),
|
||||
Usuario.username,
|
||||
Usuario.password,
|
||||
Usuario.status,
|
||||
Usuario.date_update,
|
||||
Usuario.user_id_create,
|
||||
Usuario.user_id_update,
|
||||
)
|
||||
.filter(Usuario.username == username_to_find)
|
||||
.first()
|
||||
)
|
||||
|
||||
# 3. Verifica se o usuário foi encontrado
|
||||
if not result:
|
||||
# Lança uma exceção HTTP 404 (Not Found) se não houver resultado
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Usuário '{username_to_find}' não encontrado.",
|
||||
)
|
||||
|
||||
# 4. Converte o model SQLAlchemy (um único objeto) para o schema Pydantic
|
||||
# Note que não é mais uma lista, e sim um único objeto
|
||||
data = UsuarioAuthenticateSchema.model_validate(result)
|
||||
|
||||
return data
|
||||
|
||||
finally:
|
||||
# Fecha a sessão após o uso (evita vazamento de conexão)
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
from typing import Optional
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import (
|
||||
UsuarioEmailSchema,
|
||||
UsuarioSchema,
|
||||
)
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class GetByUsuarioEmailRepository:
|
||||
"""
|
||||
Repositório responsável por buscar um usuário pelo e-mail.
|
||||
Retorna `UsuarioSchema` se encontrar, senão `None`.
|
||||
"""
|
||||
|
||||
def execute(self, usuario_schema: UsuarioEmailSchema) -> Optional[UsuarioSchema]:
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# 1. Pega o e-mail que veio do schema (texto puro)
|
||||
usuario_email_to_find = usuario_schema.email
|
||||
|
||||
# 2. Faz a busca com descriptografia AES_DECRYPT diretamente no SQL
|
||||
result = (
|
||||
db.query(
|
||||
Usuario.usuario_id,
|
||||
func.AES_DECRYPT(Usuario.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY).label("email"),
|
||||
Usuario.username,
|
||||
Usuario.password,
|
||||
Usuario.status,
|
||||
Usuario.date_update,
|
||||
Usuario.user_id_create,
|
||||
Usuario.user_id_update,
|
||||
)
|
||||
.filter(
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY) == usuario_email_to_find
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
# 3. Se não achou, devolve None
|
||||
if not result:
|
||||
return None
|
||||
|
||||
# 4. Converte os campos criptografados de bytes → string
|
||||
def to_str(value):
|
||||
return (
|
||||
value.decode("utf-8")
|
||||
if isinstance(value, (bytes, bytearray))
|
||||
else value
|
||||
)
|
||||
|
||||
# 5. Valida e retorna via schema Pydantic
|
||||
return UsuarioSchema.model_validate(result)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioSchema
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class GetByUsuarioIdRepository:
|
||||
|
||||
def execute(self, usuario_schema=UsuarioSchema):
|
||||
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
|
||||
# 1. Obtém o email do schema de autenticação
|
||||
usuario_id_to_find = usuario_schema.usuario_id
|
||||
|
||||
# 2. Executa a query com filtro
|
||||
# Substituímos .all() por .filter() e .first()
|
||||
# Usamos Usuario.username para acessar a coluna do Model
|
||||
result = (
|
||||
db.query(
|
||||
Usuario.usuario_id,
|
||||
func.AES_DECRYPT(Usuario.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY).label("email"),
|
||||
Usuario.username,
|
||||
Usuario.password,
|
||||
Usuario.status,
|
||||
Usuario.date_update,
|
||||
Usuario.user_id_create,
|
||||
Usuario.user_id_update,
|
||||
)
|
||||
.filter(Usuario.usuario_id == usuario_id_to_find)
|
||||
.first()
|
||||
)
|
||||
|
||||
# 3. Verifica se o usuário foi encontrado
|
||||
if not result:
|
||||
# Lança uma exceção HTTP 404 (Not Found) se não houver resultado
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Usuário '{usuario_id_to_find}' não encontrado.",
|
||||
)
|
||||
|
||||
# 4. Converte o model SQLAlchemy (um único objeto) para o schema Pydantic
|
||||
# Note que não é mais uma lista, e sim um único objeto
|
||||
data = UsuarioSchema.model_validate(result)
|
||||
|
||||
return data
|
||||
|
||||
finally:
|
||||
# Fecha a sessão após o uso (evita vazamento de conexão)
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import (
|
||||
UsuarioSchema,
|
||||
)
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class IndexRepository:
|
||||
def execute(self):
|
||||
# Cria a sessão dentro do repositório
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Executa a query
|
||||
result = db.query(
|
||||
Usuario.usuario_id,
|
||||
func.AES_DECRYPT(Usuario.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY).label("email"),
|
||||
Usuario.username,
|
||||
Usuario.password,
|
||||
Usuario.status,
|
||||
Usuario.date_update,
|
||||
Usuario.user_id_create,
|
||||
Usuario.user_id_update,
|
||||
).all()
|
||||
|
||||
# Converte os models SQLAlchemy em schemas Pydantic
|
||||
data = [UsuarioSchema.model_validate(obj) for obj in result]
|
||||
|
||||
return data
|
||||
|
||||
finally:
|
||||
# Fecha a sessão após o uso (evita vazamento de conexão)
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
import os
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioSaveSchema
|
||||
|
||||
# pega do mesmo lugar que o engine pega
|
||||
DB_SETTINGS = get_database_settings()
|
||||
|
||||
# pega aeskey de forma compatível com SimpleNamespace
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class SaveRepository:
|
||||
"""
|
||||
Classe responsável por salvar (inserir) novos usuários no banco de dados.
|
||||
Nome e e-mail criptografados via AES_ENCRYPT (nativo MySQL) usando só ORM.
|
||||
"""
|
||||
|
||||
def execute(self, usuario_schema: UsuarioSaveSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1) verifica username (texto puro)
|
||||
existing_by_username = (
|
||||
db.query(Usuario)
|
||||
.filter(Usuario.username == usuario_schema.username)
|
||||
.first()
|
||||
)
|
||||
if existing_by_username:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Já existe um usuário com esse nome de usuário.",
|
||||
)
|
||||
|
||||
# 2) verifica e-mail (está criptografado no banco)
|
||||
existing_by_email = (
|
||||
db.query(Usuario)
|
||||
.filter(
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY) == usuario_schema.email
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if existing_by_email:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Já existe um usuário com esse e-mail.",
|
||||
)
|
||||
|
||||
# 3) monta o objeto normalmente
|
||||
new_user = Usuario(
|
||||
username=usuario_schema.username,
|
||||
password=usuario_schema.password, # ideal: já vir hash
|
||||
status=usuario_schema.status or "A",
|
||||
user_id_create=usuario_schema.user_id_create,
|
||||
)
|
||||
|
||||
# 4) para os campos sensíveis, atribui expressão SQL
|
||||
new_user.nome = func.AES_ENCRYPT(usuario_schema.nome, AES_KEY)
|
||||
new_user.email = func.AES_ENCRYPT(usuario_schema.email, AES_KEY)
|
||||
|
||||
# 5) persiste
|
||||
db.add(new_user)
|
||||
db.commit()
|
||||
db.refresh(new_user)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Usuário criado com sucesso!",
|
||||
"data": {
|
||||
"usuario_id": new_user.usuario_id,
|
||||
"nome": usuario_schema.nome,
|
||||
"email": usuario_schema.email,
|
||||
"username": usuario_schema.username,
|
||||
"status": new_user.status,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao salvar usuário: {e}",
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
from typing import Optional
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from sqlalchemy import func
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioSchema
|
||||
|
||||
# === Recupera as configurações do banco ===
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None) # compatível com SimpleNamespace
|
||||
|
||||
|
||||
class ShowRepository:
|
||||
"""
|
||||
Repositório responsável por buscar um usuário pelo e-mail.
|
||||
Retorna `UsuarioSchema` se encontrar, senão `None`.
|
||||
"""
|
||||
|
||||
def execute(self, usuario_schema: UsuarioSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# 1. pega o e-mail que veio do schema
|
||||
usuario_id_to_find = usuario_schema.usuario_id
|
||||
|
||||
# 2. busca no banco
|
||||
result = (
|
||||
db.query(
|
||||
Usuario.usuario_id,
|
||||
func.AES_DECRYPT(Usuario.nome, AES_KEY).label("nome"),
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY).label("email"),
|
||||
Usuario.username,
|
||||
Usuario.password,
|
||||
Usuario.status,
|
||||
Usuario.date_update,
|
||||
Usuario.user_id_create,
|
||||
Usuario.user_id_update,
|
||||
)
|
||||
.filter(Usuario.usuario_id == usuario_id_to_find)
|
||||
.first()
|
||||
)
|
||||
|
||||
# 3. se não achou, devolve None
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
# 4. se achou, converte para pydantic
|
||||
# (assumindo que UsuarioSchema tem Config.from_attributes = True)
|
||||
return UsuarioSchema.model_validate(result)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
from datetime import datetime
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from database.mysql import SessionLocal, get_database_settings
|
||||
from packages.v1.administrativo.models.usuario_model import Usuario
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioUpdateSchema
|
||||
|
||||
# pega as configurações do banco
|
||||
DB_SETTINGS = get_database_settings()
|
||||
AES_KEY = getattr(DB_SETTINGS, "aeskey", None)
|
||||
|
||||
|
||||
class UpdateRepository:
|
||||
"""
|
||||
Classe responsável por atualizar usuários no banco de dados.
|
||||
Segue a mesma metodologia do SaveRepository (sessão, try/except, rollback, retorno padronizado).
|
||||
"""
|
||||
|
||||
def execute(self, usuario_id: int, usuario_schema: UsuarioUpdateSchema):
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# Busca o usuário existente
|
||||
usuario_db = (
|
||||
db.query(Usuario).filter(Usuario.usuario_id == usuario_id).first()
|
||||
)
|
||||
|
||||
if not usuario_db:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Usuário não encontrado.",
|
||||
)
|
||||
|
||||
# Verifica duplicidade de username e e-mail
|
||||
if usuario_schema.email or usuario_schema.username:
|
||||
consulta_duplicidade = db.query(Usuario).filter(
|
||||
Usuario.usuario_id != usuario_id
|
||||
)
|
||||
|
||||
# verifica duplicidade de username (texto puro)
|
||||
if usuario_schema.username:
|
||||
consulta_duplicidade = consulta_duplicidade.filter(
|
||||
Usuario.username == usuario_schema.username
|
||||
)
|
||||
|
||||
# verifica duplicidade de e-mail criptografado
|
||||
if usuario_schema.email:
|
||||
consulta_duplicidade = consulta_duplicidade.filter(
|
||||
func.AES_DECRYPT(Usuario.email, AES_KEY) == usuario_schema.email
|
||||
)
|
||||
|
||||
usuario_conflitante = consulta_duplicidade.first()
|
||||
if usuario_conflitante:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Já existe outro usuário com este e-mail ou username.",
|
||||
)
|
||||
|
||||
# Atualiza apenas campos enviados
|
||||
if usuario_schema.nome is not None:
|
||||
# Criptografa novamente o nome
|
||||
usuario_db.nome = func.AES_ENCRYPT(usuario_schema.nome, AES_KEY)
|
||||
|
||||
if usuario_schema.email is not None:
|
||||
# Criptografa novamente o e-mail
|
||||
usuario_db.email = func.AES_ENCRYPT(usuario_schema.email, AES_KEY)
|
||||
|
||||
if usuario_schema.username is not None:
|
||||
usuario_db.username = usuario_schema.username
|
||||
|
||||
if usuario_schema.password is not None:
|
||||
usuario_db.password = usuario_schema.password # deve vir com hash
|
||||
|
||||
if usuario_schema.status is not None:
|
||||
usuario_db.status = usuario_schema.status
|
||||
|
||||
if usuario_schema.user_id_update is not None:
|
||||
usuario_db.user_id_update = usuario_schema.user_id_update
|
||||
|
||||
# Atualiza data da modificação
|
||||
if hasattr(usuario_db, "date_update"):
|
||||
usuario_db.date_update = datetime.now()
|
||||
|
||||
# Persiste as alterações
|
||||
db.add(usuario_db)
|
||||
db.commit()
|
||||
db.refresh(usuario_db)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Usuário atualizado com sucesso!",
|
||||
"data": {
|
||||
"usuario_id": usuario_db.usuario_id,
|
||||
"nome": usuario_schema.nome,
|
||||
"email": usuario_schema.email,
|
||||
"username": usuario_db.username,
|
||||
"status": usuario_db.status,
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
db.rollback()
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Erro ao atualizar usuário: {e}",
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
152
packages/v1/administrativo/schemas/ato_documento_schema.py
Normal file
152
packages/v1/administrativo/schemas/ato_documento_schema.py
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
from pydantic import BaseModel, constr, field_validator, validator
|
||||
from fastapi import HTTPException, status
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
|
||||
# Funções para sanitização de entradas (evitar XSS, SQLi etc.)
|
||||
# É importante que esta função seja mantida/implementada no seu ambiente
|
||||
# from actions.validations.text import Text # Descomentar se for usar
|
||||
# Funções para validar URL (ajustar importação conforme seu projeto)
|
||||
# from actions.validations.url import URL # Descomentar se for usar
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema Base: Usado para leitura (GET, SHOW, INDEX)
|
||||
# Inclui todos os campos, incluindo os gerados pelo banco
|
||||
# ----------------------------------------------------
|
||||
class AtoDocumentoSchema(BaseModel):
|
||||
ato_documento_id: Optional[int] = None
|
||||
ato_principal_id: Optional[int] = None # bigint NOT NULL
|
||||
url: Optional[str] = None # text NOT NULL
|
||||
nome_documento: Optional[str] = None # varchar(255) NOT NULL
|
||||
tipo_documento: Optional[str] = None # varchar(50) NOT NULL
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para Requisição de ID: Usado em SHOW e DELETE
|
||||
# ----------------------------------------------------
|
||||
class AtoDocumentoIdSchema(BaseModel):
|
||||
ato_documento_id: int
|
||||
|
||||
@field_validator("ato_documento_id")
|
||||
def validate_ato_documento_id(cls, v: int):
|
||||
if v <= 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "ato_documento_id",
|
||||
"message": "ID do documento deve ser um valor positivo.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para Criação (SAVE): Campos obrigatórios e sem ID
|
||||
# ----------------------------------------------------
|
||||
class AtoDocumentoSaveSchema(BaseModel):
|
||||
# Campos obrigatórios
|
||||
ato_principal_id: Optional[int] = None # <<< tornar opcional
|
||||
url: str
|
||||
nome_documento: constr(max_length=255)
|
||||
tipo_documento: constr(max_length=50)
|
||||
|
||||
# Nota: created_at e updated_at são tratados pelo Model/Banco
|
||||
|
||||
# Validação e Sanitização de URL (chk_url_https)
|
||||
@field_validator("url")
|
||||
def validate_url(cls, v: str):
|
||||
v = v.strip()
|
||||
if not v.startswith("https://"):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{"input": "url", "message": "A URL do documento deve ser HTTPS."}
|
||||
],
|
||||
)
|
||||
# Adicionar aqui a validação de URL (ex: URL.is_valid_url(v)) se disponível
|
||||
return v
|
||||
|
||||
# Validação e Sanitização de Tipo Documento (chk_tipo_documento_not_empty)
|
||||
@field_validator("tipo_documento")
|
||||
def validate_tipo_documento(cls, v: str):
|
||||
v = v.strip()
|
||||
if not v:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "tipo_documento",
|
||||
"message": "O tipo de documento não pode ser vazio.",
|
||||
}
|
||||
],
|
||||
)
|
||||
# Adicionar aqui a sanitização de texto (ex: Text.sanitize(v)) se disponível
|
||||
return v
|
||||
|
||||
# Validação e Sanitização de Nome Documento
|
||||
@field_validator("nome_documento")
|
||||
def validate_nome_documento(cls, v: str):
|
||||
v = v.strip()
|
||||
if not v:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "nome_documento",
|
||||
"message": "O nome do documento não pode ser vazio.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para Atualização (UPDATE): Todos opcionais (parciais)
|
||||
# ----------------------------------------------------
|
||||
class AtoDocumentoUpdateSchema(BaseModel):
|
||||
# Todos os campos são opcionais no UPDATE
|
||||
ato_principal_id: Optional[int] = None
|
||||
url: Optional[str] = None
|
||||
nome_documento: Optional[constr(max_length=255)] = None
|
||||
tipo_documento: Optional[constr(max_length=50)] = None
|
||||
|
||||
# Validação de URL
|
||||
@field_validator("url")
|
||||
def validate_url(cls, v: Optional[str]):
|
||||
if v is None:
|
||||
return v
|
||||
v = v.strip()
|
||||
if v and not v.startswith("https://"):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{"input": "url", "message": "A URL do documento deve ser HTTPS."}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
# Validação de Tipo Documento
|
||||
@field_validator("tipo_documento")
|
||||
def validate_tipo_documento(cls, v: Optional[str]):
|
||||
if v is None:
|
||||
return v
|
||||
v = v.strip()
|
||||
if not v:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "tipo_documento",
|
||||
"message": "O tipo de documento não pode ser vazio.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
138
packages/v1/administrativo/schemas/ato_parte_schema.py
Normal file
138
packages/v1/administrativo/schemas/ato_parte_schema.py
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
from pydantic import BaseModel, constr, field_validator
|
||||
from fastapi import HTTPException, status
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
import re
|
||||
|
||||
# Funções para sanitização de entradas (evitar XSS, SQLi etc.)
|
||||
# É importante que esta função seja mantida/implementada no seu ambiente
|
||||
# from actions.validations.text import Text # Descomentar se for usar
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema Base: Usado para leitura (GET, SHOW, INDEX)
|
||||
# Inclui todos os campos, incluindo os gerados pelo banco
|
||||
# ----------------------------------------------------
|
||||
class AtoParteSchema(BaseModel):
|
||||
ato_parte_id: Optional[int] = None
|
||||
ato_principal_id: Optional[int] = None # bigint NOT NULL
|
||||
nome: Optional[str] = None # varchar(255) NOT NULL
|
||||
telefone: Optional[str] = None # varchar(20) DEFAULT NULL
|
||||
cpf_cnpj: Optional[str] = None # varchar(20) NOT NULL
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para Requisição de ID: Usado em SHOW e DELETE
|
||||
# ----------------------------------------------------
|
||||
class AtoParteIdSchema(BaseModel):
|
||||
ato_parte_id: int
|
||||
|
||||
@field_validator("ato_parte_id")
|
||||
def validate_ato_parte_id(cls, v: int):
|
||||
if v <= 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "ato_parte_id",
|
||||
"message": "ID da parte deve ser um valor positivo.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Funções de Validação Comuns
|
||||
# ----------------------------------------------------
|
||||
|
||||
|
||||
def validate_cpf_cnpj(cls, v: str):
|
||||
v = re.sub(r"[^\d]", "", v).strip() # Remove caracteres não numéricos
|
||||
|
||||
# chk_cpf_cnpj_formato CHECK (regexp_like(`cpf_cnpj`,_utf8mb4'^[0-9]{11,14}$'))
|
||||
if not re.match(r"^\d{11,14}$", v):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "cpf_cnpj",
|
||||
"message": "CPF/CNPJ deve conter apenas 11 (CPF) ou 14 (CNPJ) dígitos numéricos.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
def validate_nome_not_empty(cls, v: str):
|
||||
v = v.strip()
|
||||
if not v:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "nome",
|
||||
"message": "O nome não pode ser vazio.",
|
||||
}
|
||||
],
|
||||
)
|
||||
# Adicionar aqui a sanitização de texto (ex: Text.sanitize(v)) se disponível
|
||||
return v
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para Criação (SAVE): Campos obrigatórios e sem ID
|
||||
# ----------------------------------------------------
|
||||
class AtoParteSaveSchema(BaseModel):
|
||||
# Campos obrigatórios
|
||||
ato_principal_id: Optional[int] = None # <<< tornar opcional
|
||||
nome: constr(max_length=255)
|
||||
cpf_cnpj: constr(
|
||||
max_length=20
|
||||
) # Permitindo até 20 para acomodar a entrada antes de limpar
|
||||
|
||||
# Campo opcional (nullable na DDL)
|
||||
telefone: Optional[constr(max_length=20)] = None
|
||||
|
||||
# Validação de Nome
|
||||
@field_validator("nome")
|
||||
def validate_nome(cls, v: str):
|
||||
return validate_nome_not_empty(cls, v)
|
||||
|
||||
# Validação de CPF/CNPJ
|
||||
@field_validator("cpf_cnpj")
|
||||
def validate_cpf_cnpj_field(cls, v: str):
|
||||
return validate_cpf_cnpj(cls, v)
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para Atualização (UPDATE): Todos opcionais (parciais)
|
||||
# ----------------------------------------------------
|
||||
class AtoParteUpdateSchema(BaseModel):
|
||||
# Todos os campos são opcionais no UPDATE
|
||||
ato_principal_id: Optional[int] = None
|
||||
nome: Optional[constr(max_length=255)] = None
|
||||
telefone: Optional[constr(max_length=20)] = None
|
||||
cpf_cnpj: Optional[constr(max_length=20)] = None
|
||||
|
||||
# Validação de Nome
|
||||
@field_validator("nome")
|
||||
def validate_nome_update(cls, v: Optional[str]):
|
||||
if v is None:
|
||||
return v
|
||||
return validate_nome_not_empty(cls, v)
|
||||
|
||||
# Validação de CPF/CNPJ
|
||||
@field_validator("cpf_cnpj")
|
||||
def validate_cpf_cnpj_update(cls, v: Optional[str]):
|
||||
if v is None:
|
||||
return v
|
||||
return validate_cpf_cnpj(cls, v)
|
||||
|
||||
# Nota: Telefone não precisa de validação complexa além do constr(max_length)
|
||||
# se o objetivo for apenas armazenar a string fornecida.
|
||||
|
|
@ -1,56 +1,277 @@
|
|||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, constr, field_validator
|
||||
from fastapi import HTTPException, status
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
from ipaddress import IPv4Address, IPv6Address
|
||||
from decimal import Decimal
|
||||
from decimal import Decimal # Importar Decimal para campos monetários
|
||||
|
||||
# Funções para sanitização de entradas (evitar XSS, SQLi etc.)
|
||||
# É importante que esta função seja mantida/implementada no seu ambiente
|
||||
# from actions.validations.text import Text # Descomentar se for usar
|
||||
|
||||
# Schemas dos itens
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSaveSchema
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoSaveSchema,
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema base - campos principais e comuns
|
||||
# Schema Base: Usado para leitura (GET, SHOW, INDEX)
|
||||
# Inclui todos os campos, incluindo os gerados pelo banco
|
||||
# ----------------------------------------------------
|
||||
class AtoPrincipalBaseSchema(BaseModel):
|
||||
class AtoPrincipalSchema(BaseModel):
|
||||
# DDL: bigint NOT NULL AUTO_INCREMENT
|
||||
ato_principal_id: Optional[int] = None
|
||||
# DDL: bigint DEFAULT NULL
|
||||
origem_ato_principal_id: Optional[int] = None
|
||||
# DDL: bigint NOT NULL
|
||||
identificacao_pedido_cgj: int
|
||||
# DDL: int NOT NULL
|
||||
tipo_ato: int
|
||||
codigo_selo: str
|
||||
codigo_ato: str
|
||||
nome_civil_ato: str
|
||||
nome_serventuario_praticou_ato: str
|
||||
# DDL: varchar(50) NOT NULL (UNIQUE)
|
||||
codigo_selo: constr(max_length=50)
|
||||
# DDL: varchar(50) NOT NULL (UNIQUE)
|
||||
codigo_ato: constr(max_length=50)
|
||||
# DDL: varchar(255) NOT NULL (mas o banco pode conter valores NULL em registros antigos)
|
||||
nome_civil_ato: Optional[constr(max_length=255)] = None
|
||||
# DDL: varchar(255) NOT NULL (mas o banco pode conter valores NULL em registros antigos)
|
||||
nome_serventuario_praticou_ato: Optional[constr(max_length=255)] = None
|
||||
# DDL: datetime NOT NULL
|
||||
data_solicitacao: datetime
|
||||
ip_maquina: Optional[IPv4Address | IPv6Address] = None
|
||||
# DDL: varchar(45) DEFAULT NULL
|
||||
ip_maquina: Optional[constr(max_length=45)] = None
|
||||
# DDL: text NOT NULL
|
||||
inteiro_teor: str
|
||||
# DDL: decimal(12,2) DEFAULT NULL
|
||||
valor_entrada: Optional[Decimal] = None
|
||||
# DDL: decimal(12,2) NOT NULL
|
||||
emolumento: Decimal
|
||||
# DDL: decimal(12,2) NOT NULL
|
||||
taxa_judiciaria: Decimal
|
||||
# DDL: decimal(12,2) NOT NULL
|
||||
fundos_estaduais: Decimal
|
||||
protocolo_protesto: Optional[str] = None
|
||||
protocolo_imovel: Optional[str] = None
|
||||
# DDL: varchar(50) DEFAULT NULL
|
||||
protocolo_protesto: Optional[constr(max_length=50)] = None
|
||||
# DDL: varchar(50) DEFAULT NULL
|
||||
protocolo_imovel: Optional[constr(max_length=50)] = None
|
||||
# DDL: datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
created_at: Optional[datetime] = None
|
||||
# DDL: datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
# Permite a conversão de float/int para Decimal
|
||||
json_encoders = {Decimal: lambda v: float(v)}
|
||||
# Define a precisão para Decimal
|
||||
decimal_places = 2
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema de resposta (GET) — inclui metadata
|
||||
# Schema para Requisição de ID: Usado em SHOW e DELETE
|
||||
# ----------------------------------------------------
|
||||
class AtoPrincipalResponseSchema(AtoPrincipalBaseSchema):
|
||||
class AtoPrincipalIdSchema(BaseModel):
|
||||
ato_principal_id: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
@field_validator("ato_principal_id")
|
||||
def validate_ato_principal_id(cls, v: int):
|
||||
if v <= 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "ato_principal_id",
|
||||
"message": "ID do Ato Principal deve ser um valor positivo.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para Criação (SAVE): Campos obrigatórios e sem ID
|
||||
# ----------------------------------------------------
|
||||
class AtoPrincipalSaveSchema(BaseModel):
|
||||
ato_principal_id: Optional[int] = None # <<< tornar opcional
|
||||
|
||||
# Campos obrigatórios baseados na DDL (NOT NULL)
|
||||
origem_ato_principal_id: Optional[int] = None # bigint DEFAULT NULL
|
||||
identificacao_pedido_cgj: int # bigint NOT NULL
|
||||
tipo_ato: int # int NOT NULL
|
||||
codigo_selo: constr(max_length=50) # varchar(50) NOT NULL
|
||||
codigo_ato: constr(max_length=50) # varchar(50) NOT NULL
|
||||
nome_civil_ato: constr(max_length=255) # varchar(255) NOT NULL
|
||||
nome_serventuario_praticou_ato: constr(max_length=255) # varchar(255) NOT NULL
|
||||
data_solicitacao: datetime # datetime NOT NULL
|
||||
ip_maquina: Optional[constr(max_length=45)] = None # varchar(45) DEFAULT NULL
|
||||
inteiro_teor: str # text NOT NULL
|
||||
valor_entrada: Optional[Decimal] = None # decimal(12,2) DEFAULT NULL
|
||||
emolumento: Decimal # decimal(12,2) NOT NULL
|
||||
taxa_judiciaria: Decimal # decimal(12,2) NOT NULL
|
||||
fundos_estaduais: Decimal # decimal(12,2) NOT NULL
|
||||
protocolo_protesto: Optional[constr(max_length=50)] = (
|
||||
None # varchar(50) DEFAULT NULL
|
||||
)
|
||||
protocolo_imovel: Optional[constr(max_length=50)] = None # varchar(50) DEFAULT NULL
|
||||
ato_partes: List[AtoParteSaveSchema] = [] # precisa existir
|
||||
ato_documentos: List[AtoDocumentoSaveSchema] = [] # precisa existir
|
||||
|
||||
# NOVO CAMPO: Referência recursiva a outros atos principais
|
||||
# Usando string para forward reference
|
||||
atos_vinculados: Optional[List["AtoPrincipalSaveSchema"]] = None
|
||||
|
||||
# Validação e Sanitização de campos de texto obrigatórios (adaptado do código fonte)
|
||||
@field_validator(
|
||||
"codigo_selo",
|
||||
"codigo_ato",
|
||||
"nome_civil_ato",
|
||||
"nome_serventuario_praticou_ato",
|
||||
"inteiro_teor",
|
||||
)
|
||||
def validate_required_strings(cls, v: str):
|
||||
v = v.strip()
|
||||
if not v:
|
||||
# Identifica o campo que falhou a validação
|
||||
input_name = (
|
||||
"Erro de campo" # Será substituído se a função for mais complexa
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": input_name,
|
||||
"message": "Este campo obrigatório não pode ser vazio.",
|
||||
}
|
||||
],
|
||||
)
|
||||
# Adicionar aqui a sanitização de texto (ex: Text.sanitize(v)) se disponível
|
||||
return v
|
||||
|
||||
# Validação dos campos monetários (baseado na CHECK CONSTRAINT da DDL)
|
||||
@field_validator(
|
||||
"valor_entrada", "emolumento", "taxa_judiciaria", "fundos_estaduais"
|
||||
)
|
||||
def validate_positive_values(cls, v: Optional[Decimal]):
|
||||
if v is None and (
|
||||
"valor_entrada" in cls.__annotations__
|
||||
and cls.__annotations__["valor_entrada"] == Optional[Decimal]
|
||||
):
|
||||
# valor_entrada é o único campo DEFAULT NULL, aceita None
|
||||
return v
|
||||
if v is not None and v < 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "campo_monetario",
|
||||
"message": "Os valores monetários não podem ser negativos.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
json_encoders = {Decimal: lambda v: float(v)}
|
||||
decimal_places = 2
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema de criação (POST)
|
||||
# Schema para Atualização (UPDATE): Todos opcionais (parciais)
|
||||
# ----------------------------------------------------
|
||||
class AtoPrincipalCreateSchema(AtoPrincipalBaseSchema):
|
||||
pass
|
||||
class AtoPrincipalUpdateSchema(BaseModel):
|
||||
# Todos os campos que podem ser atualizados são opcionais
|
||||
origem_ato_principal_id: Optional[int] = None
|
||||
identificacao_pedido_cgj: Optional[int] = None
|
||||
tipo_ato: Optional[int] = None
|
||||
codigo_selo: Optional[constr(max_length=50)] = None
|
||||
codigo_ato: Optional[constr(max_length=50)] = None
|
||||
nome_civil_ato: Optional[constr(max_length=255)] = None
|
||||
nome_serventuario_praticou_ato: Optional[constr(max_length=255)] = None
|
||||
data_solicitacao: Optional[datetime] = None
|
||||
ip_maquina: Optional[constr(max_length=45)] = None
|
||||
inteiro_teor: Optional[str] = None
|
||||
valor_entrada: Optional[Decimal] = None
|
||||
emolumento: Optional[Decimal] = None
|
||||
taxa_judiciaria: Optional[Decimal] = None
|
||||
fundos_estaduais: Optional[Decimal] = None
|
||||
protocolo_protesto: Optional[constr(max_length=50)] = None
|
||||
protocolo_imovel: Optional[constr(max_length=50)] = None
|
||||
|
||||
# Reutiliza a validação de strings obrigatórias (só valida se o campo for fornecido)
|
||||
@field_validator(
|
||||
"codigo_selo",
|
||||
"codigo_ato",
|
||||
"nome_civil_ato",
|
||||
"nome_serventuario_praticou_ato",
|
||||
"inteiro_teor",
|
||||
)
|
||||
def validate_non_empty_strings_on_update(cls, v: Optional[str]):
|
||||
if v is not None:
|
||||
v_stripped = v.strip()
|
||||
if not v_stripped:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "campo_de_texto",
|
||||
"message": "Este campo não pode ser atualizado para um valor vazio.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
# Reutiliza a validação de valores positivos
|
||||
@field_validator(
|
||||
"valor_entrada", "emolumento", "taxa_judiciaria", "fundos_estaduais"
|
||||
)
|
||||
def validate_positive_values_on_update(cls, v: Optional[Decimal]):
|
||||
if v is not None and v < 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "campo_monetario",
|
||||
"message": "Os valores monetários não podem ser negativos.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
json_encoders = {Decimal: lambda v: float(v)}
|
||||
decimal_places = 2
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema de atualização (PUT)
|
||||
# Schema auxiliar para buscar por campos únicos (opcional, mas útil para o Save Service)
|
||||
# ----------------------------------------------------
|
||||
class AtoPrincipalUpdateSchema(AtoPrincipalBaseSchema):
|
||||
ato_principal_id: int
|
||||
class AtoPrincipalCodigoSchema(BaseModel):
|
||||
codigo: constr(max_length=50) # Pode ser codigo_selo ou codigo_ato
|
||||
|
||||
@field_validator("codigo")
|
||||
def validate_codigo(cls, v: str):
|
||||
v = v.strip()
|
||||
if not v:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "codigo",
|
||||
"message": "O código de busca não pode ser vazio.",
|
||||
}
|
||||
],
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
# --- ADIÇÃO CRÍTICA PARA RECURSIVIDADE (Resolução da forward reference) ---
|
||||
# Necessário para resolver a referência da classe dentro de si mesma.
|
||||
# Tenta Pydantic v2 (model_rebuild) e, se falhar, Pydantic v1 (update_forward_refs).
|
||||
try:
|
||||
AtoPrincipalSaveSchema.model_rebuild()
|
||||
except AttributeError:
|
||||
# Se estiver usando Pydantic v1
|
||||
AtoPrincipalSaveSchema.update_forward_refs()
|
||||
|
|
|
|||
223
packages/v1/administrativo/schemas/usuario_schema.py
Normal file
223
packages/v1/administrativo/schemas/usuario_schema.py
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
from pydantic import BaseModel, EmailStr, constr, field_validator, model_validator
|
||||
from pydantic_core import PydanticCustomError
|
||||
from fastapi import HTTPException, status
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
|
||||
# Funções utilitárias para segurança (hash e verificação de senha)
|
||||
# Supondo que você ajustará as importações conforme seu projeto
|
||||
from actions.security.security import Security
|
||||
|
||||
# Funções para sanitização de entradas (evitar XSS, SQLi etc.)
|
||||
from actions.validations.text import Text
|
||||
|
||||
# Funções para validar E-mail
|
||||
from actions.validations.email import Email
|
||||
|
||||
# Funções para validar cpf (Não está na DDL, mas mantido como opcional no Save e Update)
|
||||
# from actions.validations.cpf import CPF # Não utilizado neste novo escopo
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema base
|
||||
# ----------------------------------------------------
|
||||
class UsuarioSchema(BaseModel):
|
||||
usuario_id: Optional[int] = None
|
||||
nome: Optional[str] = None
|
||||
email: Optional[EmailStr] = None
|
||||
username: Optional[str] = None
|
||||
password: Optional[str] = None
|
||||
status: Optional[str] = None # Corresponde ao 'status' na DDL
|
||||
date_register: Optional[datetime] = None
|
||||
date_update: Optional[datetime] = None
|
||||
user_id_create: Optional[int] = None
|
||||
user_id_update: Optional[int] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para acesso ao sistema (Autenticação)
|
||||
# ----------------------------------------------------
|
||||
class UsuarioAuthenticateSchema(BaseModel):
|
||||
|
||||
# Campos utilizados
|
||||
username: str # Usando username para login, é mais comum em DDLs simples
|
||||
password: str # Corresponde ao 'password' na DDL
|
||||
status: Optional[str] = None
|
||||
usuario_id: Optional[int] = None
|
||||
nome: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
|
||||
# Validação e sanitização do email
|
||||
@field_validator("username")
|
||||
def validar_e_sanitizar_password(cls, v):
|
||||
|
||||
if not v:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail="Informe o username"
|
||||
)
|
||||
|
||||
# Sanitiza e-mail
|
||||
return Text.sanitize_input(v)
|
||||
|
||||
# Validação e sanitização da senha
|
||||
@field_validator("password")
|
||||
def validar_e_sanitizar_senha(cls, v):
|
||||
|
||||
if not v:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST, detail="Informe a password"
|
||||
)
|
||||
|
||||
# Sanitiza a senha
|
||||
return Text.sanitize_input(v)
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para localizar um usuário especifico pelo ID (GET)
|
||||
# ----------------------------------------------------
|
||||
class UsuarioIdSchema(BaseModel):
|
||||
usuario_id: int
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para criação de novo usuário (POST)
|
||||
# ----------------------------------------------------
|
||||
class UsuarioSaveSchema(BaseModel):
|
||||
usuario_id: Optional[int] = None
|
||||
nome: constr(min_length=1)
|
||||
email: EmailStr
|
||||
username: constr(min_length=1)
|
||||
password: constr(min_length=1)
|
||||
status: Optional[str] = "A"
|
||||
user_id_create: Optional[int] = None
|
||||
|
||||
# Sanitiza os inputs enviados
|
||||
@field_validator("nome", "email", "username", "password", "status")
|
||||
def validate_and_sanitize_fields(cls, v):
|
||||
if v is not None:
|
||||
return Text.sanitize_input(v)
|
||||
return v
|
||||
|
||||
# Verifica se os campos obrigatórios foram enviados e hash da senha
|
||||
@model_validator(mode="after")
|
||||
def validate_all_fields_and_hash_password(self):
|
||||
|
||||
errors = []
|
||||
|
||||
# Validação do nome
|
||||
if not self.nome or len(self.nome.strip()) == 0:
|
||||
errors.append({"input": "nome", "message": "O nome é obrigatório."})
|
||||
|
||||
# Validação do email (EmailStr do Pydantic já faz a validação de formato)
|
||||
if not self.email or len(self.email.strip()) == 0:
|
||||
errors.append({"input": "email", "message": "O e-mail é obrigatório."})
|
||||
|
||||
# Validação da username
|
||||
if not self.username or len(self.username.strip()) == 0:
|
||||
errors.append({"input": "username", "message": "O username é obrigatório."})
|
||||
|
||||
# Validação da senha
|
||||
if not self.password or len(self.password.strip()) == 0:
|
||||
errors.append({"input": "password", "message": "A senha é obrigatória."})
|
||||
|
||||
# Criptografa a senha
|
||||
if (
|
||||
self.password and not errors
|
||||
): # Hash somente se a senha estiver presente e sem erros anteriores
|
||||
self.password = Security.hash_password(self.password)
|
||||
|
||||
# Se houver errors, lança uma única exceção
|
||||
if errors:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=errors
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para atualizar usuário (PUT)
|
||||
# ----------------------------------------------------
|
||||
class UsuarioUpdateSchema(BaseModel):
|
||||
|
||||
nome: Optional[str] = None
|
||||
email: Optional[EmailStr] = None
|
||||
username: Optional[str] = None
|
||||
password: Optional[str] = None
|
||||
status: Optional[str] = None
|
||||
user_id_update: Optional[int] = None
|
||||
|
||||
# Sanitiza os inputs enviados
|
||||
@field_validator(
|
||||
"nome",
|
||||
"email",
|
||||
"username",
|
||||
"password",
|
||||
"status",
|
||||
)
|
||||
def validate_and_sanitize_fields(cls, v):
|
||||
if v is not None:
|
||||
return Text.sanitize_input(v)
|
||||
return v
|
||||
|
||||
# Hash da senha se ela for fornecida
|
||||
@model_validator(mode="after")
|
||||
def hash_password_if_provided(self):
|
||||
|
||||
# Hash da nova senha, se fornecida.
|
||||
if self.password:
|
||||
self.password = Security.hash_password(self.password)
|
||||
|
||||
# Não estamos forçando a obrigatoriedade de todos os campos aqui (PUT é parcial),
|
||||
# mas garantimos a sanitização e o hash da senha se ela existir.
|
||||
|
||||
return self
|
||||
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Schema para localizar usuário pelo e-mail
|
||||
# ----------------------------------------------------
|
||||
class UsuarioEmailSchema(BaseModel):
|
||||
|
||||
email: Optional[EmailStr] = None
|
||||
|
||||
# Sanitiza o e-mail informado
|
||||
@field_validator("email", mode="before")
|
||||
def sanitize_email(cls, v: Optional[str]):
|
||||
if v is None:
|
||||
return v
|
||||
v = v.strip()
|
||||
return v
|
||||
|
||||
# Verifica se o e-mail foi informado e se é válido
|
||||
@field_validator("email")
|
||||
def validate_email(cls, v: str):
|
||||
|
||||
errors = []
|
||||
|
||||
# vazio
|
||||
if not v:
|
||||
|
||||
errors.append({"input": "e-mail", "message": "Informe um e-mail."})
|
||||
|
||||
# inválido pelo seu helper
|
||||
if not Email.is_valid_email(v):
|
||||
|
||||
errors.append({"input": "e-mail", "message": "E-mail inválido."})
|
||||
|
||||
# Se houver errors, lança uma única exceção
|
||||
if errors:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=errors
|
||||
)
|
||||
|
||||
return v
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
from packages.v1.administrativo.actions.ato_documento.ato_documento_delete_action import (
|
||||
DeleteAction,
|
||||
)
|
||||
|
||||
|
||||
class DeleteService:
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento de ação
|
||||
delete_action = DeleteAction()
|
||||
|
||||
# Executa a ação em questão, passando o schema com o ID
|
||||
data = delete_action.execute(ato_documento_schema)
|
||||
|
||||
# Retorno da informação (inclui a mensagem de sucesso do Repository/Action)
|
||||
return data
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.actions.ato_documento.ato_documento_index_action import (
|
||||
IndexAction,
|
||||
)
|
||||
|
||||
# Nota: O Schema de índice (AtoDocumentoSchema) não é importado aqui
|
||||
# porque a Action já faz a conversão do Model para Schema.
|
||||
|
||||
|
||||
class IndexService:
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Instânciamento da Action
|
||||
index_action = IndexAction()
|
||||
|
||||
# Executa a busca de todos os documentos
|
||||
data = index_action.execute()
|
||||
|
||||
# Verifica se foram localizados registros
|
||||
if not data:
|
||||
# Retorna uma exceção 404
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar os documentos",
|
||||
)
|
||||
|
||||
# Retorna as informações localizadas
|
||||
return data
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoSaveSchema,
|
||||
)
|
||||
from packages.v1.administrativo.actions.ato_documento.ato_documento_save_action import (
|
||||
SaveAction,
|
||||
)
|
||||
|
||||
|
||||
class SaveService:
|
||||
"""
|
||||
Service responsável por validar o schema e executar a Action de salvamento
|
||||
do documento. Não requer lógica de verificação de duplicidade de campos
|
||||
que não são únicos (url, tipo_documento, nome_documento) ou
|
||||
que são chaves estrangeiras (ato_principal_id).
|
||||
"""
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSaveSchema):
|
||||
|
||||
# A verificação de duplicidade (como e-mail em usuário) não é necessária
|
||||
# para ato_documento neste ponto. A Action/Repository é chamada diretamente.
|
||||
|
||||
# Instânciamento da Action
|
||||
save_action = SaveAction()
|
||||
|
||||
# Executa a ação de salvamento
|
||||
return save_action.execute(ato_documento_schema)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
from packages.v1.administrativo.actions.ato_documento.ato_documento_show_action import (
|
||||
ShowAction,
|
||||
)
|
||||
|
||||
|
||||
class ShowService:
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento da Action
|
||||
show_action = ShowAction()
|
||||
|
||||
# Executa a ação em questão (busca pelo ID)
|
||||
data = show_action.execute(ato_documento_schema)
|
||||
|
||||
if not data:
|
||||
# Retorna uma exceção 404
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar o documento.",
|
||||
)
|
||||
|
||||
# Retorno da informação
|
||||
return data
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from packages.v1.administrativo.schemas.ato_documento_schema import (
|
||||
AtoDocumentoUpdateSchema,
|
||||
)
|
||||
from packages.v1.administrativo.actions.ato_documento.ato_documento_update_action import (
|
||||
UpdateAction,
|
||||
)
|
||||
|
||||
|
||||
class UpdateService:
|
||||
"""
|
||||
Service responsável por validar o schema e executar a Action de atualização
|
||||
do documento.
|
||||
"""
|
||||
|
||||
def execute(
|
||||
self, ato_documento_id: int, ato_documento_schema: AtoDocumentoUpdateSchema
|
||||
):
|
||||
|
||||
# A lógica de verificação de duplicidade de campos sensíveis (como e-mail)
|
||||
# não é necessária para ato_documento neste ponto.
|
||||
|
||||
# Instânciamento de ações
|
||||
updateAction = UpdateAction()
|
||||
|
||||
# Executa a atualização, passando o ID e o schema com os dados
|
||||
return updateAction.execute(ato_documento_id, ato_documento_schema)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.schemas.ato_documento_schema import AtoDocumentoSchema
|
||||
from packages.v1.administrativo.actions.ato_documento.ato_principal_show_action import (
|
||||
ShowAction,
|
||||
)
|
||||
|
||||
|
||||
class ShowAtoPrincipalService:
|
||||
|
||||
def execute(self, ato_documento_schema: AtoDocumentoSchema):
|
||||
|
||||
# Instânciamento da Action
|
||||
show_action = ShowAction()
|
||||
|
||||
# Executa a ação em questão (busca pelo ID)
|
||||
data = show_action.execute(ato_documento_schema)
|
||||
|
||||
if not data:
|
||||
# Retorna uma exceção 404
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar o documento.",
|
||||
)
|
||||
|
||||
# Retorno da informação
|
||||
return data
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteIdSchema
|
||||
from packages.v1.administrativo.actions.ato_parte.ato_parte_delete_action import (
|
||||
DeleteAction,
|
||||
)
|
||||
|
||||
|
||||
class DeleteService:
|
||||
"""
|
||||
Service responsável por orquestrar a ação de exclusão de uma parte do ato.
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteIdSchema):
|
||||
|
||||
# Instânciamento de ação (assumindo que o nome da Action é 'DeleteAction'
|
||||
# e está no caminho 'packages.v1.administrativo.actions.ato_parte')
|
||||
delete_action = DeleteAction()
|
||||
|
||||
# Executa a ação em questão, passando o schema com o ID
|
||||
# A Action deve receber um schema contendo apenas o ID, como AtoParteIdSchema
|
||||
data = delete_action.execute(ato_parte_schema)
|
||||
|
||||
# Retorno da informação (inclui a mensagem de sucesso do Repository/Action)
|
||||
return data
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.actions.ato_parte.ato_parte_index_action import (
|
||||
IndexAction,
|
||||
)
|
||||
|
||||
# Nota: O Schema de índice (AtoParteSchema) não é importado aqui
|
||||
# porque a Action já faz a conversão do Model para Schema.
|
||||
|
||||
|
||||
class IndexService:
|
||||
"""
|
||||
Service responsável por orquestrar a busca de todas as partes de ato.
|
||||
"""
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Instânciamento da Action
|
||||
index_action = IndexAction()
|
||||
|
||||
# Executa a busca de todas as partes
|
||||
data = index_action.execute()
|
||||
|
||||
# Verifica se foram localizados registros
|
||||
if not data:
|
||||
# Retorna uma exceção 404
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar as partes de ato",
|
||||
)
|
||||
|
||||
# Retorna as informações localizadas
|
||||
return data
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteSaveSchema,
|
||||
)
|
||||
from packages.v1.administrativo.actions.ato_parte.ato_parte_save_action import (
|
||||
SaveAction,
|
||||
)
|
||||
|
||||
|
||||
class SaveService:
|
||||
"""
|
||||
Service responsável por validar o schema e executar a Action de salvamento
|
||||
da parte de ato.
|
||||
Nota: Para CPF/CNPJ, é **crucial** que haja uma verificação de duplicidade,
|
||||
pois é um campo que pode ser considerado único ou que precisa de validação
|
||||
de existência no contexto da sua regra de negócio.
|
||||
Para este template, mantive a estrutura simples.
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSaveSchema):
|
||||
|
||||
# Instânciamento da Action
|
||||
save_action = SaveAction()
|
||||
|
||||
# Executa a ação de salvamento
|
||||
return save_action.execute(ato_parte_schema)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
from packages.v1.administrativo.actions.ato_parte.ato_parte_show_action import (
|
||||
ShowAction,
|
||||
)
|
||||
|
||||
|
||||
class ShowService:
|
||||
"""
|
||||
Service responsável por orquestrar a busca de uma ou mais partes
|
||||
vinculadas a um ato principal.
|
||||
(O Schema AtoParteSchema é presumido para a entrada que contém
|
||||
o ato_principal_id para busca)
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Instânciamento da Action
|
||||
show_action = ShowAction()
|
||||
|
||||
# Executa a ação em questão (busca pelo ato_principal_id)
|
||||
data = show_action.execute(ato_parte_schema)
|
||||
|
||||
if not data:
|
||||
# Retorna uma exceção 404
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar partes para o ato principal informado.",
|
||||
)
|
||||
|
||||
# Retorno da informação
|
||||
return data
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
from packages.v1.administrativo.schemas.ato_parte_schema import (
|
||||
AtoParteUpdateSchema,
|
||||
)
|
||||
from packages.v1.administrativo.actions.ato_parte.ato_parte_update_action import (
|
||||
UpdateAction,
|
||||
)
|
||||
|
||||
|
||||
class UpdateService:
|
||||
"""
|
||||
Service responsável por validar o schema e executar a Action de atualização
|
||||
da parte de ato.
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_id: int, ato_parte_schema: AtoParteUpdateSchema):
|
||||
|
||||
# A lógica de verificação de duplicidade de campos sensíveis (como CPF/CNPJ)
|
||||
# geralmente é tratada em um ponto anterior, como no Service de SAVE ou na Action.
|
||||
# Aqui, o foco é na orquestração da atualização.
|
||||
|
||||
# Instânciamento de ações
|
||||
updateAction = UpdateAction()
|
||||
|
||||
# Executa a atualização, passando o ID e o schema com os dados
|
||||
return updateAction.execute(ato_parte_id, ato_parte_schema)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.schemas.ato_parte_schema import AtoParteSchema
|
||||
from packages.v1.administrativo.actions.ato_parte.ato_principal_show_action import (
|
||||
AtoPartePrincipalShowAction,
|
||||
)
|
||||
|
||||
|
||||
class AtoPrincipalShowService:
|
||||
"""
|
||||
Service responsável por orquestrar a busca de partes vinculadas
|
||||
a um ato principal específico (busca por ato_principal_id).
|
||||
"""
|
||||
|
||||
def execute(self, ato_parte_schema: AtoParteSchema):
|
||||
|
||||
# Instânciamento da Action adaptada
|
||||
show_action = AtoPartePrincipalShowAction()
|
||||
|
||||
# Executa a ação em questão (busca pelas partes do ato principal)
|
||||
data = show_action.execute(ato_parte_schema)
|
||||
|
||||
if not data:
|
||||
# Retorna uma exceção 404
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar partes para o ato principal.",
|
||||
)
|
||||
|
||||
# Retorno da informação
|
||||
return data
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
from packages.v1.administrativo.schemas.ato_principal_schema import AtoPrincipalSchema
|
||||
from packages.v1.administrativo.actions.ato_principal.ato_principal_delete_action import (
|
||||
DeleteAction,
|
||||
)
|
||||
|
||||
|
||||
class DeleteService:
|
||||
"""
|
||||
Camada de Serviço responsável por orquestrar a exclusão
|
||||
de um AtoPrincipal, geralmente fazendo validações de negócio
|
||||
antes de chamar a Action de exclusão.
|
||||
"""
|
||||
|
||||
def execute(self, ato_principal_schema: AtoPrincipalSchema):
|
||||
|
||||
# Instânciamento de ação (DeleteAction, mantendo o padrão)
|
||||
delete_action = DeleteAction()
|
||||
|
||||
# Executa a ação em questão, passando o schema com o ID
|
||||
# Assumindo que o schema AtoPrincipalSchema ou um específico
|
||||
# como AtoPrincipalIdSchema possui o ID necessário para a exclusão.
|
||||
data = delete_action.execute(ato_principal_schema)
|
||||
|
||||
# Retorno da informação (inclui a mensagem de sucesso do Repository/Action)
|
||||
return data
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# packages/v1/administrativo/services/ato_principal/ato_principal_get_codigo_service.py
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
from database.mysql import SessionLocal
|
||||
from packages.v1.administrativo.models.ato_principal_model import AtoPrincipal
|
||||
|
||||
|
||||
class GetCodigoService:
|
||||
"""
|
||||
Serviço responsável por buscar um registro de ato_principal
|
||||
com base no código do selo ou código do ato.
|
||||
"""
|
||||
|
||||
def execute(self, codigo_selo: str = None, codigo_ato: str = None):
|
||||
# Garante que pelo menos um parâmetro foi informado
|
||||
if not codigo_selo and not codigo_ato:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail=[
|
||||
{
|
||||
"input": "codigo",
|
||||
"message": "Informe pelo menos 'codigo_selo' ou 'codigo_ato'.",
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
query = db.query(AtoPrincipal)
|
||||
|
||||
if codigo_selo:
|
||||
query = query.filter(AtoPrincipal.codigo_selo == codigo_selo)
|
||||
elif codigo_ato:
|
||||
query = query.filter(AtoPrincipal.codigo_ato == codigo_ato)
|
||||
|
||||
result = query.first()
|
||||
|
||||
if not result:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=[
|
||||
{
|
||||
"input": "codigo",
|
||||
"message": "Nenhum ato principal encontrado para o código informado.",
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
return result
|
||||
finally:
|
||||
db.close()
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.actions.ato_principal.ato_principal_index_action import (
|
||||
IndexAction,
|
||||
)
|
||||
|
||||
# Nota: O Schema de índice (AtoPrincipalSchema) não é importado aqui
|
||||
# porque a Action já deve fazer a conversão da lista de Models para lista de Schemas.
|
||||
|
||||
|
||||
class IndexService:
|
||||
"""
|
||||
Camada de Serviço responsável por orquestrar a listagem (Index)
|
||||
de todos os Atos Principais.
|
||||
"""
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Instânciamento da Action
|
||||
index_action = IndexAction()
|
||||
|
||||
# Executa a busca de todos os atos principais
|
||||
data = index_action.execute()
|
||||
|
||||
# Verifica se foram localizados registros
|
||||
if not data:
|
||||
# Retorna uma exceção 404
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar os atos principais.",
|
||||
)
|
||||
|
||||
# Retorna as informações localizadas
|
||||
return data
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
from fastapi import status, HTTPException
|
||||
|
||||
# Assumindo a existência dos Schemas com o prefixo 'ato_principal'
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSaveSchema,
|
||||
)
|
||||
|
||||
# Assumindo a existência da Action de salvamento com o novo prefixo
|
||||
from packages.v1.administrativo.actions.ato_principal.ato_principal_save_multiple_action import (
|
||||
SaveMultipleAction,
|
||||
)
|
||||
|
||||
|
||||
class SaveMultipleService:
|
||||
|
||||
def execute(self, atos_principais: list[AtoPrincipalSaveSchema]):
|
||||
save_action = SaveMultipleAction()
|
||||
|
||||
# A lista completa é passada diretamente para a Action.
|
||||
results = save_action.execute(atos_principais)
|
||||
|
||||
return results
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
from fastapi import status, HTTPException
|
||||
|
||||
# Assumindo a existência dos Schemas com o prefixo 'ato_principal'
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalSaveSchema,
|
||||
)
|
||||
|
||||
# Assumindo a existência da Action de salvamento com o novo prefixo
|
||||
from packages.v1.administrativo.actions.ato_principal.ato_principal_save_action import (
|
||||
SaveAction,
|
||||
)
|
||||
|
||||
|
||||
# Mantendo o padrão de nome de classe
|
||||
class SaveService:
|
||||
|
||||
def execute(self, ato_principal_schema: AtoPrincipalSaveSchema):
|
||||
|
||||
# Instânciamento da Action de salvamento
|
||||
saveAction = SaveAction()
|
||||
|
||||
# Retorna o resultado da ação de salvamento
|
||||
return saveAction.execute(ato_principal_schema)
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
from fastapi import HTTPException, status
|
||||
|
||||
# Assumindo que o novo schema se chama AtoPrincipalSchema
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import AtoPrincipalSchema
|
||||
|
||||
# Assumindo que a nova action se chama ShowAction
|
||||
from packages.v1.administrativo.actions.ato_principal.ato_principal_show_action import (
|
||||
ShowAction,
|
||||
)
|
||||
|
||||
|
||||
# Mantendo o padrão de nome de classe
|
||||
class ShowService:
|
||||
"""
|
||||
Serviço responsável por buscar os dados de um Ato Principal
|
||||
utilizando o seu ID como parâmetro de busca.
|
||||
"""
|
||||
|
||||
# O parâmetro do execute deve usar o novo Schema
|
||||
def execute(self, ato_principal_schema: AtoPrincipalSchema):
|
||||
|
||||
# Instânciamento da Action com o novo nome
|
||||
show_action = ShowAction()
|
||||
|
||||
# Executa a ação em questão (busca pelo ID)
|
||||
# O action.execute receberá o schema com o ID a ser buscado
|
||||
data = show_action.execute(ato_principal_schema)
|
||||
|
||||
if not data:
|
||||
# Retorna uma exceção 404 se não encontrar
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar o Ato Principal.",
|
||||
)
|
||||
|
||||
# Retorno da informação (dados do Ato Principal)
|
||||
return data
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# Assumindo a existência do Schema de Update com o prefixo 'ato_principal'
|
||||
from packages.v1.administrativo.schemas.ato_principal_schema import (
|
||||
AtoPrincipalUpdateSchema,
|
||||
)
|
||||
|
||||
# Assumindo a existência da Action de Update com o prefixo 'ato_principal'
|
||||
from packages.v1.administrativo.actions.ato_principal.ato_principal_update_action import (
|
||||
UpdateAction,
|
||||
)
|
||||
|
||||
|
||||
# Mantendo o padrão de nome de classe
|
||||
class UpdateService:
|
||||
"""
|
||||
Serviço responsável por coordenar a atualização de um Ato Principal
|
||||
com base no seu ID e nos dados fornecidos.
|
||||
"""
|
||||
|
||||
# Ajusta os nomes dos parâmetros para o novo prefixo
|
||||
def execute(
|
||||
self, ato_principal_id: int, ato_principal_schema: AtoPrincipalUpdateSchema
|
||||
):
|
||||
|
||||
# Instânciamento da Action
|
||||
updateAction = UpdateAction()
|
||||
|
||||
# Executa a ação de atualização, passando o ID e o Schema de atualização
|
||||
return updateAction.execute(ato_principal_id, ato_principal_schema)
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
from fastapi import HTTPException, status
|
||||
|
||||
from packages.v1.administrativo.actions.ato_principal.ato_principal_index_action import AtoPrincipalIndexAction
|
||||
|
||||
|
||||
class AtoPrincipalIndexService:
|
||||
"""
|
||||
Serviço responsável por encapsular a lógica de negócio para a operação
|
||||
de listagem de registros na tabela G_GRAMATICA.
|
||||
"""
|
||||
|
||||
def execute(self):
|
||||
"""
|
||||
Executa a operação de busca de todos os registros no banco de dados.
|
||||
|
||||
Args:
|
||||
g_cartorio_index_schema (GCartorioIndexSchema):
|
||||
Esquema que pode conter filtros ou parâmetros de busca.
|
||||
|
||||
Returns:
|
||||
A lista de registros encontrados.
|
||||
"""
|
||||
# ----------------------------------------------------
|
||||
# Instanciamento da ação
|
||||
# ----------------------------------------------------
|
||||
ato_principal_index_action = AtoPrincipalIndexAction()
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Execução da ação
|
||||
# ----------------------------------------------------
|
||||
data = ato_principal_index_action.execute()
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Verificação de retorno
|
||||
# ----------------------------------------------------
|
||||
if not data:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Não foi possível localizar registros de G_GRAMATICA."
|
||||
)
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Retorno da informação
|
||||
# ----------------------------------------------------
|
||||
return data
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
from fastapi import HTTPException, status
|
||||
from actions.jwt.create_token import CreateToken
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioAuthenticateSchema
|
||||
from packages.v1.administrativo.actions.usuario.usuario_get_by_authenticate_action import (
|
||||
GetByAuthenticateAction,
|
||||
)
|
||||
import json
|
||||
from actions.security.security import Security
|
||||
|
||||
|
||||
class AuthenticateService:
|
||||
|
||||
def execute(self, user_authenticate_schema: UsuarioAuthenticateSchema):
|
||||
|
||||
# Instância da action de autenticação
|
||||
get_by_authenticate_action = GetByAuthenticateAction()
|
||||
get_by_authenticate_result = get_by_authenticate_action.execute(
|
||||
user_authenticate_schema
|
||||
)
|
||||
|
||||
# Verifica se o usuário existe
|
||||
if not get_by_authenticate_result:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Usuário não encontrado ou credenciais inválidas",
|
||||
)
|
||||
|
||||
# Verifica se a senha armazenada é um hash válido
|
||||
if not Security.is_hash(get_by_authenticate_result.password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="A senha armazenada é inválida",
|
||||
)
|
||||
|
||||
# Verifica se a senha informada confere
|
||||
if not Security.verify_password(
|
||||
user_authenticate_schema.password, get_by_authenticate_result.password
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="Senha incorreta"
|
||||
)
|
||||
|
||||
# Verifica se o usuário está ativo
|
||||
if get_by_authenticate_result.status != "A":
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="O usuário encontra-se desativado",
|
||||
)
|
||||
|
||||
# Gera o token de acesso
|
||||
create_token = CreateToken()
|
||||
jwtUser = {
|
||||
"usuario_id": int(get_by_authenticate_result.usuario_id),
|
||||
"nome": str(get_by_authenticate_result.nome),
|
||||
"email": str(get_by_authenticate_result.email),
|
||||
}
|
||||
|
||||
return create_token.execute("access-token", json.dumps(jwtUser))
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioIdSchema
|
||||
from packages.v1.administrativo.actions.usuario.usuario_delete_action import (
|
||||
DeleteAction,
|
||||
)
|
||||
|
||||
|
||||
class DeleteService:
|
||||
|
||||
def execute(self, usuario_schema: UsuarioIdSchema):
|
||||
|
||||
# Instânciamento de ação
|
||||
delete_action = DeleteAction()
|
||||
|
||||
# Executa a ação em questão
|
||||
data = delete_action.execute(usuario_schema)
|
||||
|
||||
# Retorno da informação
|
||||
return data
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from fastapi import HTTPException, status
|
||||
|
||||
from packages.v1.administrativo.schemas.user_schema import UserCpfSchema
|
||||
from packages.v1.administrativo.actions.user.user_get_by_cpf_action import GetByUsuarioCpfAction
|
||||
|
||||
class GetCpfService:
|
||||
|
||||
def execute(self, usuario_schema: UserCpfSchema, messageValidate: bool):
|
||||
|
||||
# Instânciamento de ação
|
||||
cpf_action = GetByUsuarioCpfAction()
|
||||
|
||||
# Executa a ação em questão
|
||||
data = cpf_action.execute(usuario_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 CPF do usuário'
|
||||
)
|
||||
|
||||
# Retorno da informação
|
||||
return data
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
from fastapi import HTTPException, status
|
||||
from packages.v1.administrativo.schemas.usuario_schema import UsuarioEmailSchema
|
||||
from packages.v1.administrativo.actions.usuario.usuario_get_by_email_action import (
|
||||
GetByUsuarioEmailAction,
|
||||
)
|
||||
|
||||
|
||||
class GetEmailService:
|
||||
|
||||
def execute(self, usuario_schema: UsuarioEmailSchema, messageValidate: bool):
|
||||
|
||||
# Instânciamento de ação
|
||||
email_action = GetByUsuarioEmailAction()
|
||||
|
||||
# Executa a ação em questão
|
||||
data = email_action.execute(usuario_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 e-mail do usuário",
|
||||
)
|
||||
|
||||
# Retorno da informação
|
||||
return data
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue