diff --git a/AjustaFundos/.gitattributes b/AjustaFundos/.gitattributes deleted file mode 100644 index 0e0f35c..0000000 --- a/AjustaFundos/.gitattributes +++ /dev/null @@ -1,9 +0,0 @@ -# Normaliza finais de linha -* text=auto - -# Força Python e arquivos de configuração a usarem LF -*.py text eol=lf -*.sh text eol=lf -*.yml text eol=lf -*.yaml text eol=lf -*.env text eol=lf diff --git a/AjustaFundos/.gitignore b/AjustaFundos/.gitignore deleted file mode 100644 index 05291f8..0000000 --- a/AjustaFundos/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# Ambiente virtual -venv/ -.env -.env.* - -# Bytecode compilado -__pycache__/ -*.py[cod] -*$py.class - -# Arquivos temporários do sistema -.DS_Store -Thumbs.db - -# Logs e databases locais -*.log -*.sqlite3 - -# VSCode -.vscode/ - -# PyCharm -.idea/ - -# Arquivos de testes ou builds -*.coverage -htmlcov/ -coverage.xml -dist/ -build/ -.eggs/ -*.egg-info/ - -# Cache do pip -pip-wheel-metadata/ -*.egg -.cache/ -.tox/ - -# Arquivo s de conexão -config/database/firebird.json -storage/temp -storage/temp.json - -# Ignorar arquivos storage -storage/ \ No newline at end of file diff --git a/AjustaFundos/AjustaFundos.code-workspace b/AjustaFundos/AjustaFundos.code-workspace deleted file mode 100644 index 4267f61..0000000 --- a/AjustaFundos/AjustaFundos.code-workspace +++ /dev/null @@ -1,162 +0,0 @@ -{ - "folders": [ - { - "path": "S:/Web/Ferramentas/AjustaFundos" - } - ], - "settings": { - // ============================================================ - // 🔧 GERAL - // ============================================================ - "editor.minimap.enabled": false, - "editor.formatOnSave": true, - "editor.formatOnPaste": false, - "editor.formatOnType": false, - "files.trimTrailingWhitespace": true, - "files.autoSave": "onFocusChange", - "telemetry.telemetryLevel": "off", - "update.mode": "manual", - "workbench.startupEditor": "none", - "workbench.editor.enablePreview": false, - // ============================================================ - // ⚡ PERFORMANCE — Ignorar lixo - // ============================================================ - "files.watcherExclude": { - "**/__pycache__/**": true, - "**/.pytest_cache/**": true, - "**/.mypy_cache/**": true, - "**/.git/objects/**": true - }, - "search.exclude": { - "**/__pycache__": true, - "**/.pytest_cache": true, - "**/.mypy_cache": true, - "**/.git": true - }, - // ============================================================ - // 🐍 PYTHON - // ============================================================ - "python.defaultInterpreterPath": "S:/Web/RCCasamentoLvAntigo/venv/Scripts/python.exe", - "python.languageServer": "Pylance", - "python.analysis.autoImportCompletions": true, - "python.analysis.indexing": true, - "python.analysis.typeCheckingMode": "basic", - "python.analysis.useLibraryCodeForTypes": true, - // ============================================================ - // 🧹 FORMATADOR (Black) - // ============================================================ - "python.formatting.provider": "black", - "python.formatting.blackArgs": [ - "--line-length", - "100" - ], - "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter", - "editor.formatOnSave": true - }, - // ============================================================ - // 🔍 LINTING (Flake8) - // ============================================================ - "python.linting.enabled": true, - "python.linting.flake8Enabled": true, - "python.linting.flake8Args": [ - "--max-line-length=100" - ], - "python.linting.pylintEnabled": false, - // ============================================================ - // 🧠 GIT - // ============================================================ - "git.enabled": true, - "git.autorefresh": true, - "git.fetchOnPull": true, - "git.confirmSync": false, - "git.postCommitCommand": "sync", - "git.openDiffOnClick": true, - // ============================================================ - // 🔍 GITLENS - // ============================================================ - "gitlens.codeLens.enabled": false, - "gitlens.currentLine.enabled": false, - "gitlens.hovers.enabled": true, - "gitlens.defaultDateFormat": "DD/MM/YYYY HH:mm", - "gitlens.views.repositories.autoRefresh": true, - "gitlens.views.repositories.location": "scm", - // ============================================================ - // 💻 TERMINAL — Perfis úteis - // ============================================================ - "terminal.integrated.profiles.windows": { - "Python Shell": { - "path": "cmd.exe", - "args": [ - "/k", - "cd S:\\Web\\RCCasamentoLvAntigo && venv\\Scripts\\activate" - ] - }, - "Run Script": { - "path": "cmd.exe", - "args": [ - "/k", - "cd S:\\Web\\RCCasamentoLvAntigo && venv\\Scripts\\activate && python main.py" - ] - }, - "Git Bash": { - "path": "C:\\Program Files\\Git\\bin\\bash.exe" - } - }, - "terminal.integrated.defaultProfile.windows": "Python Shell", - "terminal.integrated.scrollback": 10000, - "terminal.integrated.enablePersistentSessions": false, - // ============================================================ - // 🗂️ FILTROS DE ARQUIVOS - // ============================================================ - "files.exclude": { - "**/.DS_Store": true, - "**/*.log": true - }, - // ============================================================ - // 🚫 DESATIVAR COPILOT (opcional) - // ============================================================ - "github.copilot.enable": { - "*": false - }, - "github.copilot.inlineSuggest.enable": false, - "editor.inlineSuggest.enabled": false - }, - // ============================================================== - // 🎯 DEBUG CONFIG — Python Standalone (não FastAPI) - // ============================================================== - "launch": { - "version": "0.2.0", - "configurations": [ - { - "name": "Debug Python — main.py", - "type": "python", - "request": "launch", - "program": "${workspaceFolder}/main.py", - "console": "integratedTerminal", - "justMyCode": true, - "cwd": "${workspaceFolder}", - "env": { - "PYTHONPATH": "${workspaceFolder}" - } - } - ] - }, - // ============================================================== - // 📦 Extensões recomendadas - // ============================================================== - "extensions": { - "recommendations": [ - "ms-python.python", - "ms-python.pylance", - "ms-python.black-formatter", - "ms-python.flake8", - "eamodio.gitlens", - "mhutchie.git-graph", - "donjayamanne.githistory", - "formulahendry.code-runner", - "streetsidesoftware.code-spell-checker", - "tamasfe.even-better-toml" - ] - } -} \ No newline at end of file diff --git a/AjustaFundos/Config.ini b/AjustaFundos/Config.ini deleted file mode 100644 index acf6429..0000000 --- a/AjustaFundos/Config.ini +++ /dev/null @@ -1,15 +0,0 @@ -;TipoBanco=Firebird ou Oracle -[Geral] - -;Palmenlo -;BaseDados=202A294B585F62033E343434D1DE15140E1F362B406F -;São Miguel -;BaseDados=202A294B242E780832343734D2DE15140E1F362B406F - -;Santa Rita -BaseDados=202A294B293F641D3A2D3634D2DE15140E1F362B406F64BABDB7B7BFA05BB0A2BDADB1BB7A - -Usuario=232C2B363138 -Senha=015D0D575858 -Key=265C425D5F461C0E564F4E58B5BB4B41394C31413F0E18B2BB -Versao='C:\OriusDekstop\Sistemas' \ No newline at end of file diff --git a/AjustaFundos/README.md b/AjustaFundos/README.md deleted file mode 100644 index ab1d803..0000000 --- a/AjustaFundos/README.md +++ /dev/null @@ -1,124 +0,0 @@ - -# VinculaPartes – Ajuste de Vínculo de Noivos no SIRC - -Aplicação em Python (empacotada em `.exe`) criada para **corrigir e vincular os dados dos noivos** entre as tabelas: - -- `V_CASAMENTO` -- `V_PESSOA_VINCULO` (que referencia `V_PESSOA`) - -Essa correção é necessária porque, **na tela do SIRC**, os dados são **validados com base nos registros de `V_PESSOA_VINCULO`**. -Sem esse vínculo correto, os dados dos noivos podem não aparecer ou não ser validados adequadamente. - ---- - -## 1. Como a aplicação funciona - -1. **Lê os dados dos noivos em `V_CASAMENTO`** - Para cada casamento, a aplicação busca as informações dos noivos já cadastradas nessa view/tabela. - -2. **Verifica se a pessoa já existe em `V_PESSOA`** - - Se **já existir** cadastro da pessoa: - - A aplicação **apenas cria o vínculo** correto em `V_PESSOA_VINCULO`. - - Se **não existir**: - - A aplicação **cria um novo registro em `V_PESSOA`** com base nos dados de `V_CASAMENTO`; - - Em seguida, **cria o vínculo** desse registro recém-criado com o casamento em `V_PESSOA_VINCULO`. - -3. **Resultado esperado** - - Todos os noivos presentes em `V_CASAMENTO` passam a ter: - - Um registro correspondente em `V_PESSOA` (quando necessário); - - Um vínculo correto em `V_PESSOA_VINCULO`, permitindo a **validação correta no SIRC**. - ---- - -## 2. Dependência do `config.ini` - -A aplicação **deve ser executada na mesma pasta em que está o arquivo `config.ini`**. - -- O `config.ini` contém os **dados de acesso ao banco de dados**. -- A aplicação **reutiliza essas mesmas credenciais** para conectar no banco (host, porta, usuário, senha, caminho da base, etc.). -- Sem o `config.ini` correto na mesma pasta, a aplicação **não conseguirá conectar** ao banco. - -> 🔹 Em resumo: -> **`VinculaPartes.exe` (ou `main.py`) e `config.ini` precisam estar lado a lado na mesma pasta.** - ---- - -## 3. Execução - -### 3.1. Pré-requisitos (modo desenvolvimento – Python) - -- Python instalado -- Biblioteca `fdb` instalada (`pip install fdb`) -- `fbclient.dll` acessível (na pasta do projeto ou em local conhecido) -- Arquivo `config.ini` configurado com os dados do banco - -Para executar via Python: - -```bash -python main.py -``` - -Certifique-se de que: - -- `main.py` -- `config.ini` -- `fbclient.dll` -estão na mesma pasta (ou com caminhos corretamente configurados). - -### 3.2. Execução do executável (`.exe`) - -Após gerado o executável: - -- Copie para a mesma pasta: - - `VinculaPartes.exe` - - `config.ini` - - `fbclient.dll` (se necessário) -- Dê duplo clique no `VinculaPartes.exe` **ou** execute pelo Prompt de Comando: - -```bash -VinculaPartes.exe -``` - ---- - -## 4. Build do executável com PyInstaller - -Para gerar o executável em modo one-file com ícone e dependências embutidas, utilize o comando: - -```bash -pyinstaller --onefile --name "VinculaPartes" --icon="images/icon.ico" --hidden-import=fdb --add-binary "fbclient.dll;." main.py -``` - -**Descrição dos parâmetros principais:** - -- `--onefile` - Gera um único arquivo executável. -- `--name "VinculaPartes"` - Define o nome do executável gerado. -- `--icon="images/icon.ico"` - Define o ícone do executável. -- `--hidden-import=fdb` - Garante que o PyInstaller inclua a biblioteca `fdb` no build. -- `--add-binary "fbclient.dll;."` - Inclui o `fbclient.dll` e o disponibiliza na mesma pasta do executável. -- `main.py` - Arquivo principal da aplicação. - -Após a compilação, o executável será gerado na pasta `dist/`: - -```text -dist/ -└── VinculaPartes.exe -``` - ---- - -## 5. Resumo - -- A aplicação **corrige o vínculo dos noivos** entre `V_CASAMENTO`, `V_PESSOA` e `V_PESSOA_VINCULO`. -- É **fundamental** para que os dados sejam **validados corretamente no SIRC**. -- **Depende do `config.ini`** para conectar ao banco de dados. -- Pode ser executada via Python (`main.py`) ou via executável (`VinculaPartes.exe`) gerado com PyInstaller. - -> Qualquer alteração futura na estrutura das tabelas ou nas regras de negócio -> deve ser refletida na lógica da aplicação antes de nova execução em produção. diff --git a/AjustaFundos/VinculaPartes.spec b/AjustaFundos/VinculaPartes.spec deleted file mode 100644 index 3c15920..0000000 --- a/AjustaFundos/VinculaPartes.spec +++ /dev/null @@ -1,39 +0,0 @@ -# -*- mode: python ; coding: utf-8 -*- - - -a = Analysis( - ['main.py'], - pathex=[], - binaries=[('fbclient.dll', '.')], - datas=[], - hiddenimports=['fdb'], - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[], - noarchive=False, - optimize=0, -) -pyz = PYZ(a.pure) - -exe = EXE( - pyz, - a.scripts, - a.binaries, - a.datas, - [], - name='VinculaPartes', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - upx_exclude=[], - runtime_tmpdir=None, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, - icon=['images\\icon.ico'], -) diff --git a/AjustaFundos/abstracts/repository_firebird.py b/AjustaFundos/abstracts/repository_firebird.py deleted file mode 100644 index f16a091..0000000 --- a/AjustaFundos/abstracts/repository_firebird.py +++ /dev/null @@ -1,177 +0,0 @@ -from typing import Any, List, Optional, Literal, Union, overload -from types import SimpleNamespace -from datetime import datetime, date - -from sqlalchemy import text -from sqlalchemy.engine import CursorResult -from sqlalchemy.exc import SQLAlchemyError - -from actions.ui.ui import warn -from database.firebird import Firebird - - -class BaseRepositoryFirebird: - - # ------------------------------------------------------------------ - # Sobrecargas - # ------------------------------------------------------------------ - @overload - def _execute( - self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["all"] - ) -> List[Any]: ... - - @overload - def _execute( - self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["one"] - ) -> Optional[Any]: ... - - @overload - def _execute( - self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["none"] - ) -> None: ... - - @overload - def _execute( - self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["result"] - ) -> CursorResult[Any]: ... - - # ------------------------------------------------------------------ - # Sanitizador seguro de parâmetros (CORREÇÃO CRÍTICA) - # ------------------------------------------------------------------ - def _sanitize_params(self, params: Optional[dict[str, Any]]) -> dict[str, Any]: - """ - Sanitiza parâmetros antes de enviar ao Firebird. - Trava datas inválidas (< 1900) e remove timezone para evitar overflow. - """ - if params is None: - return {} - - safe: dict[str, Any] = {} - - for key, value in params.items(): - - # Permite None normalmente - if value is None: - safe[key] = None - continue - - # --------------------------- - # Tratamento de datetime - # --------------------------- - if isinstance(value, datetime): - - # Firebird explode com datas muito antigas - if value.year < 1900: - warn( - f"⚠️ Data inválida detectada em '{key}': {value} " - f"(ano < 1900). Definido como NULL para evitar overflow." - ) - safe[key] = None - continue - - # Remove timezone se existir (evita timestamp negativo!) - if value.tzinfo is not None: - safe[key] = value.replace(tzinfo=None) - else: - safe[key] = value - continue - - # --------------------------- - # Tratamento de date - # --------------------------- - if isinstance(value, date): - if value.year < 1900: - warn( - f"⚠️ Data de calendário inválida em '{key}': {value}. " - f"Convertido para NULL." - ) - safe[key] = None - else: - safe[key] = value - continue - - # Outros valores seguem direto - safe[key] = value - - return safe - - # ------------------------------------------------------------------ - # Execução de SQL - # ------------------------------------------------------------------ - def _execute( - self, - sql: str, - params: Optional[dict[str, Any]] = None, - fetch: Literal["all", "one", "none", "result"] = "result", - ) -> Union[List[Any], Optional[Any], None, CursorResult[Any]]: - - engine = Firebird.get_engine() - - # 🔥 Sanitiza todos os parâmetros antes de enviar ao driver - safe_params = self._sanitize_params(params) - - try: - with engine.begin() as conn: - result = conn.execute(text(sql), safe_params) - - # Lê BLOBs com segurança - def _read_blob(value): - if hasattr(value, "read"): - try: - return value.read() - except Exception: - return b"" - return value - - # all - if fetch == "all": - rows = [] - for row in result.mappings().all(): - row_dict = {k.lower(): _read_blob(v) for k, v in row.items()} - rows.append(SimpleNamespace(**row_dict)) - return rows - - # one - elif fetch == "one": - row = result.mappings().first() - if row: - row_dict = {k.lower(): _read_blob(v) for k, v in row.items()} - return SimpleNamespace(**row_dict) - return None - - # none - elif fetch == "none": - return None - - # result - return result - - except SQLAlchemyError as e: - warn("⚠️ [ERRO SQL]: execução falhou") - warn(f"SQL:\n{sql}") - warn(f"Parâmetros SANITIZADOS enviados ao banco:\n{safe_params}") - raise - - # ------------------------------------------------------------------ - # Métodos utilitários públicos - # ------------------------------------------------------------------ - def query( - self, sql: str, params: Optional[dict[str, Any]] = None - ) -> CursorResult[Any]: - return self._execute(sql, params, fetch="result") - - def fetch_all(self, sql: str, params: Optional[dict[str, Any]] = None) -> List[Any]: - return self._execute(sql, params, fetch="all") - - def fetch_one( - self, sql: str, params: Optional[dict[str, Any]] = None - ) -> Optional[Any]: - return self._execute(sql, params, fetch="one") - - def run(self, sql: str, params: Optional[dict[str, Any]] = None) -> None: - self._execute(sql, params, fetch="none") - - def run_and_return( - self, sql: str, params: Optional[dict[str, Any]] = None - ) -> Optional[Any]: - return self._execute(sql, params, fetch="one") diff --git a/AjustaFundos/actions/config/config_ini.py b/AjustaFundos/actions/config/config_ini.py deleted file mode 100644 index 8e04b94..0000000 --- a/AjustaFundos/actions/config/config_ini.py +++ /dev/null @@ -1,91 +0,0 @@ -# Importa o módulo padrão do Python para ler arquivos INI (.ini) -import configparser - -# Importa Path, que facilita o trabalho com caminhos de arquivos (mais seguro que strings) -from pathlib import Path - -# Importa tipos para anotações — Dict (dicionário) e Any (qualquer tipo) -from typing import Dict, Any - - -# Define uma classe chamada ConfigIni -class ConfigIni: - - @staticmethod - def read(path: str) -> Dict[str, Any]: - """ - Lê um arquivo INI (ignorando comentários iniciados por ';') - e retorna um dicionário com suas seções e pares chave=valor. - - Tenta múltiplas codificações comuns no Windows: - - utf-8 - - utf-8-sig - - latin-1 - - cp1252 - """ - - # Converte o caminho recebido (string) em um objeto Path (mais seguro e portável) - config_path = Path(path) - - # Verifica se o arquivo realmente existe no caminho informado - if not config_path.exists(): - # Caso não exista, lança uma exceção com uma mensagem explicativa - raise FileNotFoundError(f"Arquivo não encontrado: {path}") - - # Lista de codificações a tentar, em ordem de preferência - encodings_to_try = ["utf-8", "utf-8-sig", "latin-1", "cp1252"] - - last_error: Exception | None = None - config: configparser.ConfigParser | None = None - - # Tenta ler o arquivo usando diferentes encodings - for enc in encodings_to_try: - try: - tmp_config = configparser.ConfigParser() - # Garante que as chaves mantenham o mesmo formato de maiúsculas/minúsculas - # Por padrão, o configparser converte tudo para minúsculas. - tmp_config.optionxform = str - - # Tenta ler o arquivo com a codificação atual - tmp_config.read(config_path, encoding=enc) - - # Se chegou aqui sem UnicodeDecodeError, consideramos que deu certo - config = tmp_config - break - except UnicodeDecodeError as e: - # Guarda o último erro para caso nenhuma codificação funcione - last_error = e - continue - - # Se nenhuma codificação funcionou, levanta um erro mais amigável - if config is None: - msg = ( - f"Não foi possível decodificar o arquivo INI '{path}' " - f"usando as codificações: {', '.join(encodings_to_try)}" - ) - if last_error: - raise UnicodeDecodeError( - last_error.encoding or "utf-8", - last_error.object, - last_error.start, - last_error.end, - msg, - ) - raise RuntimeError(msg) - - # Cria um dicionário vazio que armazenará os dados lidos do INI - data: Dict[str, Dict[str, Any]] = {} - - # Percorre cada seção do arquivo INI (exemplo: [Geral], [Banco], etc.) - for section in config.sections(): - # Cria um dicionário interno para armazenar as chaves e valores dessa seção - data[section] = {} - - # Percorre todas as chaves e valores da seção atual - for key, value in config.items(section): - # .strip() remove espaços no início/fim - # .strip("'\"") remove aspas simples ou duplas em volta do valor (se existirem) - data[section][key] = value.strip().strip("'\"") - - # Retorna o dicionário completo contendo todas as seções e seus pares chave=valor - return data diff --git a/AjustaFundos/actions/data/dict_to_obj.py b/AjustaFundos/actions/data/dict_to_obj.py deleted file mode 100644 index 17d80d1..0000000 --- a/AjustaFundos/actions/data/dict_to_obj.py +++ /dev/null @@ -1,19 +0,0 @@ -from types import SimpleNamespace -from collections.abc import Mapping - - -class DictToObj: - def __new__(cls, x): - # dict (ou Mapping): vira SimpleNamespace com conversão recursiva - if isinstance(x, Mapping): - return SimpleNamespace(**{k: cls(v) for k, v in x.items()}) - # listas: converte cada item - if isinstance(x, list): - return [cls(i) for i in x] - # (opcional) outras coleções comuns - if isinstance(x, tuple): - return tuple(cls(i) for i in x) - if isinstance(x, set): - return {cls(i) for i in x} - # primitivos: retornam como estão - return x diff --git a/AjustaFundos/actions/data/ensure_batch_limit.py b/AjustaFundos/actions/data/ensure_batch_limit.py deleted file mode 100644 index a50b25d..0000000 --- a/AjustaFundos/actions/data/ensure_batch_limit.py +++ /dev/null @@ -1,24 +0,0 @@ -from actions.data.json_size import JsonSize - - -class EnsureBatchLimit: - - # ------------------------------------------------------------------ - # Função reutilizável: recebe o lote (array) e o item, respeita o limite - # Retorna (to_send, new_batch): - # - se couber: (None, batch_com_item) - # - se não couber: (batch_atual_para_envio, novo_batch_com_item) - # ------------------------------------------------------------------ - def execute(self, batch: list, item, max_bytes: int): - - batch_size = JsonSize(batch) - item_size = JsonSize(item) - - if batch_size + item_size <= max_bytes: - batch.append(item) - return None, batch # nada a enviar agora - else: - # não coube: envia o lote atual e começa um novo com o item - to_send = batch[:] # cópia para envio - new_batch = [item] - return to_send, new_batch diff --git a/AjustaFundos/actions/data/generate_insert_sql.py b/AjustaFundos/actions/data/generate_insert_sql.py deleted file mode 100644 index 3f19c37..0000000 --- a/AjustaFundos/actions/data/generate_insert_sql.py +++ /dev/null @@ -1,52 +0,0 @@ -from pydantic import BaseModel -from decimal import Decimal - - -def generate_insert_sql(table_name: str, data: BaseModel | dict) -> str: - """ - Gera um comando SQL INSERT seguro para Firebird. - - Aceita BaseModel (Pydantic) ou dict. - - Ignora *_ID None. - - Mantém colunas em MAIÚSCULAS e parâmetros em minúsculas (para bind funcionar). - """ - - # Converte o model em dict limpo - if isinstance(data, BaseModel): - data_dict = data.model_dump(exclude_unset=True) - elif isinstance(data, dict): - data_dict = data - else: - raise TypeError("O parâmetro 'data' deve ser um BaseModel ou dict.") - - columns = [] - params = [] - returning_fields = [] - - for key, value in data_dict.items(): - column_name = key.upper() - - # Converte Decimal → float - if isinstance(value, Decimal): - data_dict[key] = float(value) - - # Campos válidos para retorno - if value is not None: - returning_fields.append(column_name) - - # Coluna em maiúsculo, parâmetro em minúsculo - columns.append(column_name) - params.append(f":{key}") - - columns_str = ", ".join(columns) - params_str = ", ".join(params) - returning_str = ", ".join(returning_fields) if returning_fields else "*" - - sql = ( - f"INSERT INTO {table_name} (\n" - f" {columns_str}\n" - f") VALUES (\n" - f" {params_str}\n" - f") RETURNING {returning_str};" - ) - - return sql diff --git a/AjustaFundos/actions/data/is_blank.py b/AjustaFundos/actions/data/is_blank.py deleted file mode 100644 index e91f065..0000000 --- a/AjustaFundos/actions/data/is_blank.py +++ /dev/null @@ -1,12 +0,0 @@ -class IsBlank: - - @staticmethod - def __new__(self, val) -> bool: - - if val is None: - return True - - if isinstance(val, (str, bytes)): - return len(val.strip()) == 0 - - return False diff --git a/AjustaFundos/actions/data/json_size.py b/AjustaFundos/actions/data/json_size.py deleted file mode 100644 index 2642119..0000000 --- a/AjustaFundos/actions/data/json_size.py +++ /dev/null @@ -1,33 +0,0 @@ -import json -from types import SimpleNamespace - - -class JsonSize: - @staticmethod - def _safe_default(o): - from datetime import datetime, date - from decimal import Decimal - - if isinstance(o, (datetime, date)): - return o.isoformat() - if isinstance(o, Decimal): - return float(o) - if isinstance(o, SimpleNamespace): - return vars(o) - if hasattr(o, "__dict__"): - return vars(o) - return str(o) - - def __new__(cls, obj): - try: - # 💡 ensure_ascii=False mantém acentos; surrogatepass evita falha com caracteres inválidos - json_str = json.dumps( - obj, - ensure_ascii=False, - default=cls._safe_default, - ) - # 💡 errors='ignore' ou 'replace' evita que .encode() quebre - return len(json_str.encode("utf-8", errors="ignore")) - except Exception: - # fallback de segurança (nunca deve quebrar) - return len(str(obj).encode("utf-8", errors="ignore")) diff --git a/AjustaFundos/actions/data/obj_to_dict.py b/AjustaFundos/actions/data/obj_to_dict.py deleted file mode 100644 index d3e19d7..0000000 --- a/AjustaFundos/actions/data/obj_to_dict.py +++ /dev/null @@ -1,34 +0,0 @@ -from types import SimpleNamespace -from collections.abc import Mapping -from decimal import Decimal -from datetime import datetime, date - - -class ObjToDict: - def __new__(cls, x): - # SimpleNamespace -> dict (recursivo) - if isinstance(x, SimpleNamespace): - return {k: cls(v) for k, v in vars(x).items()} - - # dict / Mapping -> dict (recursivo) - if isinstance(x, Mapping): - return {k: cls(v) for k, v in x.items()} - - # listas/tuplas/conjuntos -> preserva tipo - if isinstance(x, list): - return [cls(i) for i in x] - if isinstance(x, tuple): - return tuple(cls(i) for i in x) - if isinstance(x, set): - return {cls(i) for i in x} - - # Decimal -> float - if isinstance(x, Decimal): - return float(x) - - # datetime / date -> string ISO (compatível com JSON) - if isinstance(x, (datetime, date)): - return x.isoformat() - - # Outros tipos -> mantém - return x diff --git a/AjustaFundos/actions/file/file_name_generator.py b/AjustaFundos/actions/file/file_name_generator.py deleted file mode 100644 index 17d7ffc..0000000 --- a/AjustaFundos/actions/file/file_name_generator.py +++ /dev/null @@ -1,20 +0,0 @@ -from datetime import datetime - - -class FileNameGenerator: - """ - Gera nomes de arquivos únicos com base na data e hora atuais. - Exemplo: relatorio_2025-11-11_17-43-22.txt - """ - - def __init__( - self, - prefix: str = "arquivo", - ): - self.prefix = prefix - - def generate(self, prefix="arquivo") -> str: - """Gera o nome completo do arquivo com base na data e hora.""" - timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") - filename = f"{prefix}_{timestamp}" - return str(filename) diff --git a/AjustaFundos/actions/file/input_base_resolver.py b/AjustaFundos/actions/file/input_base_resolver.py deleted file mode 100644 index cf45d28..0000000 --- a/AjustaFundos/actions/file/input_base_resolver.py +++ /dev/null @@ -1,88 +0,0 @@ -import platform -from typing import Dict, Tuple - -from actions.env.mirror_sync_env import MirrorSyncEnv -from actions.ui.ui import warn, fail -from packages.v1.parametros.repositories.g_config.g_config_show_by_nome_repository import ( - GConfigShowByNomeRepository, -) -from packages.v1.parametros.schemas.g_config_schema import GConfigNomeSchema - - -class InputBaseResolver: - """ - Resolve dinamicamente caminhos base do GED sem precisar passar nada externo. - Apenas: - get_input_base(nome_variavel, sistema_id) - - Tudo o resto — carregar MirrorSyncEnv, decrypt, buscar LOCAL_IMAGEM — - é feito internamente. - """ - - def __init__(self): - # Carrega ENV automaticamente - self.env = MirrorSyncEnv().as_object() - - # GConfig carregado internamente - self.g_config_repo = GConfigShowByNomeRepository() - - # Cache por chave (env_var_name, sistema_id) - self._cache: Dict[Tuple[str, int], str] = {} - - # ------------------------------------------------------- - def get_input_base(self, env_var_name: str, sistema_id: int) -> str: - """ - Obtém dinamicamente o caminho do GED: - - Se Windows + ged_local=True → retorna variável do .env - - Se Windows + ged_local=False → busca LOCAL_IMAGEM no GConfig - - Se Linux → sempre retorna variável do .env - - Parâmetros: - env_var_name: nome da variável de ambiente (ex.: "ged_tabelionato") - sistema_id: ID do sistema (ex.: 2) - """ - - cache_key = (env_var_name, sistema_id) - - if cache_key in self._cache: - return self._cache[cache_key] - - resolved = self._resolve_path(env_var_name, sistema_id) - self._cache[cache_key] = resolved or "" - return resolved - - # ------------------------------------------------------- - def _resolve_path(self, env_var_name: str, sistema_id: int) -> str: - system = platform.system() - - ged_local = str(getattr(self.env, "ged_local", "false")).lower() == "true" - dynamic_path = getattr(self.env, env_var_name, "") - - # ---------------- WINDOWS ---------------- - if system == "Windows": - if ged_local: - # Usa o caminho vindo do .env (dinâmico) - return dynamic_path - - # Busca LOCAL_IMAGEM no GConfig - return self._resolve_from_gconfig(sistema_id) - - # ---------------- LINUX ------------------ - if system == "Linux": - return dynamic_path - - # ---------------- OUTROS ----------------- - warn(f"Sistema operacional não suportado: {system}") - return "" - - # ------------------------------------------------------- - def _resolve_from_gconfig(self, sistema_id: int) -> str: - """Busca LOCAL_IMAGEM no GConfig automaticamente.""" - try: - result = self.g_config_repo.execute( - GConfigNomeSchema(nome="LOCAL_IMAGEM", sistema_id=sistema_id) - ) - return result.valor - except Exception as e: - fail(f"Erro no GConfig (sistema_id={sistema_id}): {e}") - return "" diff --git a/AjustaFundos/actions/file/json_file_loader.py b/AjustaFundos/actions/file/json_file_loader.py deleted file mode 100644 index acbd193..0000000 --- a/AjustaFundos/actions/file/json_file_loader.py +++ /dev/null @@ -1,69 +0,0 @@ -import json -from json import JSONDecodeError -from types import SimpleNamespace -from pathlib import Path -from typing import Any, Optional, Union - - -class JsonFileLoader: - """ - Carrega arquivos JSON e retorna como objeto (SimpleNamespace) ou dict. - Retorna None quando não houver arquivo ou dados. - """ - - def __init__(self, file_path: Union[str, Path], encoding: str = "utf-8"): - self.path = Path(file_path) - self.encoding = encoding - - def load( - self, as_namespace: bool = True, empty_as_none: bool = True - ) -> Optional[Any]: - """ - Lê o JSON do disco. - - as_namespace=True: retorna SimpleNamespace (com conversão recursiva). - - as_namespace=False: retorna dict/list nativos. - - empty_as_none=True: {}, [] ou None são tratados como "sem dados" e retornam None. - """ - # 1) Arquivo inexistente ou não regular - if not self.path.exists() or not self.path.is_file(): - return None - - # 2) Arquivo vazio - if self.path.stat().st_size == 0: - return None - - # 3) Leitura + limpeza - try: - with self.path.open("r", encoding=self.encoding) as f: - raw = f.read() - except OSError: - return None - - raw = (raw or "").strip() - if not raw: - return None - - # 4) Parse do JSON - try: - data = json.loads(raw) - except JSONDecodeError: - return None - - # 5) Tratar dados vazios - if empty_as_none and (data is None or data == {} or data == []): - return None - - # 6) Converter (opcional) para SimpleNamespace - return self._to_namespace(data) if as_namespace else data - - # ---------- helpers ---------- - @classmethod - def _to_namespace(cls, value: Any) -> Any: - """Converte recursivamente dict/list em SimpleNamespace/list.""" - if isinstance(value, dict): - return SimpleNamespace( - **{k: cls._to_namespace(v) for k, v in value.items()} - ) - if isinstance(value, list): - return [cls._to_namespace(v) for v in value] - return value diff --git a/AjustaFundos/actions/file/json_file_merge.py b/AjustaFundos/actions/file/json_file_merge.py deleted file mode 100644 index 9f91540..0000000 --- a/AjustaFundos/actions/file/json_file_merge.py +++ /dev/null @@ -1,180 +0,0 @@ -import json -import traceback -from pathlib import Path -from types import SimpleNamespace -from typing import Any, Optional, Literal, Union - -from pydantic import BaseModel - -from actions.file.json_file_saver import JsonFileSaver - - -class JsonFileMerger: - """ - Classe utilitária para unir um novo JSON com um existente em disco, - aplicando merge profundo e salvando o resultado final. - - Mantém o mesmo padrão seguro de conversão da classe JsonFileSaver. - """ - - def __init__(self, saver: Optional[JsonFileSaver] = None): - self.saver = saver or JsonFileSaver() - - # ------------------------------------------------------------ - # Carrega JSON existente (se houver) - # ------------------------------------------------------------ - def _load_existing(self, file_path: Path) -> Any: - if not file_path.exists(): - return {} - try: - with open(file_path, "r", encoding=self.saver.encoding) as f: - return json.load(f) - except Exception: - # Em caso de erro, considera como vazio para não quebrar o fluxo - return {} - - # ------------------------------------------------------------ - # Merge de listas (não duplica itens) - # ------------------------------------------------------------ - def _merge_lists(self, base_list: list, new_list: list) -> list: - combined = base_list[:] - for item in new_list: - if item not in combined: - combined.append(item) - return combined - - # ------------------------------------------------------------ - # Merge profundo (deep merge) para dicionários - # ------------------------------------------------------------ - def _deep_merge(self, base: dict, new: dict) -> dict: - for key, value in new.items(): - if key in base: - # dict + dict → merge recursivo - if isinstance(base[key], dict) and isinstance(value, dict): - base[key] = self._deep_merge(base[key], value) - - # list + list → merge de listas - elif isinstance(base[key], list) and isinstance(value, list): - base[key] = self._merge_lists(base[key], value) - - # tipos diferentes ou simples → substitui - else: - base[key] = value - else: - base[key] = value - - return base - - # ------------------------------------------------------------ - # Estratégias de merge - # ------------------------------------------------------------ - def _apply_strategy(self, existing: Any, new: Any, strategy: str) -> Any: - # Se ambos forem listas, usa merge de listas - if isinstance(existing, list) and isinstance(new, list): - return self._merge_lists(existing, new) - - # Se tipos forem diferentes, substitui completamente - if type(existing) is not type(new): - return new - - # replace → ignora o que existia - if strategy == "replace": - return new - - # update → comportamento similar a dict.update (apenas para dicts) - if strategy == "update": - if isinstance(existing, dict) and isinstance(new, dict): - existing.update(new) - return existing - # para outros tipos, apenas substitui - return new - - # default / "deep" → deep merge para dicts - if strategy == "deep": - if isinstance(existing, dict) and isinstance(new, dict): - return self._deep_merge(existing, new) - # se não forem dicts, substitui - return new - - # fallback: se for estratégia desconhecida, substitui - return new - - # ------------------------------------------------------------ - # NOVO MÉTODO — merge sem salvar (apenas processa) - # ------------------------------------------------------------ - def merge_data( - self, - existing_json: Any, - new_json: Union[dict, BaseModel, SimpleNamespace], - strategy: Literal["replace", "update", "deep"] = "deep", - ) -> Any: - - new_clean = self.saver._convert(new_json) - return self._apply_strategy(existing_json, new_clean, strategy) - - # ------------------------------------------------------------ - # MÉTODO PRINCIPAL — AGORA USANDO merge_data() - # ------------------------------------------------------------ - def merge_and_save( - self, - new_json: Union[dict, BaseModel, SimpleNamespace], - file_path: str, - strategy: Literal["replace", "update", "deep"] = "deep", - add_timestamp: bool = False, - ) -> dict: - """ - Faz merge entre existing.json ← new_json e salva o resultado final. - - Parâmetros: - new_json: - - Dado novo que será mesclado ao JSON existente. - Pode ser dict, BaseModel ou SimpleNamespace. - - file_path: - - Caminho do arquivo JSON em disco. - - strategy: - - "replace" → sobrescreve tudo - - "update" → comportamento semelhante a dict.update - - "deep" → merge recursivo (deep merge) para dicts - e merge de listas sem duplicação - - add_timestamp: - - Se True, adiciona timestamp no nome do arquivo ao salvar. - - Retorno: - dict com: - { - "success": bool, - "path": str, - "size": int, - "error": Optional[str], - } - """ - try: - path = Path(file_path) - path.parent.mkdir(parents=True, exist_ok=True) - - # Carrega JSON existente - existing = self._load_existing(path) - - # Novo merge utilizando merge_data() - merged = self.merge_data(existing, new_json, strategy) - - # Salva em disco - return self.saver.save( - data=merged, - file_path=str(path), - as_json=True, - add_timestamp=add_timestamp, - mode="overwrite", - ) - - except Exception as e: - traceback.print_exc() - return { - "success": False, - "path": file_path, - "size": 0, - "error": str(e), - } diff --git a/AjustaFundos/actions/file/json_file_saver.py b/AjustaFundos/actions/file/json_file_saver.py deleted file mode 100644 index 4705598..0000000 --- a/AjustaFundos/actions/file/json_file_saver.py +++ /dev/null @@ -1,133 +0,0 @@ -import json -import traceback -from datetime import datetime, date -from decimal import Decimal -from types import SimpleNamespace -from pathlib import Path -from typing import Any, Optional, Literal, Union -from pydantic import BaseModel - -# ✔️ agora usando sua UI -from actions.ui.ui import ok, fail - - -class JsonFileSaver: - """ - Classe utilitária para salvar qualquer tipo de dado em disco, - automaticamente convertido para JSON se aplicável. - - Suporta: dict, list, str, bytes, BaseModel, SimpleNamespace, Decimal, datetime, etc. - """ - - def __init__( - self, - encoding: str = "utf-8", - indent: int = 4, - default_suffix: str = ".json", - ): - self.encoding = encoding - self.indent = indent - self.default_suffix = default_suffix - - # ------------------------------------------------------------ - # Método público principal - # ------------------------------------------------------------ - def save( - self, - data: Union[str, bytes, dict, list, Any], - file_path: str, - as_json: Optional[bool] = None, - add_timestamp: bool = False, - mode: Literal["overwrite", "append"] = "overwrite", - ) -> dict: - """ - Salva o conteúdo em disco com serialização segura. - """ - try: - path = Path(file_path) - path.parent.mkdir(parents=True, exist_ok=True) - - # Adiciona timestamp no nome, se solicitado - if add_timestamp: - timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") - stem = path.stem - suffix = path.suffix or self.default_suffix - path = path.with_name(f"{stem}_{timestamp}{suffix}") - - # Detecta automaticamente se é JSON - if as_json is None: - as_json = isinstance(data, (dict, list, SimpleNamespace, BaseModel)) - - # Define o modo de escrita - write_mode = ( - "wb" if isinstance(data, bytes) else "a" if mode == "append" else "w" - ) - - # Salva arquivo - if isinstance(data, bytes): - with open(path, write_mode) as f: - f.write(data) - - elif as_json: - safe_data = self._convert(data) - with open(path, write_mode, encoding=self.encoding) as f: - json.dump(safe_data, f, ensure_ascii=False, indent=self.indent) - - else: - if not isinstance(data, str): - data = str(data) - with open(path, write_mode, encoding=self.encoding) as f: - f.write(data) - - file_size = path.stat().st_size if path.exists() else 0 - - # ✔️ substitui print() por UI - ok(f"Arquivo salvo: {path} ({file_size} bytes)") - - return { - "success": True, - "path": str(path.resolve()), - "size": file_size, - "error": None, - } - - except Exception as e: - error_message = ( - f"Falha ao salvar arquivo '{file_path}': {e}\n" - f"{traceback.format_exc()}" - ) - - # ✔️ substitui print de erro por UI - fail(error_message) - - return { - "success": False, - "path": str(file_path), - "size": 0, - "error": str(e), - } - - # ------------------------------------------------------------ - # Conversor recursivo interno - # ------------------------------------------------------------ - def _convert(self, obj: Any) -> Any: - """Converte qualquer tipo para formato serializável JSON.""" - if obj is None: - return None - if isinstance(obj, (str, int, float, bool)): - return obj - if isinstance(obj, bytes): - return obj.decode("utf-8", errors="ignore") - if isinstance(obj, Decimal): - return float(obj) - if isinstance(obj, (datetime, date)): - return obj.isoformat() - if isinstance(obj, SimpleNamespace): - return {k: self._convert(v) for k, v in vars(obj).items()} - if isinstance(obj, BaseModel): - return obj.model_dump() - if isinstance(obj, list): - return [self._convert(i) for i in obj] - if isinstance(obj, dict): - return {k: self._convert(v) for k, v in obj.items()} - return str(obj) diff --git a/AjustaFundos/actions/file/json_merge.py b/AjustaFundos/actions/file/json_merge.py deleted file mode 100644 index b6f950d..0000000 --- a/AjustaFundos/actions/file/json_merge.py +++ /dev/null @@ -1,67 +0,0 @@ -import json -import threading -from pathlib import Path -from typing import Dict, List, Any - - -class JsonArrayPersistentStorage: - """ - Classe para gravar e atualizar um JSON de forma persistente, - com MERGE profundo e proteção contra escrita paralela. - """ - - def __init__(self, caminho_arquivo: Path): - self.caminho = caminho_arquivo - self.lock = threading.Lock() # 🔒 proteção de escrita - self.caminho.parent.mkdir(parents=True, exist_ok=True) - self._cache = self._load_existing() - - # ------------------------------------------------------------------ - def _load_existing(self) -> Dict[str, Any]: - if not self.caminho.exists(): - return {} - try: - with open(self.caminho, "r", encoding="utf-8") as f: - return json.load(f) - except Exception: - return {} - - # ------------------------------------------------------------------ - def _deep_merge(self, original: Any, novo: Any) -> Any: - if isinstance(original, dict) and isinstance(novo, dict): - for k, v in novo.items(): - if k not in original: - original[k] = v - else: - original[k] = self._deep_merge(original[k], v) - return original - - if isinstance(original, list) and isinstance(novo, list): - for item in novo: - if item not in original: - original.append(item) - return original - - return novo - - # ------------------------------------------------------------------ - def _save(self): - with open(self.caminho, "w", encoding="utf-8") as f: - json.dump(self._cache, f, indent=4, ensure_ascii=False) - - # ------------------------------------------------------------------ - # MÉTODO QUE RESOLVE O ERRO - AGORA COM LOCK - # ------------------------------------------------------------------ - def add(self, novos_dados: Dict[str, List[dict]]): - """ - Adiciona novos dados com merge profundo. - Protegido por lock para evitar race condition. - """ - - with self.lock: # 🔒 trava escrita e merge até finalizar - self._cache = self._deep_merge(self._cache, novos_dados) - self._save() - - # ------------------------------------------------------------------ - def get_all(self) -> Dict[str, Any]: - return self._cache diff --git a/AjustaFundos/actions/file/localizar_arquivo_por_id.py b/AjustaFundos/actions/file/localizar_arquivo_por_id.py deleted file mode 100644 index d3b69d4..0000000 --- a/AjustaFundos/actions/file/localizar_arquivo_por_id.py +++ /dev/null @@ -1,300 +0,0 @@ -from pathlib import Path -from typing import Optional, Iterable, Dict, Any, List, TypedDict -from actions.string.file_name_generator import FileNameGenerator -from actions.ui.ui import ok, warn, fail - - -# ------------------------------------------------------------------- -# TRATATIVA DE ERRO SMB — WinError 64 (Rede indisponível) -# ------------------------------------------------------------------- -def _exists_safe(path: Path, verbose: bool = True) -> bool: - """ - Verifica se o path existe sem explodir WinError 64 (rede indisponível). - """ - try: - return path.exists() - except OSError as e: - if getattr(e, "winerror", None) == 64: - if verbose: - fail(f"⚠️ Rede indisponível ao acessar: {path}") - return False - raise - - -# ------------------------------------------------------------------- -# VERIFICAÇÃO REAL DE ACESSO AO ARQUIVO -# ------------------------------------------------------------------- -def can_open_file(path: Path, verbose: bool = True) -> bool: - """ - Garante que o arquivo pode ser aberto — diferentemente de .exists(). - Captura erros reais de SMB/Permissão. - """ - try: - with open(path, "rb"): - return True - - except PermissionError: - if verbose: - fail(f"❌ Permissão negada ao tentar abrir: {path}") - return False - - except FileNotFoundError: - if verbose: - fail(f"❌ Arquivo não encontrado no momento da abertura: {path}") - return False - - except OSError as e: - if verbose: - fail(f"⚠️ Erro ao abrir arquivo ({e}) → {path}") - return False - - -# --------------------------------------------------------------- -# TABELAS DE TIPOS -# --------------------------------------------------------------- -class ArquivoLocalizado(TypedDict): - caminho_arquivo: str - tipo_documento: str - nome_documento: str - - -TIPOS_PADRAO: Dict[str, Dict[str, str]] = { - "Ato": {"base": "Ato", "prefixo": "A_", "tipo_documento": "ATO_LAVRADO"}, - "Cartao": { - "base": "Cartao", - "prefixo": "C_", - "tipo_documento": "DOCUMENTO_PESSOAL", - }, - "Biometria": { - "base": "Biometria", - "prefixo": "Biometria_", - "tipo_documento": "DOCUMENTO_PESSOAL", - }, - "Procuracao": { - "base": "Procuracao", - "prefixo": "P_", - "tipo_documento": "PROCURACAO", - }, - "Documento": { - "base": "Documento", - "prefixo": "D_", - "tipo_documento": "DOCUMENTO_PESSOAL", - }, - "Registro": {"base": "Registro", "prefixo": "R_", "tipo_documento": "MATRICULA"}, - "Contrato": {"base": "Contrato", "prefixo": "T_", "tipo_documento": "CONTRATO"}, - "Dut": {"base": "Dut", "prefixo": "U_", "tipo_documento": "OUTROS"}, - "RegistroImoveis": {"base": "", "prefixo": "R_", "tipo_documento": "MATRICULA"}, -} - -PREFIXOS_RC: Dict[str, List[str]] = { - "nascimento": ["L_A_", "C_A_"], - "casamento": ["L_B_", "C_B_"], - "obito": ["L_C_", "C_C_"], - "estrangeiro": ["L_E_", "C_E_"], - "averbacao": ["R_A_"], -} - -EXTS: tuple[str, ...] = (".spd", ".tif", ".tiff") - - -# --------------------------------------------------------------- -# FUNÇÕES AUXILIARES -# --------------------------------------------------------------- -def _nomes_possiveis( - prefixos: Iterable[str], - id6: str, - sufixos_extras: Optional[Iterable[str]] = None, -) -> List[str]: - simbolos = ("#", "_", "") - sufixos = list(sufixos_extras) if sufixos_extras is not None else [""] - nomes: List[str] = [] - - for prefixo in prefixos: - for extra in sufixos: - for simbolo in simbolos: - for ext in EXTS: - nomes.append(f"{prefixo}{id6}{extra}{simbolo}{ext}") - - return nomes - - -def _calcular_pasta(arquivo_id: int) -> str: - if arquivo_id < 1000: - return f"{arquivo_id:03d}" - return str(arquivo_id)[:3] - - -def _gerar_nome_documento(caminho: Path, tipo_documento: str) -> str: - base_sem_ext = caminho.stem - return FileNameGenerator.generate(base_sem_ext) - - -def _montar_retorno(caminho: Path, tipo_documento: str) -> ArquivoLocalizado: - return ArquivoLocalizado( - caminho_arquivo=str(caminho), - tipo_documento=tipo_documento, - nome_documento=_gerar_nome_documento(caminho, tipo_documento), - ) - - -# --------------------------------------------------------------- -# FUNÇÃO PRINCIPAL — agora com verificação REAL de acesso SMB -# --------------------------------------------------------------- -def localizar_arquivo_por_id( - arquivo_id: Optional[int | float], - pasta_origem: str, - natureza: Optional[str] = None, - tipos_permitidos: Optional[Iterable[str]] = None, - registro: Optional[str] = None, - livro: Optional[str] = None, - registro_anterior: Optional[str] = None, - verbose: bool = True, -) -> Optional[Dict[str, Any]]: - - if arquivo_id is None: - if verbose: - warn("ID inválido (None) — Ignorando busca de arquivo.") - return None - - try: - arquivo_id_int = int(arquivo_id) - except (TypeError, ValueError): - if verbose: - warn(f"ID inválido ({arquivo_id}) — Ignorando busca de arquivo.") - return None - - id6 = f"{arquivo_id_int:06d}" - ddd = _calcular_pasta(arquivo_id_int) - base_path = Path(pasta_origem) - - # ----------------------------------------------------------- - # REGISTRO CIVIL - # ----------------------------------------------------------- - if natureza in PREFIXOS_RC: - prefixos = PREFIXOS_RC[natureza] - pasta_ddd = base_path / ddd - - if not _exists_safe(pasta_ddd, verbose): - return None - - for nome in _nomes_possiveis(prefixos, id6): - caminho_path = pasta_ddd / nome - - if _exists_safe(caminho_path, verbose) and can_open_file( - caminho_path, verbose - ): - if verbose: - ok( - f"[RC/{natureza.upper()}] Arquivo encontrado e acessível: {caminho_path}" - ) - return _montar_retorno(caminho_path, "CERTIDAO") - - if verbose: - fail( - f"[RC/{natureza.upper()}] Nenhum arquivo acessível para ID {arquivo_id_int}" - ) - return None - - # ----------------------------------------------------------- - # PROTESTO - # ----------------------------------------------------------- - if natureza == "protesto": - sufixos_protesto = ("", "I") - prefixos = ("PRO_",) - - for subpasta in ("", "Retirados"): - pasta = base_path / ddd if not subpasta else base_path / subpasta / ddd - - if not _exists_safe(pasta, verbose): - continue - - for nome in _nomes_possiveis(prefixos, id6, sufixos_protesto): - caminho_path = pasta / nome - - if _exists_safe(caminho_path, verbose) and can_open_file( - caminho_path, verbose - ): - if verbose: - ok(f"[PROTESTO] Arquivo encontrado e acessível: {caminho_path}") - return _montar_retorno(caminho_path, "OUTROS") - - if verbose: - fail(f"[PROTESTO] Nenhum arquivo acessível para ID {arquivo_id_int}") - return None - - # ----------------------------------------------------------- - # RCPJ / RTD - # ----------------------------------------------------------- - if registro in ("RCPJ", "RTD"): - pasta_ddd = base_path / ddd - if not _exists_safe(pasta_ddd, verbose): - return None - - prefixo_base = f"{registro}_{(livro or 'A')}_" - sufixo = ( - registro_anterior - if (registro == "RCPJ" and registro_anterior in ("N", "S", "U")) - else "" - ) - - for nome in _nomes_possiveis((prefixo_base,), id6, (sufixo,)): - caminho_path = pasta_ddd / nome - - if _exists_safe(caminho_path, verbose) and can_open_file( - caminho_path, verbose - ): - tipo_doc = "ESCRITURA" if registro == "RCPJ" else "OUTROS" - if verbose: - ok(f"[{registro}] Arquivo encontrado e acessível: {caminho_path}") - return _montar_retorno(caminho_path, tipo_doc) - - if verbose: - fail(f"[{registro}] Nenhum arquivo acessível para ID {arquivo_id_int}") - return None - - # ----------------------------------------------------------- - # PADRÕES / REGISTRO IMÓVEIS - # ----------------------------------------------------------- - tipos = list(tipos_permitidos) if tipos_permitidos else list(TIPOS_PADRAO.keys()) - - for tipo in tipos: - info_tipo = TIPOS_PADRAO.get(tipo) - if not info_tipo: - continue - - tipo_doc = info_tipo["tipo_documento"] - - # REGISTRO DE IMÓVEIS - if tipo == "RegistroImoveis": - for ri_dir in (p for p in base_path.glob("R_*") if p.is_dir()): - for nome in _nomes_possiveis((info_tipo["prefixo"],), id6): - for achado in ri_dir.rglob(nome): - - if _exists_safe(achado, verbose) and can_open_file( - achado, verbose - ): - if verbose: - ok(f"[RI] Arquivo encontrado e acessível: {achado}") - return _montar_retorno(achado, tipo_doc) - - # TIPOS NORMAIS - base_tipo = info_tipo["base"] - pasta_tipo = base_path / base_tipo if base_tipo else base_path - pasta_ddd = pasta_tipo / ddd - - if not _exists_safe(pasta_ddd, verbose): - continue - - for nome in _nomes_possiveis((info_tipo["prefixo"],), id6): - caminho_path = pasta_ddd / nome - - if _exists_safe(caminho_path, verbose) and can_open_file( - caminho_path, verbose - ): - if verbose: - ok(f"Arquivo encontrado e acessível ({tipo}): {caminho_path}") - return _montar_retorno(caminho_path, tipo_doc) - - if verbose: - fail(f"Nenhum arquivo acessível para ID {arquivo_id_int} em {pasta_origem}") - return None diff --git a/AjustaFundos/actions/file/save_to_disk.py b/AjustaFundos/actions/file/save_to_disk.py deleted file mode 100644 index 8828d43..0000000 --- a/AjustaFundos/actions/file/save_to_disk.py +++ /dev/null @@ -1,101 +0,0 @@ -import json -import traceback -from datetime import datetime, date -from decimal import Decimal -from types import SimpleNamespace -from pathlib import Path -from typing import Any, Optional, Literal, Union -from pydantic import BaseModel - - -def save_to_disk( - data: Union[str, bytes, dict, list, Any], - file_path: str, - as_json: Optional[bool] = None, - encoding: str = "utf-8", - indent: int = 4, - add_timestamp: bool = False, - mode: Literal["overwrite", "append"] = "overwrite", -) -> dict: - """ - Salva dados em disco local de forma segura, com tratamento automático - para objetos não serializáveis (ex.: SimpleNamespace, Decimal, datetime, BaseModel). - """ - - def convert(obj: Any): - """Converte qualquer objeto para formato serializável em JSON.""" - if obj is None: - return None - if isinstance(obj, (str, int, float, bool)): - return obj - if isinstance(obj, bytes): - return obj.decode("utf-8", errors="ignore") - if isinstance(obj, Decimal): - return float(obj) - if isinstance(obj, (datetime, date)): - return obj.isoformat() - if isinstance(obj, SimpleNamespace): - return {k: convert(v) for k, v in vars(obj).items()} - if isinstance(obj, BaseModel): - return obj.model_dump() - if isinstance(obj, list): - return [convert(i) for i in obj] - if isinstance(obj, dict): - return {k: convert(v) for k, v in obj.items()} - # fallback final — stringifica o objeto - return str(obj) - - try: - path = Path(file_path) - - # Garante que o diretório existe - path.parent.mkdir(parents=True, exist_ok=True) - - # Adiciona timestamp ao nome se necessário - if add_timestamp: - timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") - stem = path.stem - suffix = path.suffix or ".json" - path = path.with_name(f"{stem}_{timestamp}{suffix}") - - # Detecta automaticamente se deve salvar como JSON - if as_json is None: - as_json = isinstance(data, (dict, list, SimpleNamespace, BaseModel)) - - write_mode = ( - "wb" if isinstance(data, bytes) else "a" if mode == "append" else "w" - ) - - if isinstance(data, bytes): - with open(path, write_mode) as f: - f.write(data) - elif as_json: - # Converte antes de salvar - safe_data = convert(data) - with open(path, write_mode, encoding=encoding) as f: - json.dump(safe_data, f, ensure_ascii=False, indent=indent) - else: - if not isinstance(data, str): - data = str(data) - with open(path, write_mode, encoding=encoding) as f: - f.write(data) - - file_size = path.stat().st_size if path.exists() else 0 - print(f"[OK] Arquivo salvo: {path} ({file_size} bytes)") - - return { - "success": True, - "path": str(path.resolve()), - "size": file_size, - "error": None, - } - - except Exception as e: - error_message = f"[ERRO] Falha ao salvar arquivo '{file_path}': {e}\n{traceback.format_exc()}" - print(error_message) - return { - "success": False, - "path": str(file_path), - "size": 0, - "error": str(e), - } diff --git a/AjustaFundos/actions/file/tif_to_pdf_converter.py b/AjustaFundos/actions/file/tif_to_pdf_converter.py deleted file mode 100644 index c6f5109..0000000 --- a/AjustaFundos/actions/file/tif_to_pdf_converter.py +++ /dev/null @@ -1,218 +0,0 @@ -from PIL import Image, UnidentifiedImageError -from pathlib import Path -from pypdf import PdfReader, PdfWriter -from reportlab.pdfgen import canvas -from io import BytesIO -from pypdf.constants import UserAccessPermissions -import base64 -from typing import Optional -from actions.ui.ui import info, ok, fail, status, progress - - -# Alias para manter compatibilidade e usar "error" na interface -def error(message: str): - fail(message) - - -class TifToPdfConverter: - """ - Converte um arquivo TIFF/SPD específico em PDF protegido e confidencial. - Totalmente em memória, com marca d'água e feedback visual via UI. - """ - - def __init__( - self, input_file: str, output_folder: Optional[str] = "storage/output" - ): - self.input_file = Path(input_file) - if not self.input_file.exists(): - raise FileNotFoundError(f"Arquivo não encontrado: {self.input_file}") - - # Pasta de saída padrão - self.output_folder = Path(output_folder) - self.output_folder.mkdir(parents=True, exist_ok=True) - - self.watermark_text = "DISPONÍVEL APENAS PARA ATIVIDADE CORRECIONAL ONLINE" - self.confidential_metadata = { - "/Title": "Documento Confidencial", - "/Author": "Sistema MirrorSYNC", - "/Subject": "Documento protegido", - "/Keywords": "Confidencial, Corregedoria, MirrorSYNC, Orius", - "/Producer": "Orius Tecnologia", - "/Creator": "MirrorSYNC Automação", - } - - # ========================================================= - # Helper 1 — Converte imagem em PDF (BytesIO) - # ========================================================= - def _convert_image_to_pdf(self) -> Optional[BytesIO]: - try: - with Image.open(self.input_file) as img: - frames = [] - - # Converte todas as páginas do TIFF para RGB - for frame in range(getattr(img, "n_frames", 1)): - img.seek(frame) - frame_rgb = img.convert("RGB") - frames.append(frame_rgb.copy()) - - if not frames: - info(f"Nenhuma página encontrada em {self.input_file}") - return None - - # Buffer em memória - buffer = BytesIO() - - # Salva todas as páginas como um único PDF - frames[0].save( - buffer, - format="PDF", - resolution=150, - save_all=True, - append_images=frames[1:], - quality=80, - optimize=True, - ) - buffer.seek(0) - - ok( - f"Imagem convertida para PDF em memória " - f"({len(frames)} página(s))." - ) - return buffer - - except UnidentifiedImageError: - error(f"Arquivo não reconhecido como imagem: {self.input_file}") - except Exception as e: - error(f"Erro ao converter {self.input_file}: {e}") - return None - - # ========================================================= - # Helper 2 — Gera PDF de marca d’água - # ========================================================= - def _create_watermark_pdf(self, page_width: float, page_height: float) -> BytesIO: - buffer = BytesIO() - c = canvas.Canvas(buffer, pagesize=(page_width, page_height)) - c.saveState() - - # Fonte adaptativa (limites 24..72) - base_font = max(24, min(72, max(page_width, page_height) * 0.04)) - c.setFont("Helvetica-Bold", base_font) - - # Cor vermelha com transparência (~30%) - try: - c.setFillColorRGB(1, 0, 0) # vermelho - c.setFillAlpha(0.3) - except Exception: - # Fallback sem alpha (ainda vermelho) - c.setFillColorRGB(1, 0, 0) - - # Centro e rotação para deixar na diagonal - x_center = page_width / 2.0 - y_center = page_height / 2.0 - c.translate(x_center, y_center) - c.rotate(45) # ângulo da marca d'água (diagonal) - - # Linhas igualmente espaçadas ao longo do eixo Y rotacionado - span = max(page_width, page_height) * 0.4 - y_positions = [-span, -span * 0.5, 0, span * 0.5, span] - - for y in y_positions: - c.drawCentredString(0, y, self.watermark_text) - - c.restoreState() - c.save() - buffer.seek(0) - return buffer - - # ========================================================= - # Helper 3 — Aplica marca d'água e confidencialidade - # ========================================================= - def _apply_watermark_and_security(self, pdf_buffer: BytesIO) -> BytesIO: - reader = PdfReader(pdf_buffer) - writer = PdfWriter() - - for page in reader.pages: - width = float(page.mediabox.width) - height = float(page.mediabox.height) - watermark_stream = self._create_watermark_pdf(width, height) - watermark_pdf = PdfReader(watermark_stream) - watermark_page = watermark_pdf.pages[0] - page.merge_page(watermark_page) - writer.add_page(page) - - # Aplica metadados confidenciais - writer.add_metadata(self.confidential_metadata) - - # Bloqueia ações do usuário - block_permissions = ( - UserAccessPermissions.PRINT - | UserAccessPermissions.MODIFY - | UserAccessPermissions.EXTRACT - | UserAccessPermissions.ASSEMBLE_DOC - | UserAccessPermissions.PRINT_TO_REPRESENTATION - ) - writer.encrypt( - user_password="", - owner_password="correcional", - permissions_flag=int(block_permissions), - ) - - output_buffer = BytesIO() - writer.write(output_buffer) - output_buffer.seek(0) - ok("Marca d’água e proteção aplicadas em memória.") - return output_buffer - - # ========================================================= - # Helper 4 — Converte PDF final para Base64 - # ========================================================= - def _to_base64(self, pdf_buffer: BytesIO) -> str: - b64 = base64.b64encode(pdf_buffer.getvalue()).decode("ascii") - ok("Arquivo convertido para Base64.") - return b64 - - # ========================================================= - # Método principal — Processamento completo - # ========================================================= - def convert(self, return_base64: bool = False) -> Optional[str]: - """ - Executa a conversão e retorna: - - Base64 (string), se return_base64=True - - Caminho do arquivo PDF salvo em disco, se return_base64=False - """ - - info(f"📄 Iniciando conversão de: {self.input_file.name}") - - # Barra de progresso única para todo o fluxo - with progress(f"Processando {self.input_file.name}...", total=3) as step: - - # 1) Converter imagem em PDF - with status("Convertendo imagem para PDF..."): - pdf_buffer = self._convert_image_to_pdf() - step() - - if not pdf_buffer: - error("Falha na conversão da imagem. Processo interrompido.") - return None - - # 2) Aplicar marca d’água e segurança - with status("Aplicando marca d’água e proteção..."): - protected_buffer = self._apply_watermark_and_security(pdf_buffer) - step() - - # 3) Gerar Base64 ou salvar em disco - if return_base64: - with status("Gerando conteúdo Base64..."): - result = self._to_base64(protected_buffer) - ok("Conversão concluída com sucesso (Base64 gerado).") - step() - return result - - with status("Salvando arquivo PDF em disco..."): - output_path = self.output_folder / f"{self.input_file.stem}.pdf" - with open(output_path, "wb") as f: - f.write(protected_buffer.getvalue()) - ok(f"Arquivo PDF salvo em: {output_path}") - step() - - return str(output_path) diff --git a/AjustaFundos/actions/firebird/parse_firebird_path.py b/AjustaFundos/actions/firebird/parse_firebird_path.py deleted file mode 100644 index d574006..0000000 --- a/AjustaFundos/actions/firebird/parse_firebird_path.py +++ /dev/null @@ -1,80 +0,0 @@ -import re -from typing import Any, Dict, Union - - -class ParseFirebirdPath: - - DEFAULT_HOST = "localhost" - DEFAULT_PORT = 3050 - - @classmethod - def execute(cls, value: Union[str, Dict[str, Any]]) -> Dict[str, Any]: - - # ------------------------------------------- - # Se for dicionário, já padroniza - # ------------------------------------------- - if isinstance(value, dict): - return { - "host": value.get("host", cls.DEFAULT_HOST), - "port": int(value.get("port", cls.DEFAULT_PORT)), - "path": value.get("path"), - } - - if not isinstance(value, str): - raise TypeError("BaseDados deve ser string ou dict.") - - raw = value.strip().strip('"').strip("'") - - if not raw: - raise ValueError("BaseDados está vazio.") - - # ------------------------------------------- - # 1) host/port:path - # ------------------------------------------- - m = re.match(r"^(?P[^:/]+)\/(?P\d+)\:(?P.+)$", raw) - if m: - return { - "host": m.group("host"), - "port": int(m.group("port")), - "path": m.group("path").strip(), - } - - # ------------------------------------------- - # 2) host:path (ex: 127.0.0.1:D:\Banco.fdb) - # ------------------------------------------- - m = re.match(r"^(?P[^:\/]+)\:(?P[A-Za-z]:\\.+)$", raw) - if m: - return { - "host": m.group("host"), - "port": cls.DEFAULT_PORT, - "path": m.group("path"), - } - - # ------------------------------------------- - # 3) Caminho local absoluto (D:\, E:\) - # ------------------------------------------- - if re.match(r"^[A-Za-z]:\\", raw): - return { - "host": cls.DEFAULT_HOST, - "port": cls.DEFAULT_PORT, - "path": raw, - } - - # ------------------------------------------- - # 4) UNC path (\\servidor\pasta\arquivo) - # ------------------------------------------- - if raw.startswith("\\\\"): - return { - "host": cls.DEFAULT_HOST, - "port": cls.DEFAULT_PORT, - "path": raw, - } - - # ------------------------------------------- - # 5) Alias puro — retorna padrão - # ------------------------------------------- - return { - "host": cls.DEFAULT_HOST, - "port": cls.DEFAULT_PORT, - "path": raw, - } diff --git a/AjustaFundos/actions/hexCipher/hex_chipher.py b/AjustaFundos/actions/hexCipher/hex_chipher.py deleted file mode 100644 index 40642a1..0000000 --- a/AjustaFundos/actions/hexCipher/hex_chipher.py +++ /dev/null @@ -1,124 +0,0 @@ -class HexCipher: - """ - Um cifrador simples e reversível baseado em: - - XOR com chave - - Inversão de texto - - Representação em hexadecimal - - Inspirado no componente original Delphi TEvCriptografa. - """ - - # ------------------------------------------------------------------------- - # Construtor - # ------------------------------------------------------------------------- - def __init__(self, key: str = "123", ignore_fields: list[str] | None = None): - """Inicializa a classe com a chave fornecida.""" - self._key = key - # nomes de campos que NÃO devem ser descriptografados (sempre minúsculos) - self._ignore_fields = ( - {f.lower() for f in ignore_fields} if ignore_fields else set() - ) - - # ------------------------------------------------------------------------- - # Métodos públicos principais - # ------------------------------------------------------------------------- - - def encrypt(self, text: str) -> str: - """ - Recebe um texto puro e retorna sua versão criptografada em hexadecimal. - """ - binary_cipher = self._text_to_binary_cipher(text) - hex_cipher = "".join(self._decimal_to_hex(ord(c)) for c in binary_cipher) - return hex_cipher - - def decrypt(self, hex_string: str) -> str: - """ - Recebe um texto criptografado em hexadecimal e retorna o texto puro. - """ - chars = [] - for i in range(0, len(hex_string), 2): - hex_pair = hex_string[i : i + 2] - chars.append(chr(self._hex_to_decimal(hex_pair))) - - binary_str = "".join(chars) - return self._binary_to_text(binary_str) - - def decrypt_safe(self, value: str, field: str | None = None) -> str: - """ - Descriptografa com segurança: - - Se o campo estiver em _ignore_fields, retorna o valor original. - - Se o valor não parecer HEX válido, retorna o valor original. - - Em qualquer erro na descriptografia, retorna o valor original. - """ - # 1) Campo explicitamente ignorado - if field and field.lower() in self._ignore_fields: - return value - - # 2) Valor vazio / None - if not value: - return value - - # 3) Verifica se é HEX puro (somente 0-9 A-F) e tamanho par - import re - - if re.fullmatch(r"[0-9A-Fa-f]+", value) is None: - return value - - if len(value) % 2 != 0: - return value - - # 4) Tenta descriptografar - try: - return self.decrypt(value) - except Exception: - return value - - # ------------------------------------------------------------------------- - # Funções internas de criptografia/descriptografia - # ------------------------------------------------------------------------- - - def _text_to_binary_cipher(self, text: str) -> str: - """ - Criptografa um texto aplicando: - 1. Inversão de caracteres. - 2. Operação XOR entre cada caractere e um valor derivado da chave. - """ - text = self._reverse(text) - result = [] - - for position, char in enumerate(text, start=1): - key_char = self._key[position % len(self._key)] - key_value = ord(key_char) + position - result.append(chr(ord(char) ^ key_value)) - - return "".join(result) - - def _binary_to_text(self, cipher_text: str) -> str: - """ - Descriptografa um texto binário cifrado por XOR. - O processo é simétrico: aplica o mesmo XOR e inverte novamente. - """ - result = [] - - for position, char in enumerate(cipher_text, start=1): - key_char = self._key[position % len(self._key)] - key_value = ord(key_char) + position - result.append(chr(ord(char) ^ key_value)) - - return self._reverse("".join(result)) - - # ------------------------------------------------------------------------- - # Funções auxiliares - # ------------------------------------------------------------------------- - - def _reverse(self, text: str) -> str: - """Inverte a ordem dos caracteres de uma string.""" - return text[::-1] - - def _decimal_to_hex(self, number: int) -> str: - """Converte um número decimal (byte) em uma string hexadecimal de 2 dígitos.""" - return f"{number:02X}" - - def _hex_to_decimal(self, hex_str: str) -> int: - """Converte uma string hexadecimal de 2 dígitos em seu valor decimal (byte).""" - return int(hex_str, 16) diff --git a/AjustaFundos/actions/jwt/create_token.py b/AjustaFundos/actions/jwt/create_token.py deleted file mode 100644 index 1b7c3fd..0000000 --- a/AjustaFundos/actions/jwt/create_token.py +++ /dev/null @@ -1,32 +0,0 @@ -from datetime import datetime, timedelta -from jose import jwt -from pytz import timezone - -from actions.config.config_json import ConfigJson - - -class CreateToken: - def __init__(self): - # Busca as configurações da aplicação - self.config = ConfigJson.get("app.json") - - # Cria o timedelta com base na config - self.access_token_expire = timedelta( - minutes=self.config.jwt.expire.minute, - hours=self.config.jwt.expire.hours, - days=self.config.jwt.expire.days, - ) - - def execute(self, tipo_token: str, data: str) -> str: - - sp = timezone("America/Sao_Paulo") - agora = datetime.now(tz=sp) - expira = agora + self.access_token_expire - - # Define os dados do token - payload = {"type": tipo_token, "exp": expira, "iat": agora, "data": str(data)} - - # Retorna os dados codificados - return jwt.encode( - payload, self.config.jwt.token, algorithm=self.config.jwt.algorithm - ) diff --git a/AjustaFundos/actions/jwt/get_current_user.py b/AjustaFundos/actions/jwt/get_current_user.py deleted file mode 100644 index 7bedf85..0000000 --- a/AjustaFundos/actions/jwt/get_current_user.py +++ /dev/null @@ -1,24 +0,0 @@ -from fastapi import Depends, HTTPException, status -from fastapi.security import OAuth2PasswordBearer - -from actions.jwt.verify_token import VerifyToken # A classe que criamos anteriormente - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") # Apenas requerido pelo FastAPI - -def get_current_user(token: str = Depends(oauth2_scheme)): - - # Ação que válida o tokne - verify_token = VerifyToken() - # Obtem o resultado da validação - result = verify_token.execute(token) - - # Verifica se a resposta é diferente de inválida - if result['status'] != 'valid': - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail=result.get('message', 'Token inválido ou expirado'), - headers={"WWW-Authenticate": "Bearer"}, - ) - - # Retorna apenas os dados do token - return result['payload'] diff --git a/AjustaFundos/actions/jwt/verify_token.py b/AjustaFundos/actions/jwt/verify_token.py deleted file mode 100644 index 4eedcca..0000000 --- a/AjustaFundos/actions/jwt/verify_token.py +++ /dev/null @@ -1,55 +0,0 @@ -from jose import jwt, JWTError, ExpiredSignatureError - -from actions.config.config_json import ConfigJson - - -class VerifyToken: - def __init__(self): - # Carrega configurações - self.config = ConfigJson.get('app.json') - - def execute(self, token: str, expected_type: str = 'access-token') -> dict: - try: - # Decodifica o token - payload = jwt.decode( - token, - self.config.jwt.token, - algorithms=[self.config.jwt.algorithm] - ) - - # Valida expiração - exp_timestamp = payload.get("exp") - if exp_timestamp is None: - raise ValueError("O token não possui data de expiração.") - - # Verifica o tipo de token - token_type = payload.get("type") - if token_type != expected_type: - raise ValueError("Tipo de token inválido.") - - # Verificação opcional: validar campo "data" - if "data" not in payload: - raise ValueError("Token malformado: campo 'data' ausente.") - - return { - "status": "valid", - "payload": payload - } - - except ExpiredSignatureError: - return { - "status": "expired", - "message": "O token expirou." - } - - except JWTError as e: - return { - "status": "invalid", - "message": f"Token inválido: {str(e)}" - } - - except Exception as e: - return { - "status": "error", - "message": f"Erro na validação do token: {str(e)}" - } \ No newline at end of file diff --git a/AjustaFundos/actions/log/log.py b/AjustaFundos/actions/log/log.py deleted file mode 100644 index 3fe4298..0000000 --- a/AjustaFundos/actions/log/log.py +++ /dev/null @@ -1,32 +0,0 @@ -import json -import os - - -class Log: - - def register(self, data, caminho_arquivo='storage/temp.json'): - try: - # Garante que a pasta existe - os.makedirs(os.path.dirname(caminho_arquivo), exist_ok=True) - - # Lê dados existentes (ou cria nova lista) - if os.path.exists(caminho_arquivo): - with open(caminho_arquivo, 'r', encoding='utf-8') as arquivo: - try: - dados_existentes = json.load(arquivo) - if not isinstance(dados_existentes, list): - dados_existentes = [] - except json.JSONDecodeError: - dados_existentes = [] - else: - dados_existentes = [] - - # Adiciona novo dado - dados_existentes.append(data) - - # Salva novamente no arquivo com indentação - with open(caminho_arquivo, 'w', encoding='utf-8') as arquivo: - json.dump(dados_existentes, arquivo, indent=4, ensure_ascii=False) - - except Exception as e: - print(f"❌ Erro ao salvar o dado: {e}") \ No newline at end of file diff --git a/AjustaFundos/actions/string/file_name_generator.py b/AjustaFundos/actions/string/file_name_generator.py deleted file mode 100644 index 8c71cf8..0000000 --- a/AjustaFundos/actions/string/file_name_generator.py +++ /dev/null @@ -1,59 +0,0 @@ -import re -import unicodedata -from datetime import datetime -from typing import Optional - - -class FileNameGenerator: - """ - Gera nomes de arquivos seguros e consistentes a partir de uma string de entrada. - - Remove acentos, espaços e caracteres inválidos - - Pode adicionar timestamp e extensão - - Não grava em disco, apenas retorna a string final - """ - - @staticmethod - def _sanitize(text: str) -> str: - """Remove acentos, espaços e símbolos inválidos do nome do arquivo.""" - text = ( - unicodedata.normalize("NFKD", text) - .encode("ASCII", "ignore") - .decode("ASCII") - ) - text = re.sub(r"[^a-zA-Z0-9_-]+", "_", text) - text = re.sub(r"_+", "_", text).strip("_") - return text.lower() - - @classmethod - def generate( - cls, - base_name: str, - extension: str = ".txt", - include_timestamp: bool = False, - counter: Optional[int] = None, - ) -> str: - """ - Retorna um nome de arquivo limpo, como string. - - :param base_name: Texto base (ex: título, nome, descrição) - :param extension: Extensão desejada (ex: .pdf, .json) - :param include_timestamp: Se True, adiciona timestamp no nome - :param counter: Número opcional para diferenciar nomes repetidos - :return: String do nome final do arquivo - """ - if not base_name: - raise ValueError("O nome base não pode estar vazio.") - - safe_name = cls._sanitize(base_name) - - if include_timestamp: - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - safe_name = f"{safe_name}_{timestamp}" - - if counter is not None: - safe_name = f"{safe_name}_{counter}" - - if not extension.startswith("."): - extension = f".{extension}" - - return f"{safe_name}{extension}" diff --git a/AjustaFundos/actions/string/string.py b/AjustaFundos/actions/string/string.py deleted file mode 100644 index 2be8da4..0000000 --- a/AjustaFundos/actions/string/string.py +++ /dev/null @@ -1,141 +0,0 @@ -# Importa a biblioteca nativa 'zlib' usada para descompressão de dados binários. -import base64 -import zlib - -# Importa a função 'rtf_to_text' da biblioteca 'striprtf', -# responsável por converter documentos RTF em texto plano legível. -from striprtf.striprtf import rtf_to_text - - -# Define uma classe utilitária chamada 'String', contendo apenas métodos estáticos. -# Essa abordagem permite o uso direto sem necessidade de instanciar a classe. -class String: - @staticmethod - def decompress(vf_string): - """ - Descomprime e decodifica texto de origem WPTools/Firebird. - - Finalidade: - Converter o conteúdo de campos BLOB ou strings compactadas (como no Delphi) - em texto legível, detectando automaticamente se o conteúdo está: - - Compactado com zlib - - Codificado em ISO-8859-1 (padrão ANSI) - - Representado como bytes puros - """ - # Verifica se o valor recebido é nulo, vazio ou None. - # Se for, retorna string vazia para evitar erros de processamento. - if not vf_string: - return "" - - # Caso seja um objeto tipo stream (ex: campo BLOB do Firebird) - # Campos BLOB geralmente possuem o método `.read()` para leitura de bytes. - if hasattr(vf_string, "read"): - vf_string = vf_string.read() # Lê o conteúdo completo do stream - - # Garante que o valor trabalhado é uma sequência de bytes (não string) - # Se o dado já for texto (str), converte para bytes em codificação Latin-1, - # que é compatível com ISO-8859-1 usado por sistemas Delphi/Firebird. - if isinstance(vf_string, str): - vf_bytes = vf_string.encode("latin1", errors="ignore") - else: - vf_bytes = vf_string # Já está em bytes, então apenas reaproveita - - # Detecta se o conteúdo foi compactado com zlib. - # A assinatura padrão do formato zlib começa com bytes: 0x78 0x9C ou 0x78 0xDA. - is_zlib = ( - len(vf_bytes) > 2 and vf_bytes[0] == 0x78 and vf_bytes[1] in (0x9C, 0xDA) - ) - - # Se a detecção confirmar que o conteúdo é zlib, tenta descompactar. - if is_zlib: - try: - # Descompacta os bytes e decodifica o texto usando ISO-8859-1 (ANSI), - # que preserva corretamente acentuação e caracteres especiais. - text = zlib.decompress(vf_bytes).decode("iso-8859-1", errors="ignore") - return text - except Exception: - # Caso falhe (por dados corrompidos ou não comprimidos de fato), - # o fluxo continua normalmente sem interromper a execução. - pass - - # Se não for zlib, tenta tratar o conteúdo como texto puro (não compactado) - try: - # Decodifica os bytes diretamente de ISO-8859-1 (padrão usado pelo Delphi) - return vf_bytes.decode("iso-8859-1", errors="ignore") - except Exception: - # Como fallback, converte para string bruta para evitar falhas. - return str(vf_string) - - # >>> NOVO MÉTODO <<< - @staticmethod - def compress(text, *, encoding: str = "iso-8859-1", as_base64: bool = True): - """ - Comprime texto/dados com zlib. - - Parâmetros: - text: str | bytes | stream (com .read()) - encoding: encoding usado quando 'text' for str (padrão: ISO-8859-1) - as_base64: se True, retorna string Base64 do conteúdo comprimido; - caso False, retorna bytes comprimidos. - - Retorno: - - bytes (zlib) quando as_base64=False - - str (Base64) quando as_base64=True - - Observações: - - Use o mesmo 'encoding' ao descomprimir para simetria. - - Ideal para armazenar em BLOB ou trafegar seguro (Base64). - """ - if text is None or text == "": - return "" if as_base64 else b"" - - # Se for stream (ex.: BLOB do Firebird) - if hasattr(text, "read"): - raw = text.read() - else: - raw = text - - # Garante bytes - if isinstance(raw, str): - raw_bytes = raw.encode(encoding, errors="ignore") - else: - raw_bytes = bytes(raw) - - # Comprime com zlib - comp = zlib.compress(raw_bytes) - - # Opcional: codifica em Base64 para transporte/JSON - if as_base64: - return base64.b64encode(comp).decode("ascii") - - return comp - - @staticmethod - def to_text(raw_text: str) -> str: - """ - Converte o conteúdo RTF em texto simples e retorna como string. - - Finalidade: - - Detectar automaticamente se o conteúdo está em formato RTF. - - Converter para texto plano usando a função 'rtf_to_text' (da striprtf). - - Retornar uma string limpa e pronta para ser usada em APIs, logs, etc. - """ - # Verifica se o texto recebido está vazio ou None — retorna vazio se sim. - if not raw_text: - return "" - - # Verifica se o texto começa com o cabeçalho padrão de arquivos RTF. - # Exemplo: "{\\rtf1\\ansi..." indica conteúdo em formato RTF. - if raw_text.strip().startswith("{\\rtf"): - try: - # Converte o RTF em texto simples, preservando acentuação e quebras de linha. - text = rtf_to_text(raw_text) - # Remove espaços em branco extras nas extremidades. - return text.strip() - except Exception: - # Se ocorrer erro na conversão (ex: RTF inválido), - # retorna o conteúdo original sem alterações. - return raw_text - - # Caso o texto não seja RTF, apenas remove espaços em branco extras e retorna. - return raw_text.strip() diff --git a/AjustaFundos/actions/system/exceptions.py b/AjustaFundos/actions/system/exceptions.py deleted file mode 100644 index ec151c9..0000000 --- a/AjustaFundos/actions/system/exceptions.py +++ /dev/null @@ -1,4 +0,0 @@ -# exceptions.py -class BusinessRuleException(Exception): - def __init__(self, message: str): - self.message = message \ No newline at end of file diff --git a/AjustaFundos/actions/system/handlers.py b/AjustaFundos/actions/system/handlers.py deleted file mode 100644 index 24e0300..0000000 --- a/AjustaFundos/actions/system/handlers.py +++ /dev/null @@ -1,85 +0,0 @@ -# handlers.py -import traceback - -from fastapi import Request -from fastapi.exceptions import RequestValidationError -from fastapi.responses import JSONResponse -from starlette.exceptions import HTTPException as StarletteHTTPException - -from actions.system.exceptions import BusinessRuleException -from actions.log.log import Log - - -def register_exception_handlers(app): - - def __init__ (self): - log = Log() - - @app.exception_handler(BusinessRuleException) - async def business_rule_exception_handler(request: Request, exc: BusinessRuleException): - - response = { - "status": "422", - "error": "Regra de negócio", - "detail": exc.message - } - - # Salva o log em disco - Log.register(response, 'storage/temp/business_rule_exception_handler.json') - - return JSONResponse( - status_code=422, - content=response - ) - - @app.exception_handler(StarletteHTTPException) - async def http_exception_handler(request: Request, exc: StarletteHTTPException): - response = { - "status": exc.status_code, - "error": "HTTP Error", - "detail": exc.detail - } - - # Salva o log em disco - Log.register(response, 'storage/temp/http_exception_handler.json') - - return JSONResponse( - status_code=exc.status_code, - content=response - ) - - @app.exception_handler(RequestValidationError) - async def validation_exception_handler(request: Request, exc: RequestValidationError): - - response = { - "status": 400, - "error": "Erro de validação", - "detail": exc.errors() - } - - # Salva o log em disco - Log.register(response, 'storage/temp/validation_exception_handler.json') - - return JSONResponse( - status_code=400, - content=response - ) - - @app.exception_handler(Exception) - async def global_exception_handler(request: Request, exc: Exception): - - response = { - "status": 500, - "error": "Erro Interno do Servidor", - "type": type(exc).__name__, - "message": str(exc), - "trace": traceback.format_exc() - } - - # Salva o log em disco - Log.register(response, 'storage/temp/validation_exception_handler.json') - - return JSONResponse( - status_code=500, - content=response - ) diff --git a/AjustaFundos/actions/ui/ui.py b/AjustaFundos/actions/ui/ui.py deleted file mode 100644 index 38c5694..0000000 --- a/AjustaFundos/actions/ui/ui.py +++ /dev/null @@ -1,203 +0,0 @@ -# ui.py -from contextlib import asynccontextmanager -from contextlib import contextmanager -from typing import Iterable, Mapping - -from rich.live import Live -from rich.console import Console -from rich.theme import Theme -from rich.panel import Panel -from rich.table import Table -from rich.text import Text -from rich.progress import ( - Progress, - SpinnerColumn, - BarColumn, - TextColumn, - TimeElapsedColumn, - TimeRemainingColumn, -) -from rich.markdown import Markdown -from rich.traceback import install -from rich.logging import RichHandler -import logging -import json - -# ───────────────────────────────────────────────────────────── -# Tema global (cores nomeadas para facilitar padronização) -# ───────────────────────────────────────────────────────────── -theme = Theme( - { - "accent": "bright_magenta", - "info": "cyan", - "success": "green", - "warning": "yellow", - "error": "bold red", - "muted": "grey62", - } -) - -# Console único para todo o sistema -console = Console(theme=theme) -install(show_locals=False) # Tracebacks bonitos - - -# ───────────────────────── -# BÁSICOS -# ───────────────────────── -def banner(titulo: str, subtitulo: str | None = None): - text = Text(titulo, style="bold accent") - if subtitulo: - text.append(f"\n{subtitulo}", style="muted") - console.print(Panel.fit(text, border_style="accent", padding=(1, 2))) - - -def rule(texto: str = ""): - console.rule(Text(texto, style="accent")) - - -def info(msg: str): - console.print(f"ℹ️ [info]{msg}[/]") - - -def ok(msg: str): - console.print(f"✅ [success]{msg}[/]") - - -def warn(msg: str): - console.print(f"⚠️ [warning]{msg}[/]") - - -def fail(msg: str): - console.print(f"❌ [error]{msg}[/]") - - -def md(markdown: str): - console.print(Markdown(markdown)) - - -def json_pretty(data): - try: - console.print_json(data=json.loads(data) if isinstance(data, str) else data) - except Exception: - console.print(data) - - -# ───────────────────────── -# TABELA RÁPIDA -# ───────────────────────── -def table(rows: Iterable[Mapping], title: str | None = None): - rows = list(rows) - if not rows: - warn("Tabela vazia.") - return - - t = Table(title=title, title_style="accent") - - for col in rows[0].keys(): - t.add_column(str(col), style="muted") - - for r in rows: - t.add_row(*[str(r[k]) for k in rows[0].keys()]) - - console.print(t) - - -# ───────────────────────── -# STATUS / SPINNER -# ───────────────────────── -@contextmanager -def status(msg: str): - with console.status(f"[info]{msg}[/]"): - yield - - -# ───────────────────────── -# BARRA DE PROGRESSO -# ───────────────────────── -@contextmanager -def progress(task_desc: str, total: int | None = None): - with Progress( - SpinnerColumn(), - TextColumn("[accent]{task.description}"), - BarColumn(), - TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), - TimeElapsedColumn(), - TimeRemainingColumn(), - transient=True, - console=console, - ) as p: - - task_id = p.add_task(task_desc, total=total) - yield lambda advance=1: p.update(task_id, advance=advance) - - -# ───────────────────────── -# LOGGING RICH -# ───────────────────────── -def setup_logging(level: int = logging.INFO): - logging.basicConfig( - level=level, - format="%(message)s", - handlers=[RichHandler(rich_tracebacks=True, console=console)], - ) - - -# ───────────────────────── -# FIREBIRD / DB HELPERS -# ───────────────────────── -def db_info(msg: str): - console.print(f"🗄️ [info][DB INFO][/info] {msg}") - - -def db_ok(msg: str): - console.print(f"🗄️ [success][DB OK][/success] {msg}") - - -def db_fail(msg: str): - console.print(f"🗄️ [error][DB ERROR][/error] {msg}") - - -def db_warning(msg: str): - console.print(f"🗄️ [warning][DB WARNING][/warning] {msg}") - - -def db_dsn(dsn: str): - # Mascara senha com segurança - try: - before_at = dsn.split("@")[0] - user = before_at.split("//")[1].split(":")[0] - masked = dsn.replace(user, "******") - except Exception: - masked = dsn # fallback - - console.print( - Panel( - Text(f"[accent]DSN de conexão[/accent]\n{masked}", style="muted"), - border_style="accent", - ) - ) - - -@asynccontextmanager -async def progress_manager(): - - # Criar progress com o console compartilhado - progress = Progress( - SpinnerColumn(), - TextColumn("[progress.description]{task.description}"), - BarColumn(), - TextColumn("{task.completed}/{task.total}"), - TimeElapsedColumn(), - expand=True, - console=console, # fundamental! - ) - - # Live controla a tela inteira - live = Live(progress, refresh_per_second=10, console=console, transient=False) - live.start() - - try: - yield progress - finally: - live.stop() diff --git a/AjustaFundos/database/firebird.py b/AjustaFundos/database/firebird.py deleted file mode 100644 index f49698a..0000000 --- a/AjustaFundos/database/firebird.py +++ /dev/null @@ -1,76 +0,0 @@ -from typing import Optional -from sqlalchemy import create_engine, text -from sqlalchemy.engine import Engine -from sqlalchemy.exc import DBAPIError, OperationalError -from firebird.driver.types import DatabaseError as FbDatabaseError - -from actions.config.config_ini import ConfigIni -from actions.firebird.parse_firebird_path import ParseFirebirdPath -from actions.hexCipher.hex_chipher import HexCipher -from actions.ui.ui import db_fail - - -class Firebird: - - _engine: Optional[Engine] = None - hex_cipher: Optional[HexCipher] = None - - @classmethod - def get_engine(cls) -> Engine: - - # Cria a instância de descriptografia apenas uma vez - if cls.hex_cipher is None: - cls.hex_cipher = HexCipher(key="Wallace&Gromitt") - - # Lê o arquivo INI com os parâmetros - database = ConfigIni.read("Config.ini") - - # ---------------------------------------------------------------------- - # Descriptografa o valor bruto do BaseDados ANTES do parser. - # Ex: "127.0.0.1/3050:S:\Bases\SANTARITA.FDB" - # ---------------------------------------------------------------------- - base_raw = cls.hex_cipher.decrypt(database["Geral"]["BaseDados"]) - - # Parser converte "host/port:path" → dict {host, port, path} - base_info = ParseFirebirdPath.execute(base_raw) - - # Descriptografa usuário e senha - user = cls.hex_cipher.decrypt(database["Geral"]["Usuario"]) - passwd = cls.hex_cipher.decrypt(database["Geral"]["Senha"]) - - # Charset da conexão - charset = "ISO8859_1" - - # Monta o DSN final no padrão aceito pelo firebird-driver - dsn = ( - f"firebird+firebird://{user}:{passwd}" - f"@{base_info['host']}:{base_info['port']}/{base_info['path']}" - ) - - # Cria a engine apenas uma vez (singleton) - if cls._engine is None: - try: - cls._engine = create_engine( - dsn, - connect_args={"charset": charset}, - pool_pre_ping=True, - pool_size=5, - max_overflow=10, - ) - - # Testa a conexão imediatamente para evitar erros silenciosos - with cls._engine.connect() as conn: - conn.execute(text("SELECT 1 FROM RDB$DATABASE")) - - except (OperationalError, DBAPIError, FbDatabaseError) as e: - db_fail("Erro ao conectar ao Firebird:") - db_fail(str(e)) - raise - - return cls._engine - - @classmethod - def dispose(cls): - if cls._engine: - cls._engine.dispose() - cls._engine = None diff --git a/AjustaFundos/fbclient.dll b/AjustaFundos/fbclient.dll deleted file mode 100644 index c0f2c12..0000000 Binary files a/AjustaFundos/fbclient.dll and /dev/null differ diff --git a/AjustaFundos/images/icon.ico b/AjustaFundos/images/icon.ico deleted file mode 100644 index e2b5ee5..0000000 Binary files a/AjustaFundos/images/icon.ico and /dev/null differ diff --git a/AjustaFundos/images/icon.png b/AjustaFundos/images/icon.png deleted file mode 100644 index 2232896..0000000 Binary files a/AjustaFundos/images/icon.png and /dev/null differ diff --git a/AjustaFundos/main.py b/AjustaFundos/main.py deleted file mode 100644 index eda0fed..0000000 --- a/AjustaFundos/main.py +++ /dev/null @@ -1,156 +0,0 @@ -import asyncio -import os -import platform -import sys -import traceback -from datetime import datetime -from pathlib import Path - -from firebird.driver import driver_config -from actions.ui.ui import ok, rule, warn -from packages.v1.manutencao.controller.manutencao_v_casamento_controller import ( - ManutencaoVCasamentoController, -) - -# ============================================================== -# Corrige BASE_DIR (funciona no .exe, --onefile e ambiente normal) -# ============================================================== - -if getattr(sys, "frozen", False): - BASE_DIR = Path(getattr(sys, "_MEIPASS", Path(sys.executable).parent)) -else: - BASE_DIR = Path(__file__).resolve().parent - -sys.path.insert(0, str(BASE_DIR)) - - -# ============================================================== -# Prepara pasta de logs (100% seguro) -# ============================================================== - - -def get_log_path() -> Path: - """Sempre retorna o caminho correto para logs + cria pasta storage.""" - storage_dir = BASE_DIR / "storage" - storage_dir.mkdir(parents=True, exist_ok=True) - - # arquivo de log diário - today = datetime.now().strftime("%Y-%m-%d") - return storage_dir / f"errors_{today}.log" - - -# ============================================================== -# Logging robusto para qualquer exceção -# ============================================================== - - -def registrar_erro(e: Exception, contexto: str = ""): - """Grava traceback completo em storage/errors_YYYY-MM-DD.log.""" - log_path = get_log_path() - - try: - with open(log_path, "a", encoding="utf-8") as f: - f.write("\n" + "=" * 80 + "\n") - f.write(f"DATA: {datetime.now().isoformat()}\n") - if contexto: - f.write(f"CONTEXTO: {contexto}\n") - f.write("ERRO:\n") - traceback.print_exc(file=f) - f.write("=" * 80 + "\n") - - warn(f"⚠️ Erro registrado em {log_path}") - - except Exception as log_error: - print("❌ Falha ao escrever no arquivo de log:", log_error) - print("Erro original:", e) - input("\nPressione ENTER para sair...") - sys.exit(1) - - -# ============================================================== -# Configuração do Firebird -# ============================================================== - - -def configurar_firebird(): - try: - system = platform.system() - - if system == "Windows": - fb_client_local = BASE_DIR / "fbclient.dll" - if fb_client_local.exists(): - os.add_dll_directory(str(BASE_DIR)) - driver_config.fb_client_library.value = str(fb_client_local) - ok(f"🔗 Firebird DLL carregada: {fb_client_local}") - else: - raise FileNotFoundError( - f"fbclient.dll não encontrada em {fb_client_local}" - ) - - elif system == "Linux": - possible_paths = [ - "/usr/lib/x86_64-linux-gnu/firebird/4.0/lib/libfbclient.so.2", - "/usr/lib/x86_64-linux-gnu/libfbclient.so.2", - "/usr/lib/x86_64-linux-gnu/libfbclient.so.4.0.5", - str(BASE_DIR / "libfbclient.so"), - ] - - for path in possible_paths: - if os.path.exists(path): - driver_config.fb_client_library.value = path - ok(f"🔗 Firebird client carregado: {path}") - break - else: - raise FileNotFoundError( - "❌ libfbclient.so não encontrada. " - "Instale o firebird-client no Linux." - ) - - else: - warn(f"⚠️ Sistema operacional não suportado: {system}") - - except Exception as e: - registrar_erro(e, contexto="CONFIGURAÇÃO FIREBIRD") - raise - - -# ============================================================== -# Execução principal -# ============================================================== - - -async def main(): - manutencao_v_casamento_controller = ManutencaoVCasamentoController() - response = manutencao_v_casamento_controller.VincularNoivosAtosAntigos() - print(response) - - -# ============================================================== -# Entry point -# ============================================================== - -if __name__ == "__main__": - - try: - configurar_firebird() - except Exception: - traceback.print_exc() - input("\nErro ao configurar o Firebird. Pressione ENTER para sair...") - sys.exit(1) - - # Corrige event loop no Windows - if platform.system() == "Windows": - try: - asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) - except Exception: - pass - - try: - asyncio.run(main()) - input("\nProcesso concluído. Pressione ENTER para sair...") - - except Exception as e: - registrar_erro(e, contexto="EXECUÇÃO PRINCIPAL") - traceback.print_exc() - input("\nOcorreu um erro. Pressione ENTER para sair...") - sys.exit(1) diff --git a/AjustaFundos/packages/__init__.py b/AjustaFundos/packages/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/AjustaFundos/packages/v1/api/Mattermost/actions/api_action.py b/AjustaFundos/packages/v1/api/Mattermost/actions/api_action.py deleted file mode 100644 index 1cb2d53..0000000 --- a/AjustaFundos/packages/v1/api/Mattermost/actions/api_action.py +++ /dev/null @@ -1,198 +0,0 @@ -import json -import re -from types import SimpleNamespace -from actions.file.file_name_generator import FileNameGenerator -from actions.file.json_file_saver import JsonFileSaver -import httpx -from actions.data.dict_to_obj import DictToObj -from actions.ui.ui import fail, ok, rule - - -class ApiAction: - - def __init__(self) -> None: - - self.file_name_generator = FileNameGenerator() - - # Classe para obter as variaveis de ambiente - mirror_sync_env = SimpleNamespace( - url="https://mattermost.oriustecnologia.com/api/v4/", - timeout=10, - token="uzszwh6c7pbc8xyt1d1skope8y", - ) - - # Obtem as variaveis de ambiente em formato de objeto - self.mirror_sync_env = mirror_sync_env - - pass - - def sanitize_unicode(self, data): - """ - Remove caracteres inválidos (surrogates) de strings dentro de estruturas complexas. - """ - if isinstance(data, str): - # Remove caracteres Unicode no intervalo D800–DFFF (não permitidos em UTF-8) - return re.sub(r"[\ud800-\udfff]", "", data) - elif isinstance(data, list): - return [self.sanitize_unicode(i) for i in data] - elif isinstance(data, dict): - return {k: self.sanitize_unicode(v) for k, v in data.items()} - return data - - # Cria os Cabeçalhos de envio - def _headers(self, data): - - headers = { - "Accept": getattr(data, "accept", "application/json"), - "Content-Type": getattr(data, "content_type", "application/json"), - } - - token = getattr(data, "token", None) - - if token: - headers["Authorization"] = f"Bearer {token}" - - return headers - - # Trata os dados da respsota - async def _response(self, response: httpx.Response, data): - - # Tenta JSON; se falhar, retorna texto bruto - try: - - # Gerador de arquivo JSON - json_file_saver = JsonFileSaver() - - # Obtem o código de requisição - status = response.status_code - - # Converter o Json para objeto - response = DictToObj(response.json()) - - # Verifica o tipo de resposta - match status: - - case 200: - rule("Dados enviados.:" + str(status)) - ok("Verifique o log...") - json_file_saver.save( - response, - "storage/2XX/" - + self.file_name_generator.generate("200") - + ".json", - ) - - case 201: - rule("Dados criados.:" + str(status)) - ok("Verifique o log...") - json_file_saver.save( - response, - "storage/2XX/" - + self.file_name_generator.generate("201") - + ".json", - ) - - case 400: - rule("Error.:" + str(status)) - fail("Verifique o log...") - json_file_saver.save( - response, - "storage/4XX/" - + self.file_name_generator.generate("400") - + ".json", - ) - - case 404: - rule("Error.:" + str(status)) - fail("Verifique o log...") - json_file_saver.save( - response, - "storage/4XX/" - + self.file_name_generator.generate("404") - + ".json", - ) - - case 422: - rule("Error.:" + str(status)) - fail("Verifique o log....") - json_file_saver.save( - response, - "storage/4XX/" - + self.file_name_generator.generate("422") - + ".json", - ) - - return response - - except ValueError: - - return DictToObj( - { - "status": status, - "message": json.dumps(response, ensure_ascii=False, default=vars), - "data": None, - } - ) - - # Contrói a requisição - async def _request(self, client: httpx.AsyncClient, data): - """ - Constrói e envia a requisição com base no método HTTP definido em `data.method`. - - Suporta: - - GET: usa params (query string) - - POST/PUT/PATCH: usa json ou form (data) - - DELETE: suporta params opcionais - """ - # Obtem o verbo de requisição - method = data.method.lower().strip() - - # Obtem o endpoint - url = data.endpoint.lstrip("/") - - # Prepara argumentos de envio - kwargs = {} - - # Obtem o corpo da requisição - body = getattr(data, "body", None) - - # Corpo JSON ou formulário (para POST/PUT/PATCH) - if body is not None: - - # Sanitiza caracteres inválidos antes de enviar - body = self.sanitize_unicode(body) - - # Guarda o corpo da requisição - kwargs["json"] = body - - # Constrói o request (sem enviar ainda) - request = client.build_request(method.upper(), url, **kwargs) - - # Envia a requisição (client.send respeita timeout e intercepta tudo) - response = await client.send(request) - - # Se sucesso, trata normalmente - return await self._response(response, data) - - # Prepara os dados para envio - async def send(self, data): - - async with httpx.AsyncClient( - base_url=self.mirror_sync_env.url, - headers=self._headers(data), - timeout=getattr(data, "timeout", int(self.mirror_sync_env.timeout)), - follow_redirects=True, - ) as client: - - rule("Salvando Dados de Envio...") - if True: - json_file_saver = JsonFileSaver() - json_file_saver.save( - data, - "storage/data/" + self.file_name_generator.generate() + ".json", - ) - - response = await self._request(client, data) - - # Pydantic v2 valida e ignora campos extras (ex.: userId) - return response diff --git a/AjustaFundos/packages/v1/api/Mattermost/services/api_send_to_channel.py b/AjustaFundos/packages/v1/api/Mattermost/services/api_send_to_channel.py deleted file mode 100644 index 2bc841e..0000000 --- a/AjustaFundos/packages/v1/api/Mattermost/services/api_send_to_channel.py +++ /dev/null @@ -1,29 +0,0 @@ -from types import SimpleNamespace -from actions.data.obj_to_dict import ObjToDict -from packages.v1.api.Mattermost.actions.api_action import ApiAction -from actions.ui.ui import status - - -class ApiSendToChannel: - - async def execute(self, data): - - # Converte o SimpleNamespace em um dicionário serializável - ato_dict = ObjToDict(data) - - # Classe de requisição - api_action = ApiAction() - - # Informa que esta enviandoos dados - with status("Mattermost..."): - - # Envia os dados para a API - await api_action.send( - SimpleNamespace( - endpoint="posts", - method="post", - body=ato_dict, - timeout=None, - token="uzszwh6c7pbc8xyt1d1skope8y", - ) - ) diff --git a/AjustaFundos/packages/v1/api/Mirror/actions/api_action.py b/AjustaFundos/packages/v1/api/Mirror/actions/api_action.py deleted file mode 100644 index 45f2161..0000000 --- a/AjustaFundos/packages/v1/api/Mirror/actions/api_action.py +++ /dev/null @@ -1,194 +0,0 @@ -import json -import re -from actions.env.mirror_sync_env import MirrorSyncEnv -from actions.file.file_name_generator import FileNameGenerator -from actions.file.json_file_saver import JsonFileSaver -import httpx -from actions.data.dict_to_obj import DictToObj -from actions.ui.ui import fail, ok, rule - - -class ApiAction: - - def __init__(self) -> None: - - self.file_name_generator = FileNameGenerator() - - # Classe para obter as variaveis de ambiente - mirror_sync_env = MirrorSyncEnv() - - # Obtem as variaveis de ambiente em formato de objeto - self.mirror_sync_env = mirror_sync_env.as_object() - - pass - - def sanitize_unicode(self, data): - """ - Remove caracteres inválidos (surrogates) de strings dentro de estruturas complexas. - """ - if isinstance(data, str): - # Remove caracteres Unicode no intervalo D800–DFFF (não permitidos em UTF-8) - return re.sub(r"[\ud800-\udfff]", "", data) - elif isinstance(data, list): - return [self.sanitize_unicode(i) for i in data] - elif isinstance(data, dict): - return {k: self.sanitize_unicode(v) for k, v in data.items()} - return data - - # Cria os Cabeçalhos de envio - def _headers(self, data): - - headers = { - "Accept": getattr(data, "accept", "application/json"), - "Content-Type": getattr(data, "content_type", "application/json"), - } - - token = getattr(data, "token", None) - - if token: - headers["Authorization"] = f"Bearer {token}" - - return headers - - # Trata os dados da respsota - async def _response(self, response: httpx.Response, data): - - # Tenta JSON; se falhar, retorna texto bruto - try: - - # Gerador de arquivo JSON - json_file_saver = JsonFileSaver() - - # Obtem o código de requisição - status = response.status_code - - # Converter o Json para objeto - response = DictToObj(response.json()) - - # Verifica o tipo de resposta - match status: - - case 200: - rule("Dados enviados.:" + str(status)) - ok("Verifique o log...") - json_file_saver.save( - response, - "storage/2XX/" - + self.file_name_generator.generate("200") - + ".json", - ) - - case 201: - rule("Dados criados.:" + str(status)) - ok("Verifique o log...") - json_file_saver.save( - response, - "storage/2XX/" - + self.file_name_generator.generate("201") - + ".json", - ) - - case 400: - rule("Error.:" + str(status)) - fail("Verifique o log...") - json_file_saver.save( - response, - "storage/4XX/" - + self.file_name_generator.generate("400") - + ".json", - ) - - case 404: - rule("Error.:" + str(status)) - fail("Verifique o log...") - json_file_saver.save( - response, - "storage/4XX/" - + self.file_name_generator.generate("404") - + ".json", - ) - - case 422: - rule("Error.:" + str(status)) - fail("Verifique o log....") - json_file_saver.save( - response, - "storage/4XX/" - + self.file_name_generator.generate("422") - + ".json", - ) - - return response - - except ValueError: - - return DictToObj( - { - "status": status, - "message": json.dumps(response, ensure_ascii=False, default=vars), - "data": None, - } - ) - - # Contrói a requisição - async def _request(self, client: httpx.AsyncClient, data): - """ - Constrói e envia a requisição com base no método HTTP definido em `data.method`. - - Suporta: - - GET: usa params (query string) - - POST/PUT/PATCH: usa json ou form (data) - - DELETE: suporta params opcionais - """ - # Obtem o verbo de requisição - method = data.method.lower().strip() - - # Obtem o endpoint - url = data.endpoint.lstrip("/") - - # Prepara argumentos de envio - kwargs = {} - - # Obtem o corpo da requisição - body = getattr(data, "body", None) - - # Corpo JSON ou formulário (para POST/PUT/PATCH) - if body is not None: - - # Sanitiza caracteres inválidos antes de enviar - body = self.sanitize_unicode(body) - - # Guarda o corpo da requisição - kwargs["json"] = body - - # Constrói o request (sem enviar ainda) - request = client.build_request(method.upper(), url, **kwargs) - - # Envia a requisição (client.send respeita timeout e intercepta tudo) - response = await client.send(request) - - # Se sucesso, trata normalmente - return await self._response(response, data) - - # Prepara os dados para envio - async def send(self, data): - - async with httpx.AsyncClient( - base_url=self.mirror_sync_env.api_url, - headers=self._headers(data), - timeout=getattr(data, "timeout", int(self.mirror_sync_env.timeout)), - follow_redirects=True, - ) as client: - - rule("Salvando Dados de Envio...") - if True: - json_file_saver = JsonFileSaver() - json_file_saver.save( - data, - "storage/data/" + self.file_name_generator.generate() + ".json", - ) - - response = await self._request(client, data) - - # Pydantic v2 valida e ignora campos extras (ex.: userId) - return response diff --git a/AjustaFundos/packages/v1/api/Mirror/schemas/api_schema.py b/AjustaFundos/packages/v1/api/Mirror/schemas/api_schema.py deleted file mode 100644 index c80f74b..0000000 --- a/AjustaFundos/packages/v1/api/Mirror/schemas/api_schema.py +++ /dev/null @@ -1,17 +0,0 @@ -from ast import Dict -from dataclasses import dataclass -from typing import Optional, Dict, Any - - -@dataclass -class RequestData: - base_url: str - endpoint: str - method: str = "get" - accept: str = "application/json" - content_type: str = "application/json" - token: Optional[str] = None - params: Optional[Dict[str, Any]] = None - json: Optional[Dict[str, Any]] = None - form: Optional[Dict[str, Any]] = None - timeout: float = 10.0 diff --git a/AjustaFundos/packages/v1/api/Mirror/schemas/usuario_schema.py b/AjustaFundos/packages/v1/api/Mirror/schemas/usuario_schema.py deleted file mode 100644 index f597d2c..0000000 --- a/AjustaFundos/packages/v1/api/Mirror/schemas/usuario_schema.py +++ /dev/null @@ -1,10 +0,0 @@ -from pydantic import BaseModel - - -class UsuarioAuthenticateSchema(BaseModel): - - username: str - password: str - - class Config: - from_attributes = True diff --git a/AjustaFundos/packages/v1/api/Mirror/services/api_authenticate_service.py b/AjustaFundos/packages/v1/api/Mirror/services/api_authenticate_service.py deleted file mode 100644 index 540b45c..0000000 --- a/AjustaFundos/packages/v1/api/Mirror/services/api_authenticate_service.py +++ /dev/null @@ -1,41 +0,0 @@ -from types import SimpleNamespace - -from actions.env.mirror_sync_env import MirrorSyncEnv -from packages.v1.api.Mirror.actions.api_action import ApiAction -from actions.ui.ui import ok, rule, status - - -class ApiAuthenticateService: - - def __init__(self): - - # Classe de variaveis de ambiente - mirror_sync_env = MirrorSyncEnv() - - # Obtem todas as variaveis que inicia com MIRROR_SYNC - self.mirror_sync_env = mirror_sync_env.as_object() - - async def execute(self): - - rule("Autenticação") - - api_action = ApiAction() - - # Informa que esta enviandoos dados - with status("Autenticando na plataforma..."): - - # Realiza a autenticação - response = await api_action.send( - SimpleNamespace( - endpoint="usuario/authenticate", - method="post", - body={ - "username": self.mirror_sync_env.username, - "password": self.mirror_sync_env.password, - }, - ) - ) - - ok("Autenticação realizada!") - - return response diff --git a/AjustaFundos/packages/v1/api/Mirror/services/api_send_ato_batch_service.py b/AjustaFundos/packages/v1/api/Mirror/services/api_send_ato_batch_service.py deleted file mode 100644 index eb85af4..0000000 --- a/AjustaFundos/packages/v1/api/Mirror/services/api_send_ato_batch_service.py +++ /dev/null @@ -1,29 +0,0 @@ -from types import SimpleNamespace -from actions.data.obj_to_dict import ObjToDict -from packages.v1.api.Mirror.actions.api_action import ApiAction -from actions.ui.ui import status - - -class ApiSendAtoBatchService: - - async def execute(self, data, user_authenticated): - - # Converte o SimpleNamespace em um dicionário serializável - ato_dict = ObjToDict(data) - - # Classe de requisição - api_action = ApiAction() - - # Informa que esta enviandoos dados - with status("Enviando dados..."): - - # Envia os dados para a API - await api_action.send( - SimpleNamespace( - endpoint="ato/batch", - method="post", - token=user_authenticated.token, - body=ato_dict, - timeout=None, - ) - ) diff --git a/AjustaFundos/packages/v1/api/Mirror/services/api_send_ato_service.py b/AjustaFundos/packages/v1/api/Mirror/services/api_send_ato_service.py deleted file mode 100644 index 1136113..0000000 --- a/AjustaFundos/packages/v1/api/Mirror/services/api_send_ato_service.py +++ /dev/null @@ -1,29 +0,0 @@ -from types import SimpleNamespace -from actions.data.obj_to_dict import ObjToDict -from packages.v1.api.Mirror.actions.api_action import ApiAction -from actions.ui.ui import status - - -class ApiSendAtoService: - - async def execute(self, data, user_authenticated): - - # Converte o SimpleNamespace em um dicionário serializável - ato_dict = ObjToDict(data) - - # Classe de requisição - api_action = ApiAction() - - # Informa que esta enviandoos dados - with status("Enviando dados..."): - - # Envia os dados para a API - await api_action.send( - SimpleNamespace( - endpoint="ato/", - method="post", - token=user_authenticated.token, - body=ato_dict, - timeout=None, - ) - ) diff --git a/AjustaFundos/packages/v1/api/Mirror/services/api_send_ged_batch_service.py b/AjustaFundos/packages/v1/api/Mirror/services/api_send_ged_batch_service.py deleted file mode 100644 index 1bec480..0000000 --- a/AjustaFundos/packages/v1/api/Mirror/services/api_send_ged_batch_service.py +++ /dev/null @@ -1,29 +0,0 @@ -from types import SimpleNamespace -from actions.data.obj_to_dict import ObjToDict -from packages.v1.api.Mirror.actions.api_action import ApiAction -from actions.ui.ui import status - - -class ApiSendGedBatchService: - - async def execute(self, data, user_authenticated): - - # Converte o SimpleNamespace em um dicionário serializável - ato_dict = ObjToDict(data) - - # Classe de requisição - api_action = ApiAction() - - # Informa que esta enviandoos dados - with status("Enviando dados..."): - - # Envia os dados para a API - await api_action.send( - SimpleNamespace( - endpoint="ato_documento/batch", - method="post", - token=user_authenticated.token, - body=ato_dict, - timeout=None, - ) - ) diff --git a/AjustaFundos/packages/v1/manutencao/controller/manutencao_v_casamento_controller.py b/AjustaFundos/packages/v1/manutencao/controller/manutencao_v_casamento_controller.py deleted file mode 100644 index a3e5350..0000000 --- a/AjustaFundos/packages/v1/manutencao/controller/manutencao_v_casamento_controller.py +++ /dev/null @@ -1,12 +0,0 @@ -from packages.v1.manutencao.services.manutencao_vincular_noivos_atos_antigos import ( - ManutencaoVincularNoivosAtosAntigos, -) - - -class ManutencaoVCasamentoController: - - def VincularNoivosAtosAntigos(self): - - manutencao_vincular_noivos_atos_antigos = ManutencaoVincularNoivosAtosAntigos() - - return manutencao_vincular_noivos_atos_antigos.execute() diff --git a/AjustaFundos/packages/v1/manutencao/services/manutencao_vincular_noivos_atos_antigos.py b/AjustaFundos/packages/v1/manutencao/services/manutencao_vincular_noivos_atos_antigos.py deleted file mode 100644 index 3f7f3f9..0000000 --- a/AjustaFundos/packages/v1/manutencao/services/manutencao_vincular_noivos_atos_antigos.py +++ /dev/null @@ -1,172 +0,0 @@ -from types import SimpleNamespace -from actions.ui.ui import info, ok, rule, warn -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema -from packages.v1.sequencia.services.g_sequencia.generate_service import GenerateService -from packages.v1.serventias.controllers.v_casamento_controller import ( - VCasamentoController, -) -from packages.v1.serventias.schemas.v_pessoa_schema import ( - VPessoaSaveSchema, - VPessoaSearchSchema, -) -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoIndexSchema, - VPessoaVinculoSaveSchema, -) -from packages.v1.serventias.services.v_pessoa.go.v_pessoa_index_service import ( - VPessoaIndexService, -) -from packages.v1.serventias.services.v_pessoa.go.v_pessoa_save_service import ( - VPessoaSaveService, -) -from packages.v1.serventias.services.v_pessoa_vinculo.go.v_pessoa_vinculo_index_service import ( - VPessoaVinculoIndexService, -) -from packages.v1.serventias.services.v_pessoa_vinculo.go.v_pessoa_vinculo_save_service import ( - VPessoaVInculoSaveService, -) - - -class ManutencaoVincularNoivosAtosAntigos: - - def _gerar_sequencia(self, tabela): - - # Cria o schema de sequência - sequencia_schema = GSequenciaSchema() - sequencia_schema.tabela = tabela - - # Gera a sequência atualizada - generate = GenerateService() - - response = generate.execute(sequencia_schema) - - return response.sequencia - - def _cadastrar_pessoa(self, pessoa): - - info("Cadastro da pessoa.:" + pessoa.nome) - - pessoa.pessoa_id = self._gerar_sequencia("V_PESSOA") - - v_pessoa = VPessoaSaveService() - - info("Criando sequência de pessoa..: " + pessoa.nome) - - response = v_pessoa.execute( - VPessoaSaveSchema( - pessoa_id=pessoa.pessoa_id, - nome=pessoa.nome, - cpf_cnpj=pessoa.cpf, - nacionalidade=pessoa.nacionalidade, - naturalidade=pessoa.naturalidade, - data_nascimento=pessoa.data_nascimento, - nome_mae=pessoa.nome_mae, - nome_pai=pessoa.nome_pai, - ) - ) - - return response - - def _vincular_pessoa(self, nome, ato_antigo, sexo): - - info("Buscando noivo(a)..: " + nome) - - v_pessoa_search = VPessoaIndexService() - - response_pessoa = v_pessoa_search.execute(VPessoaSearchSchema(nome=nome)) - - if not response_pessoa: - - if sexo == "M": - - response_pessoa = self._cadastrar_pessoa( - SimpleNamespace( - nome=nome, - sexo=sexo, - cpf=getattr(ato_antigo, "noivo_cpf", None), - nacionalidade=getattr(ato_antigo, "noivo_nacionalidade", None), - naturalidade=getattr( - ato_antigo, "lv_antigo_noivo_naturalidade", None - ), - data_nascimento=getattr( - ato_antigo, "lv_antigo_noivo_nascimento", None - ), - nome_mae=getattr(ato_antigo, "lv_antigo_noivo_mae", None), - nome_pai=getattr(ato_antigo, "lv_antigo_noivo_pai", None), - ) - ) - - elif sexo == "F": - - response_pessoa = self._cadastrar_pessoa( - SimpleNamespace( - nome=nome, - exo=sexo, - cpf=getattr(ato_antigo, "noiva_cpf", None), - nacionalidade=getattr(ato_antigo, "noiva_nacionalidade", None), - naturalidade=getattr( - ato_antigo, "lv_antigo_noiva_naturalidade", None - ), - data_nascimento=getattr( - ato_antigo, "lv_antigo_noiva_nascimento", None - ), - nome_mae=getattr(ato_antigo, "lv_antigo_noiva_mae", None), - nome_pai=getattr(ato_antigo, "lv_antigo_noiva_pai", None), - ) - ) - - ok("Noivo(a) localizado..: " + nome) - - info("Vinculando ao casamento..: " + nome) - - info("Criando sequência de vinculo..: " + nome) - - sequencia = self._gerar_sequencia("V_PESSOA_VINCULO") - - v_pessoa_vinculo_save_service = VPessoaVInculoSaveService() - - response = v_pessoa_vinculo_save_service.execute( - VPessoaVinculoSaveSchema( - pessoa_vinculo_id=sequencia, - registro_id=ato_antigo.casamento_id, - livro_natureza_id=4, - nome=getattr(response_pessoa, "nome", None), - pessoa_id=response_pessoa.pessoa_id, - tb_estadocivil_id=getattr(response_pessoa, "tb_estadocivil_id", None), - tb_profissao_id=getattr(response_pessoa, "tb_profissao_id", None), - tipo_cadastro_geral=7, - ) - ) - - if response: - ok("Noivo(a) vinculado..: " + ato_antigo.noivo_nome_atual) - - def execute(self): - - v_casamento_controller = VCasamentoController() - - response_atos_antigos = v_casamento_controller.AntigosIndex() - - for ato_antigo in response_atos_antigos: - - rule("Casamento.:" + str(ato_antigo.casamento_id)) - - v_pessoa_vinculo_service = VPessoaVinculoIndexService() - - response_pessoas = v_pessoa_vinculo_service.execute( - VPessoaVinculoIndexSchema( - registro_id=ato_antigo.casamento_id, livro_natureza_id=4 - ) - ) - - if len(response_pessoas) == 0: - - info("Casamento antigo sem partes vinculadas") - - if ato_antigo.noivo_nome_atual: - - self._vincular_pessoa(ato_antigo.noivo_nome_atual, ato_antigo, "M") - - if ato_antigo.noivo_nome_atual: - - self._vincular_pessoa(ato_antigo.noiva_nome_atual, ato_antigo, "F") diff --git a/AjustaFundos/packages/v1/parametros/actions/g_config/g_config_by_nome_show_action.py b/AjustaFundos/packages/v1/parametros/actions/g_config/g_config_by_nome_show_action.py deleted file mode 100644 index 1c14c2a..0000000 --- a/AjustaFundos/packages/v1/parametros/actions/g_config/g_config_by_nome_show_action.py +++ /dev/null @@ -1,18 +0,0 @@ -from packages.v1.parametros.repositories.g_config.g_config_show_by_nome_repository import ( - GConfigShowByNomeRepository, -) -from packages.v1.parametros.schemas.g_config_schema import ( - GConfigNomeSchema, - GConfigResponseSchema, -) - - -class GConfigShowByNomeAction: - - def execute(self, g_config_nome_schema: GConfigNomeSchema) -> GConfigResponseSchema: - - # Instânciamento de repositório - g_config_show_by_nome_repository = GConfigShowByNomeRepository() - - # Execução do repositório - return g_config_show_by_nome_repository.execute(g_config_nome_schema) diff --git a/AjustaFundos/packages/v1/parametros/actions/g_config/g_config_show_by_nome_action.py b/AjustaFundos/packages/v1/parametros/actions/g_config/g_config_show_by_nome_action.py deleted file mode 100644 index 1c14c2a..0000000 --- a/AjustaFundos/packages/v1/parametros/actions/g_config/g_config_show_by_nome_action.py +++ /dev/null @@ -1,18 +0,0 @@ -from packages.v1.parametros.repositories.g_config.g_config_show_by_nome_repository import ( - GConfigShowByNomeRepository, -) -from packages.v1.parametros.schemas.g_config_schema import ( - GConfigNomeSchema, - GConfigResponseSchema, -) - - -class GConfigShowByNomeAction: - - def execute(self, g_config_nome_schema: GConfigNomeSchema) -> GConfigResponseSchema: - - # Instânciamento de repositório - g_config_show_by_nome_repository = GConfigShowByNomeRepository() - - # Execução do repositório - return g_config_show_by_nome_repository.execute(g_config_nome_schema) diff --git a/AjustaFundos/packages/v1/parametros/repositories/g_config/g_config_show_by_nome_repository.py b/AjustaFundos/packages/v1/parametros/repositories/g_config/g_config_show_by_nome_repository.py deleted file mode 100644 index 86160c1..0000000 --- a/AjustaFundos/packages/v1/parametros/repositories/g_config/g_config_show_by_nome_repository.py +++ /dev/null @@ -1,31 +0,0 @@ -from abstracts.repository_firebird import BaseRepositoryFirebird -from packages.v1.parametros.schemas.g_config_schema import ( - GConfigNomeSchema, - GConfigResponseSchema, -) - - -class GConfigShowByNomeRepository(BaseRepositoryFirebird): - - def execute(self, g_config_nome_schema: GConfigNomeSchema) -> GConfigResponseSchema: - - # Montagem da consulta sql - sql = """ SELECT - FIRST 1 GC.* - FROM G_CONFIG GC - JOIN G_CONFIG_GRUPO GCG ON GC.CONFIG_GRUPO_ID = GCG.CONFIG_GRUPO_ID - WHERE GC.NOME LIKE :nome - AND GCG.SISTEMA_ID = :sistema_id - """ - - # Preenchimento dos parâmetros - params = { - "nome": g_config_nome_schema.nome, - "sistema_id": g_config_nome_schema.sistema_id, - } - - # Execução do sql - response = self.fetch_one(sql, params) - - # Transforma em dict associativo - return response diff --git a/AjustaFundos/packages/v1/parametros/schemas/g_config_schema.py b/AjustaFundos/packages/v1/parametros/schemas/g_config_schema.py deleted file mode 100644 index 2486732..0000000 --- a/AjustaFundos/packages/v1/parametros/schemas/g_config_schema.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import Optional -from pydantic import BaseModel, ConfigDict - - -class GConfigSchema(BaseModel): - config_id: Optional[float] = None - config_grupo_id: Optional[float] = None - config_padrao_id: Optional[float] = None - secao: Optional[str] = None - nome: Optional[str] = None - valor: Optional[str] = None - descricao: Optional[str] = None - texto: Optional[str] = None - terminal: Optional[str] = None - tipo_valor: Optional[str] = None - atualizado: Optional[str] = None - - # substitui a antiga inner class Config - model_config = ConfigDict(from_attributes=True) - - -class GConfigResponseSchema(GConfigSchema): - model_config = ConfigDict(from_attributes=True) - - -class GConfigNomeSchema(BaseModel): - nome: str = None - sistema_id: float = None - model_config = ConfigDict(from_attributes=True) diff --git a/AjustaFundos/packages/v1/parametros/services/g_config/g_config_show_by_nome_service.py b/AjustaFundos/packages/v1/parametros/services/g_config/g_config_show_by_nome_service.py deleted file mode 100644 index 0137b93..0000000 --- a/AjustaFundos/packages/v1/parametros/services/g_config/g_config_show_by_nome_service.py +++ /dev/null @@ -1,18 +0,0 @@ -from packages.v1.parametros.actions.g_config.g_config_show_by_nome_action import ( - GConfigShowByNomeAction, -) -from packages.v1.parametros.schemas.g_config_schema import ( - GConfigNomeSchema, - GConfigResponseSchema, -) - - -class GConfigShowByNomeService: - - def execute(self, g_config_nome_schema: GConfigNomeSchema) -> GConfigResponseSchema: - - # Instânciamento de Action - g_config_show_by_nome_action = GConfigShowByNomeAction() - - # Execução da Ação - return g_config_show_by_nome_action.execute(g_config_nome_schema) diff --git a/AjustaFundos/packages/v1/selos/actions/g_selo_livro/g_selo_livro_create_object_acton.py b/AjustaFundos/packages/v1/selos/actions/g_selo_livro/g_selo_livro_create_object_acton.py deleted file mode 100644 index 8bd910a..0000000 --- a/AjustaFundos/packages/v1/selos/actions/g_selo_livro/g_selo_livro_create_object_acton.py +++ /dev/null @@ -1,9 +0,0 @@ -from types import SimpleNamespace - - -class GSeloLivroCreateObjectAction: - - @staticmethod - def execute(data): - """Cria um objeto SimpleNamespace para atos vinculados.""" - return SimpleNamespace(**data) diff --git a/AjustaFundos/packages/v1/selos/actions/g_selo_livro/g_selo_livro_index_action.py b/AjustaFundos/packages/v1/selos/actions/g_selo_livro/g_selo_livro_index_action.py deleted file mode 100644 index 5a6b9bd..0000000 --- a/AjustaFundos/packages/v1/selos/actions/g_selo_livro/g_selo_livro_index_action.py +++ /dev/null @@ -1,17 +0,0 @@ -from packages.v1.selos.repositories.g_selo_livro.g_selo_livro_index_repository import ( - GSeloLivroIndexRepository, -) -from packages.v1.selos.schemas.g_selo_livro_schema import ( - GSeloLivroIndexSchema, -) - - -class GSeloLivroIndexAction: - - def execute(self, g_selo_livro_index_schema: GSeloLivroIndexSchema): - - # Instânciamento de repositório - g_selo_livro_index_repository = GSeloLivroIndexRepository() - - # Retorna todos produtos - return g_selo_livro_index_repository.execute(g_selo_livro_index_schema) diff --git a/AjustaFundos/packages/v1/selos/actions/t_ato_vinculoparte/t_ato_vinculoparte_index_action.py b/AjustaFundos/packages/v1/selos/actions/t_ato_vinculoparte/t_ato_vinculoparte_index_action.py deleted file mode 100644 index 0d6804c..0000000 --- a/AjustaFundos/packages/v1/selos/actions/t_ato_vinculoparte/t_ato_vinculoparte_index_action.py +++ /dev/null @@ -1,22 +0,0 @@ -from packages.v1.serventias.repositories.t_ato_vinculoparte.t_ato_vinculoparte_index_repository import ( - TAatoVinculoParteIndexRepository, -) -from packages.v1.serventias.schemas.t_ato_vinculoparte_schema import ( - ResponseTAtoVinculoParteSchema, - TAtoVinculoParteIndexSchema, -) - - -class TAtoVinculoParteIndexAction(=): - - def execute( - self, ato_vinculoparte_index_schema: TAtoVinculoParteIndexSchema - ) -> ResponseTAtoVinculoParteSchema: - - # Instânciamento de repositório - t_ato_vinculoparte_index_repository = TAatoVinculoParteIndexRepository() - - # Retorna todos produtos - return t_ato_vinculoparte_index_repository.execute( - ato_vinculoparte_index_schema - ) diff --git a/AjustaFundos/packages/v1/selos/controllers/g_selo_livro_controller.py b/AjustaFundos/packages/v1/selos/controllers/g_selo_livro_controller.py deleted file mode 100644 index be97f0d..0000000 --- a/AjustaFundos/packages/v1/selos/controllers/g_selo_livro_controller.py +++ /dev/null @@ -1,18 +0,0 @@ -# Importação de bibliotecas -from packages.v1.selos.services.g_selo_livro.go.g_selo_livro_index_service import ( - GSeloLivroIndexService, -) -from packages.v1.selos.schemas.g_selo_livro_schema import ( - GSeloLivroIndexSchema, -) - - -class GSeloLivroController: - - def index(self, g_selo_livro_index_schema: GSeloLivroIndexSchema): - - # Importação da classe desejad - g_selo_livro_index_service = GSeloLivroIndexService() - - # Lista todos os produtos - return g_selo_livro_index_service.execute(g_selo_livro_index_schema) diff --git a/AjustaFundos/packages/v1/selos/controllers/t_ato_vinculoparte_controller.py b/AjustaFundos/packages/v1/selos/controllers/t_ato_vinculoparte_controller.py deleted file mode 100644 index 4ea4eb8..0000000 --- a/AjustaFundos/packages/v1/selos/controllers/t_ato_vinculoparte_controller.py +++ /dev/null @@ -1,24 +0,0 @@ -from packages.v1.serventias.schemas.t_ato_vinculoparte_schema import ( - ResponseTAtoVinculoParteSchema, - TAtoVinculoParteIndexSchema, -) -from packages.v1.serventias.services.t_ato_vinculoparte.go.t_ato_vinculoparte_index_service import ( - TAtoVinculoParteIndexService, -) - - -class TAtoVinculoParteController: - - def index( - self, ato_vinculoparte_index_schema: TAtoVinculoParteIndexSchema - ) -> ResponseTAtoVinculoParteSchema: - - # Importação da classe desejada - t_ato_vinculoparte_index_service = TAtoVinculoParteIndexService() - - # Executa a classe importada - response = t_ato_vinculoparte_index_service.execute( - ato_vinculoparte_index_schema - ) - - return response diff --git a/AjustaFundos/packages/v1/selos/repositories/g_selo_livro/g_selo_livro_index_repository.py b/AjustaFundos/packages/v1/selos/repositories/g_selo_livro/g_selo_livro_index_repository.py deleted file mode 100644 index 5956f78..0000000 --- a/AjustaFundos/packages/v1/selos/repositories/g_selo_livro/g_selo_livro_index_repository.py +++ /dev/null @@ -1,52 +0,0 @@ -from abstracts.repository_firebird import BaseRepositoryFirebird -from packages.v1.selos.schemas.g_selo_livro_schema import ( - GSeloLivroIndexSchema, -) - - -class GSeloLivroIndexRepository(BaseRepositoryFirebird): - """ - Repositório para a operação de listagem de todos os registros - na tabela t_censec_qualidade. - """ - - def execute(self, g_selo_livro_index_schema: GSeloLivroIndexSchema): - """ - Executa a consulta SQL para buscar todos os registros. - - Returns: - Uma lista de dicionários contendo os dados dos registros. - """ - # Montagem do SQL - sql = """ SELECT - COALESCE(NULLIF(TRIM(GU.NOME_COMPLETO), ''), 'Não informado') AS nome_serventuario_praticou_ato, - COALESCE(GSG.NUMERO, 0) AS tipo_ato, - COALESCE(NULLIF(TRIM(GST.NOTA_FISCAL), ''), 'Não informado') AS identificacao_pedido_cgj, - COALESCE(NULLIF(TRIM(GSL.NUMERO_SELO), ''), 'Não informado') AS codigo_selo, - COALESCE(NULLIF(TRIM(GSL.NUMERO_SELO), ''), 'Não informado') AS codigo_ato, - COALESCE(NULLIF(TRIM(GSL.APRESENTANTE), ''), 'Não informado') AS nome_civil_ato, - COALESCE(GSL.USUARIO_ID, 0) AS USUARIO_ID, - GSL.DATA_INFORMACAO as data_solicitacao, - COALESCE(NULLIF(TRIM(GSL.IP_MAQUINA), ''), 'Não informado') AS ip_maquina, - COALESCE(GSL.VALOR_EMOLUMENTO, 0) AS emolumento, - COALESCE(GSL.VALOR_TAXA_JUDICIARIA, 0) AS taxa_judiciaria, - COALESCE(GSL.VALOR_FUNDESP, 0) AS fundos_estaduais - FROM G_SELO_LIVRO GSL - JOIN G_SELO_LOTE GST ON GSL.SELO_LOTE_ID = GST.SELO_LOTE_ID - JOIN G_SELO_GRUPO GSG ON GST.SELO_GRUPO_ID = GSG.SELO_GRUPO_ID - JOIN G_USUARIO GU ON GSL.USUARIO_ID = GU.USUARIO_ID - WHERE GSL.CAMPO_ID = :campo_id - AND GSL.TABELA LIKE :tabela - ORDER BY GSG.NUMERO ASC; """ - - # Preenchimento dos parâmetros - params = { - "campo_id": g_selo_livro_index_schema.campo_id, - "tabela": g_selo_livro_index_schema.tabela, - } - - # Execução do sql - response = self.fetch_all(sql, params) - - # Retorna os dados localizados - return response diff --git a/AjustaFundos/packages/v1/selos/repositories/t_ato_vinculoparte/t_ato_vinculoparte_index_repository.py b/AjustaFundos/packages/v1/selos/repositories/t_ato_vinculoparte/t_ato_vinculoparte_index_repository.py deleted file mode 100644 index 7ddabe9..0000000 --- a/AjustaFundos/packages/v1/selos/repositories/t_ato_vinculoparte/t_ato_vinculoparte_index_repository.py +++ /dev/null @@ -1,37 +0,0 @@ -from abstracts.repository_firebird import BaseRepositoryFirebird -from packages.v1.serventias.schemas.t_ato_vinculoparte_schema import ( - ResponseTAtoVinculoParteSchema, - TAtoVinculoParteIndexSchema, -) - - -class TAatoVinculoParteIndexRepository(BaseRepositoryFirebird): - """ - Repositório para a operação de listagem de todos os registros - na tabela t_censec_qualidade. - """ - - def execute( - self, ato_vinculoparte_index_schema: TAtoVinculoParteIndexSchema - ) -> ResponseTAtoVinculoParteSchema: - """ - Executa a consulta SQL para buscar todos os registros. - - Returns: - Uma lista de dicionários contendo os dados dos registros. - """ - # Montagem do SQL - sql = """ SELECT - TAV.PESSOA_NOME, - TAV.PESSOA_CPF - FROM T_ATO_VINCULOPARTE TAV - WHERE TAV.ATO_ID = :ato_id """ - - # Preenchimento dos parâmetros - params = {"ato_id": ato_vinculoparte_index_schema.ato_id} - - # Execução do sql - response = self.fetch_all(sql, params) - - # Retorna os dados localizados - return response diff --git a/AjustaFundos/packages/v1/selos/schemas/__init__.py b/AjustaFundos/packages/v1/selos/schemas/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/AjustaFundos/packages/v1/selos/schemas/g_selo_livro_schema.py b/AjustaFundos/packages/v1/selos/schemas/g_selo_livro_schema.py deleted file mode 100644 index 00e360b..0000000 --- a/AjustaFundos/packages/v1/selos/schemas/g_selo_livro_schema.py +++ /dev/null @@ -1,31 +0,0 @@ -from pydantic import BaseModel - - -class GSeloLivroIndexSchema(BaseModel): - campo_id: int - tabela: str - - class Config: - from_attributes = True - - -class GSeloLivro(BaseModel): - selo_livro_id: int - numero_selo: str - apresentante: str - usuario_id: str - data_informacao: str - ip_maquina: str - valor_emolumento: str - valor_taxa_judiciaria: str - valor_fundesp: str - - class Config: - from_attributes = True - - -class ResponseGSeloLivro(BaseModel): - data: list[GSeloLivro] - - class Config: - from_attributes = True diff --git a/AjustaFundos/packages/v1/selos/schemas/t_ato_vinculoparte_schema.py b/AjustaFundos/packages/v1/selos/schemas/t_ato_vinculoparte_schema.py deleted file mode 100644 index cdf7235..0000000 --- a/AjustaFundos/packages/v1/selos/schemas/t_ato_vinculoparte_schema.py +++ /dev/null @@ -1,20 +0,0 @@ -from pydantic import BaseModel - -class TAtoVinculoParteIndexSchema(BaseModel): - ato_id: int - - class Config: - from_attributes = True - -class TAtoVinculoParteSchema(BaseModel): - pessoa_nome: str - pessoa_cpf: str - - class Config: - from_attributes = True - -class ResponseTAtoVinculoParteSchema(BaseModel): - data: list[TAtoVinculoParteSchema] - - class Config: - from_attributes = True \ No newline at end of file diff --git a/AjustaFundos/packages/v1/selos/services/g_selo_livro/go/g_selo_livro_index_service.py b/AjustaFundos/packages/v1/selos/services/g_selo_livro/go/g_selo_livro_index_service.py deleted file mode 100644 index a1c6c4b..0000000 --- a/AjustaFundos/packages/v1/selos/services/g_selo_livro/go/g_selo_livro_index_service.py +++ /dev/null @@ -1,39 +0,0 @@ -from packages.v1.selos.actions.g_selo_livro.g_selo_livro_index_action import ( - GSeloLivroIndexAction, -) -from packages.v1.selos.schemas.g_selo_livro_schema import ( - GSeloLivroIndexSchema, -) - - -class GSeloLivroIndexService: - """ - 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, g_selo_livro_index_schema: GSeloLivroIndexSchema): - """ - 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 - # ---------------------------------------------------- - g_selo_livro_index_action = GSeloLivroIndexAction() - - # ---------------------------------------------------- - # Execução da ação - # ---------------------------------------------------- - data = g_selo_livro_index_action.execute(g_selo_livro_index_schema) - - # ---------------------------------------------------- - # Retorno da informação - # ---------------------------------------------------- - return data diff --git a/AjustaFundos/packages/v1/selos/services/t_ato_vinculoparte/go/t_ato_vinculoparte_index_service.py b/AjustaFundos/packages/v1/selos/services/t_ato_vinculoparte/go/t_ato_vinculoparte_index_service.py deleted file mode 100644 index 06553ae..0000000 --- a/AjustaFundos/packages/v1/selos/services/t_ato_vinculoparte/go/t_ato_vinculoparte_index_service.py +++ /dev/null @@ -1,42 +0,0 @@ -from packages.v1.serventias.actions.t_ato_vinculoparte.t_ato_vinculoparte_index_action import ( - TAtoVinculoParteIndexAction, -) -from packages.v1.serventias.schemas.t_ato_vinculoparte_schema import ( - ResponseTAtoVinculoParteSchema, - TAtoVinculoParteIndexSchema, -) - - -class TAtoVinculoParteIndexService: - """ - 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, ato_vinculoparte_index_schema: TAtoVinculoParteIndexSchema - ) -> ResponseTAtoVinculoParteSchema: - """ - 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 - # ---------------------------------------------------- - t_ato_vinculoparte_action = TAtoVinculoParteIndexAction() - - # ---------------------------------------------------- - # Execução da ação - # ---------------------------------------------------- - data = t_ato_vinculoparte_action.execute(ato_vinculoparte_index_schema) - - # ---------------------------------------------------- - # Retorno da informação - # ---------------------------------------------------- - return data diff --git a/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/checkout_action.py b/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/checkout_action.py deleted file mode 100644 index a0cb63f..0000000 --- a/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/checkout_action.py +++ /dev/null @@ -1,13 +0,0 @@ -from packages.v1.sequencia.repositories.g_sequencia.checkout import Checkout -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema - - -class CheckoutAction: - - def execute(self, sequencia_schema: GSequenciaSchema): - - # Instânciamento de repositório - checkout = Checkout() - - # Execução do repositório - return checkout.execute(sequencia_schema) diff --git a/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/get_action.py b/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/get_action.py deleted file mode 100644 index 2709829..0000000 --- a/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/get_action.py +++ /dev/null @@ -1,13 +0,0 @@ -from packages.v1.sequencia.repositories.g_sequencia.get import Get -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema - - -class GetAction: - - def execute(self, sequencia_schema: GSequenciaSchema): - - # Instânciamento de repositório - get = Get() - - # Execução do repositório - return get.execute(sequencia_schema) diff --git a/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/save_action.py b/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/save_action.py deleted file mode 100644 index e069396..0000000 --- a/AjustaFundos/packages/v1/sequencia/actions/g_sequencia/save_action.py +++ /dev/null @@ -1,13 +0,0 @@ -from packages.v1.sequencia.repositories.g_sequencia.save import Save -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema - - -class SaveAction: - - def execute(self, sequencia_schema: GSequenciaSchema): - - # Instânciamento de repositório - save = Save() - - # Execução do repositório - return save.execute(sequencia_schema) diff --git a/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/checkout.py b/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/checkout.py deleted file mode 100644 index 3987865..0000000 --- a/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/checkout.py +++ /dev/null @@ -1,71 +0,0 @@ -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema -from abstracts.repository_firebird import BaseRepositoryFirebird -from fastapi import HTTPException, status - - -class Checkout(BaseRepositoryFirebird): - - def execute(self, sequencia_schema: GSequenciaSchema): - - # 1) Descobre o nome da PK a partir dos metadados - sql = """ - SELECT - sg.RDB$FIELD_NAME AS primary_key - FROM RDB$RELATION_CONSTRAINTS rc - JOIN RDB$INDEX_SEGMENTS sg - ON rc.RDB$INDEX_NAME = sg.RDB$INDEX_NAME - WHERE rc.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' - AND rc.RDB$RELATION_NAME = UPPER(:tabela) - ORDER BY sg.RDB$FIELD_POSITION - """ - params = {"tabela": sequencia_schema.tabela} - pk_result = self.fetch_one(sql, params) - - if not pk_result: - raise Exception( - f"Tabela {sequencia_schema.tabela} não possui chave primária" - ) - - # CORREÇÃO AQUI - pk_field = pk_result.primary_key.strip() - - # 2) Monta dinamicamente a query para buscar o último ID - sql = f"SELECT MAX({pk_field}) AS last_id FROM {sequencia_schema.tabela}" - last_id_row = self.fetch_one(sql) - - # CORREÇÃO: SimpleNamespace → acessar como atributo - last_id = last_id_row.last_id if last_id_row else None - if last_id is None: - last_id = 0 # tabela vazia - - # 3) Verifica se a tabela foi cadastrada no G_SEQUENCIA - sql = """ - SELECT * - FROM G_SEQUENCIA - WHERE TABELA = :tabela - """ - params = {"tabela": sequencia_schema.tabela} - g_seq = self.fetch_one(sql, params) - - # 4) Se não houver registro no g_sequencia, cadastra um novo - if not g_seq: - sql = """ - INSERT INTO G_SEQUENCIA (TABELA, SEQUENCIA) - VALUES (:tabela, :sequencia) - """ - params = {"tabela": sequencia_schema.tabela, "sequencia": last_id} - self.run(sql, params) - return last_id - - # 5) Se a sequência estiver divergente - if g_seq.sequencia != last_id: - raise HTTPException( - status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, - detail=( - f"A sequência atual ({g_seq.sequencia}) está divergente " - f"do último ID da tabela ({last_id})" - ), - ) - - # Tudo ok → retorna o last_id - return last_id diff --git a/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/get.py b/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/get.py deleted file mode 100644 index 5b8bc41..0000000 --- a/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/get.py +++ /dev/null @@ -1,19 +0,0 @@ -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema -from abstracts.repository_firebird import BaseRepositoryFirebird - - -class Get(BaseRepositoryFirebird): - - def execute(self, sequencia_schema: GSequenciaSchema): - - # Montagem da consulta sql - sql = """ SELECT FIRST 1 * FROM G_SEQUENCIA gs WHERE gs.TABELA LIKE :tabela """ - - # Preenchimento dos parâmetros - params = {"tabela": sequencia_schema.tabela} - - # Execução do sql - response = self.fetch_one(sql, params) - - # Transforma em dict associativo - return response diff --git a/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/save.py b/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/save.py deleted file mode 100644 index 1ccc580..0000000 --- a/AjustaFundos/packages/v1/sequencia/repositories/g_sequencia/save.py +++ /dev/null @@ -1,25 +0,0 @@ -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema -from abstracts.repository_firebird import BaseRepositoryFirebird - - -class Save(BaseRepositoryFirebird): - - def execute(self, sequencia_schema: GSequenciaSchema): - - # Construção do sql - sql = """ UPDATE G_SEQUENCIA - SET SEQUENCIA = :sequencia - WHERE TABELA LIKE :tabela - RETURNING TABELA, SEQUENCIA """ - - # Preenchimento de parâmetros - params = { - "sequencia": sequencia_schema.sequencia, - "tabela": sequencia_schema.tabela, - } - - # Execução do sql - response = self.run_and_return(sql, params) - - # Retorna como verdadeiro se for salvo com sucesso - return response diff --git a/AjustaFundos/packages/v1/sequencia/schemas/g_sequencia.py b/AjustaFundos/packages/v1/sequencia/schemas/g_sequencia.py deleted file mode 100644 index ee1607a..0000000 --- a/AjustaFundos/packages/v1/sequencia/schemas/g_sequencia.py +++ /dev/null @@ -1,11 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - - -class GSequenciaSchema(BaseModel): - tabela: Optional[str] = None - sequencia: Optional[str] = None - - class Config: - from_attributes = True diff --git a/AjustaFundos/packages/v1/sequencia/services/g_sequencia/checkout_service.py b/AjustaFundos/packages/v1/sequencia/services/g_sequencia/checkout_service.py deleted file mode 100644 index a90ede0..0000000 --- a/AjustaFundos/packages/v1/sequencia/services/g_sequencia/checkout_service.py +++ /dev/null @@ -1,25 +0,0 @@ -from packages.v1.sequencia.actions.g_sequencia.checkout_action import CheckoutAction -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema -from fastapi import HTTPException, status - - -class GenerateService: - - def execute(self, sequencia_schema: GSequenciaSchema): - - # Instânciamento de Action - checkoutAction = CheckoutAction() - - # Atualiza a sequência atual - data = checkoutAction.execute(sequencia_schema) - - # Verifica se foi localizado o registro - if not data: - # Retorna uma exceção - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Não foi possível localizar a tabela para verificação de sequência", - ) - - # Retorna a informação localizada - return data diff --git a/AjustaFundos/packages/v1/sequencia/services/g_sequencia/generate_service.py b/AjustaFundos/packages/v1/sequencia/services/g_sequencia/generate_service.py deleted file mode 100644 index 30a7cfa..0000000 --- a/AjustaFundos/packages/v1/sequencia/services/g_sequencia/generate_service.py +++ /dev/null @@ -1,26 +0,0 @@ -from packages.v1.sequencia.actions.g_sequencia.get_action import GetAction -from packages.v1.sequencia.actions.g_sequencia.save_action import SaveAction -from packages.v1.sequencia.actions.g_sequencia.checkout_action import CheckoutAction -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema - - -class GenerateService: - - def execute(self, sequencia_schema: GSequenciaSchema): - - # Instânciamento de Action - getAction = GetAction() - saveAction = SaveAction() - checkoutAction = CheckoutAction() - - # # Verifico se a tabela existe no G_SEQUENCIA e se a sequência está correta - # checkoutAction.execute(sequencia_schema) - - # Busco a sequência atual - sequencia_result = getAction.execute(sequencia_schema) - - # Incrementa a sequência atual - sequencia_schema.sequencia = sequencia_result.sequencia + 1 - - # Atualiza a sequência atual - return saveAction.execute(sequencia_schema) diff --git a/AjustaFundos/packages/v1/sequencia/services/g_sequencia/save_service.py b/AjustaFundos/packages/v1/sequencia/services/g_sequencia/save_service.py deleted file mode 100644 index 6affda3..0000000 --- a/AjustaFundos/packages/v1/sequencia/services/g_sequencia/save_service.py +++ /dev/null @@ -1,14 +0,0 @@ -from packages.v1.sequencia.actions.g_sequencia.save_action import \ - SaveAction -from packages.v1.sequencia.schemas.g_sequencia import GSequenciaSchema - - -class SaveService: - - def execute(self, sequencia_schema : GSequenciaSchema): - - # Instânciamento de Action - saveAction = SaveAction() - - # Execução da Ação - return saveAction.execute(sequencia_schema) \ No newline at end of file diff --git a/AjustaFundos/packages/v1/serventias/actions/v_casamento/v_casamento_antigo_index_action.py b/AjustaFundos/packages/v1/serventias/actions/v_casamento/v_casamento_antigo_index_action.py deleted file mode 100644 index 8011218..0000000 --- a/AjustaFundos/packages/v1/serventias/actions/v_casamento/v_casamento_antigo_index_action.py +++ /dev/null @@ -1,14 +0,0 @@ -from packages.v1.serventias.repositories.v_casamento.v_casamento_antigo_index_repository import ( - VCasamentoAntigoIndexRepository, -) - - -class VCasamentoAntigosIndexAction: - - def execute(self): - - # Instânciamento de repositório - v_casamento_index_repository = VCasamentoAntigoIndexRepository() - - # Retorna todos produtos - return v_casamento_index_repository.execute() diff --git a/AjustaFundos/packages/v1/serventias/actions/v_pessoa/v_pessoa_index_action.py b/AjustaFundos/packages/v1/serventias/actions/v_pessoa/v_pessoa_index_action.py deleted file mode 100644 index 0897485..0000000 --- a/AjustaFundos/packages/v1/serventias/actions/v_pessoa/v_pessoa_index_action.py +++ /dev/null @@ -1,17 +0,0 @@ -from packages.v1.serventias.repositories.v_pessoa.v_pessoa_index_repository import ( - VPessoaIndexRepository, -) -from packages.v1.serventias.schemas.v_pessoa_schema import ( - VPessoaSaveSchema, -) - - -class VPessoaIndexAction: - - def execute(self, v_pessoa_search: VPessoaSaveSchema): - - # Instânciamento de repositório - v_pessoa_save = VPessoaIndexRepository() - - # Retorna todos produtos - return v_pessoa_save.execute(v_pessoa_search) diff --git a/AjustaFundos/packages/v1/serventias/actions/v_pessoa/v_pessoa_save_action.py b/AjustaFundos/packages/v1/serventias/actions/v_pessoa/v_pessoa_save_action.py deleted file mode 100644 index 2fba6c9..0000000 --- a/AjustaFundos/packages/v1/serventias/actions/v_pessoa/v_pessoa_save_action.py +++ /dev/null @@ -1,17 +0,0 @@ -from packages.v1.serventias.repositories.v_pessoa.v_pessoa_save_repository import ( - VPessoaSaveRepository, -) -from packages.v1.serventias.schemas.v_pessoa_schema import ( - VPessoaSaveSchema, -) - - -class VPessoaSaveAction: - - def execute(self, v_pessoa_save_schema: VPessoaSaveSchema): - - # Instânciamento de repositório - v_pessoa_save = VPessoaSaveRepository() - - # Retorna todos produtos - return v_pessoa_save.execute(v_pessoa_save_schema) diff --git a/AjustaFundos/packages/v1/serventias/actions/v_pessoa_vinculo/v_pessoa_vinculo_index_action.py b/AjustaFundos/packages/v1/serventias/actions/v_pessoa_vinculo/v_pessoa_vinculo_index_action.py deleted file mode 100644 index 5f510f4..0000000 --- a/AjustaFundos/packages/v1/serventias/actions/v_pessoa_vinculo/v_pessoa_vinculo_index_action.py +++ /dev/null @@ -1,17 +0,0 @@ -from packages.v1.serventias.repositories.v_pessoa_vinculo.v_pessoa_vinculo_index_repository import ( - VPessoaVinculoIndexRepository, -) -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoIndexSchema, -) - - -class VPessoaVinculoIndexAction: - - def execute(self, v_pessoa_vinculo_index_schema: VPessoaVinculoIndexSchema): - - # Instânciamento de repositório - v_pessoa_vinculo_index_repository = VPessoaVinculoIndexRepository() - - # Retorna todos produtos - return v_pessoa_vinculo_index_repository.execute(v_pessoa_vinculo_index_schema) diff --git a/AjustaFundos/packages/v1/serventias/actions/v_pessoa_vinculo/v_pessoa_vinculo_save_action.py b/AjustaFundos/packages/v1/serventias/actions/v_pessoa_vinculo/v_pessoa_vinculo_save_action.py deleted file mode 100644 index ec2ced8..0000000 --- a/AjustaFundos/packages/v1/serventias/actions/v_pessoa_vinculo/v_pessoa_vinculo_save_action.py +++ /dev/null @@ -1,17 +0,0 @@ -from packages.v1.serventias.repositories.v_pessoa_vinculo.v_pessoa_vinculo_save_repository import ( - VPessoaVinculoSaveRepository, -) -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoSaveSchema, -) - - -class VPessoaVinculoSaveAction: - - def execute(self, v_pessoa_vinculo_save_schema: VPessoaVinculoSaveSchema): - - # Instânciamento de repositório - v_pessoa_vinculo_save_repository = VPessoaVinculoSaveRepository() - - # Retorna todos produtos - return v_pessoa_vinculo_save_repository.execute(v_pessoa_vinculo_save_schema) diff --git a/AjustaFundos/packages/v1/serventias/controllers/v_casamento_controller.py b/AjustaFundos/packages/v1/serventias/controllers/v_casamento_controller.py deleted file mode 100644 index cca3791..0000000 --- a/AjustaFundos/packages/v1/serventias/controllers/v_casamento_controller.py +++ /dev/null @@ -1,14 +0,0 @@ -from packages.v1.serventias.services.v_casamento.go.v_casamento_antigo_index_service import ( - VCasamentosAntigosIndexService, -) - - -class VCasamentoController: - - def AntigosIndex(self): - - # Importação da classe desejad - antigos_index = VCasamentosAntigosIndexService() - - # Lista todos os produtos - return antigos_index.execute() diff --git a/AjustaFundos/packages/v1/serventias/controllers/v_pessoa_vinculo_controller.py b/AjustaFundos/packages/v1/serventias/controllers/v_pessoa_vinculo_controller.py deleted file mode 100644 index 0dbf765..0000000 --- a/AjustaFundos/packages/v1/serventias/controllers/v_pessoa_vinculo_controller.py +++ /dev/null @@ -1,23 +0,0 @@ -# Importação de bibliotecas -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoIndexSchema, -) -from packages.v1.serventias.services.v_pessoa_vinculo.go.v_pessoa_vinculo_index_service import ( - VPessoaVinculoIndexService, -) - - -class VPessoaVinculoController: - - def index(self, v_pessoa_vinculo_index_schema: VPessoaVinculoIndexSchema): - - # Importação da classe desejad - v_pessoa_vinculo_index_service = VPessoaVinculoIndexService() - - # Intânciamento da classe service - self.v_pessoa_vinculo_index_service = v_pessoa_vinculo_index_service - - # Lista todos os produtos - return self.v_pessoa_vinculo_index_service.execute( - v_pessoa_vinculo_index_schema - ) diff --git a/AjustaFundos/packages/v1/serventias/repositories/v_casamento/v_casamento_antigo_index_repository.py b/AjustaFundos/packages/v1/serventias/repositories/v_casamento/v_casamento_antigo_index_repository.py deleted file mode 100644 index edac989..0000000 --- a/AjustaFundos/packages/v1/serventias/repositories/v_casamento/v_casamento_antigo_index_repository.py +++ /dev/null @@ -1,52 +0,0 @@ -import sys -from abstracts.repository_firebird import BaseRepositoryFirebird - - -class VCasamentoAntigoIndexRepository(BaseRepositoryFirebird): - """ - Repositório para a operação de listagem de todos os registros - na tabela t_censec_qualidade. - """ - - def execute(self): - """ - Executa a consulta SQL para buscar todos os registros. - - Returns: - Uma lista de dicionários contendo os dados dos registros. - """ - # Montagem do SQL - sql = """ SELECT - VCA.CASAMENTO_ID, - VCA.NOIVO_CPF, - VCA.NOIVO_NOME_ATUAL, - VCA.NOIVO_NACIONALIDADE, - VCA.NOIVA_CPF, - VCA.NOIVA_NOME_ATUAL, - VCA.NOIVA_NACIONALIDADE, - VCA.LV_ANTIGO_NOIVO_NASCIMENTO, - VCA.LV_ANTIGO_NOIVO_MAE, - VCA.LV_ANTIGO_NOIVO_PAI, - VCA.LV_ANTIGO_NOIVA_NASCIMENTO, - VCA.LV_ANTIGO_NOIVA_PAI, - VCA.LV_ANTIGO_NOIVA_MAE, - VCA.LV_ANTIGO_NOIVO_NATURALIDADE, - VCA.LV_ANTIGO_NOIVA_NATURALIDADE - FROM V_CASAMENTO VCA - WHERE VCA.LV_ANTIGO_TEXTO_NOIVO IS NOT NULL - OR VCA.LV_ANTIGO_TEXTO_NOIVA IS NOT NULL - OR VCA.LV_ANTIGO_NOIVO_NASCIMENTO IS NOT NULL - OR VCA.LV_ANTIGO_NOIVO_MAE IS NOT NULL - OR VCA.LV_ANTIGO_NOIVO_PAI IS NOT NULL - OR VCA.LV_ANTIGO_NOIVA_NASCIMENTO IS NOT NULL - OR VCA.LV_ANTIGO_NOIVA_PAI IS NOT NULL - OR VCA.LV_ANTIGO_NOIVA_MAE IS NOT NULL - OR VCA.LV_ANTIGO_NOIVO_NATURALIDADE IS NOT NULL - OR VCA.LV_ANTIGO_NOIVA_NATURALIDADE IS NOT NULL - ORDER BY CASAMENTO_ID ASC""" - - # Execução do sql - response = self.fetch_all(sql) - - # Retorna os dados localizados - return response diff --git a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa/v_pessoa_index_repository.py b/AjustaFundos/packages/v1/serventias/repositories/v_pessoa/v_pessoa_index_repository.py deleted file mode 100644 index d4e1b4e..0000000 --- a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa/v_pessoa_index_repository.py +++ /dev/null @@ -1,29 +0,0 @@ -from abstracts.repository_firebird import BaseRepositoryFirebird -from packages.v1.serventias.schemas.v_pessoa_schema import VPessoaSearchSchema - - -class VPessoaIndexRepository(BaseRepositoryFirebird): - """ - Repositório para a operação de listagem de todos os registros - na tabela t_censec_qualidade. - """ - - def execute(self, v_pessoa_search: VPessoaSearchSchema): - """ - Executa a consulta SQL para buscar todos os registros. - - Returns: - Uma lista de dicionários contendo os dados dos registros. - """ - # Montagem do SQL - sql = """ SELECT FIRST 1 * FROM V_PESSOA WHERE NOME LIKE :nome""" - - params = { - "nome": v_pessoa_search.nome, - } - - # Execução do sql - response = self.fetch_one(sql, params) - - # Retorna os dados localizados - return response diff --git a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa/v_pessoa_save_repository.py b/AjustaFundos/packages/v1/serventias/repositories/v_pessoa/v_pessoa_save_repository.py deleted file mode 100644 index e4a9334..0000000 --- a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa/v_pessoa_save_repository.py +++ /dev/null @@ -1,27 +0,0 @@ -from abstracts.repository_firebird import BaseRepositoryFirebird -from actions.data.generate_insert_sql import generate_insert_sql -from packages.v1.serventias.schemas.v_pessoa_schema import VPessoaSaveSchema - - -class VPessoaSaveRepository(BaseRepositoryFirebird): - """ - Repositório para a operação de listagem de todos os registros - na tabela t_censec_qualidade. - """ - - def execute(self, v_pessoa_save_schema: VPessoaSaveSchema): - - # ---------------------------------------------------- - # Preenchimento dos parâmetros - # ---------------------------------------------------- - params = v_pessoa_save_schema.model_dump(exclude_unset=True) - - # ---------------------------------------------------- - # Montagem do SQL dinâmico - # ---------------------------------------------------- - sql = generate_insert_sql("V_PESSOA", params) - - # ---------------------------------------------------- - # Execução do SQL e retorno do registro - # ---------------------------------------------------- - return self.run_and_return(sql, params) diff --git a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa_vinculo/v_pessoa_vinculo_index_repository.py b/AjustaFundos/packages/v1/serventias/repositories/v_pessoa_vinculo/v_pessoa_vinculo_index_repository.py deleted file mode 100644 index 6897e5e..0000000 --- a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa_vinculo/v_pessoa_vinculo_index_repository.py +++ /dev/null @@ -1,38 +0,0 @@ -from abstracts.repository_firebird import BaseRepositoryFirebird -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoIndexSchema, -) - - -class VPessoaVinculoIndexRepository(BaseRepositoryFirebird): - """ - Repositório para a operação de listagem de todos os registros - na tabela t_censec_qualidade. - """ - - def execute(self, v_pessoa_vinculo_index_schema: VPessoaVinculoIndexSchema): - """ - Executa a consulta SQL para buscar todos os registros. - - Returns: - Uma lista de dicionários contendo os dados dos registros. - """ - # Montagem do SQL - sql = """ - SELECT - VPV.PESSOA_VINCULO_ID - FROM V_PESSOA_VINCULO VPV - WHERE VPV.REGISTRO_ID = :registro_id - AND VPV.LIVRO_NATUREZA_ID = :livro_natureza_id - """ - - params = { - "registro_id": v_pessoa_vinculo_index_schema.registro_id, - "livro_natureza_id": v_pessoa_vinculo_index_schema.livro_natureza_id, - } - - # Execução do sql - response = self.fetch_all(sql, params) - - # Retorna os dados localizados - return response diff --git a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa_vinculo/v_pessoa_vinculo_save_repository.py b/AjustaFundos/packages/v1/serventias/repositories/v_pessoa_vinculo/v_pessoa_vinculo_save_repository.py deleted file mode 100644 index 8b23788..0000000 --- a/AjustaFundos/packages/v1/serventias/repositories/v_pessoa_vinculo/v_pessoa_vinculo_save_repository.py +++ /dev/null @@ -1,30 +0,0 @@ -from abstracts.repository_firebird import BaseRepositoryFirebird -from actions.data.generate_insert_sql import generate_insert_sql -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoIndexSchema, - VPessoaVinculoSaveSchema, -) - - -class VPessoaVinculoSaveRepository(BaseRepositoryFirebird): - """ - Repositório para a operação de listagem de todos os registros - na tabela t_censec_qualidade. - """ - - def execute(self, v_pessoa_vinculo_index_schema: VPessoaVinculoSaveSchema): - - # ---------------------------------------------------- - # Preenchimento dos parâmetros - # ---------------------------------------------------- - params = v_pessoa_vinculo_index_schema.model_dump(exclude_unset=True) - - # ---------------------------------------------------- - # Montagem do SQL dinâmico - # ---------------------------------------------------- - sql = generate_insert_sql("V_PESSOA_VINCULO", params) - - # ---------------------------------------------------- - # Execução do SQL e retorno do registro - # ---------------------------------------------------- - return self.run_and_return(sql, params) diff --git a/AjustaFundos/packages/v1/serventias/schemas/__init__.py b/AjustaFundos/packages/v1/serventias/schemas/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/AjustaFundos/packages/v1/serventias/schemas/v_casamento_schema.py b/AjustaFundos/packages/v1/serventias/schemas/v_casamento_schema.py deleted file mode 100644 index c758531..0000000 --- a/AjustaFundos/packages/v1/serventias/schemas/v_casamento_schema.py +++ /dev/null @@ -1,22 +0,0 @@ -from pydantic import BaseModel - - -class VCasamentoIndex(BaseModel): - casamento_id: int - - class Config: - from_attributes = True - - -class VCasamento(BaseModel): - casamento_id: int - - class Config: - from_attributes = True - - -class ResponseVCasamento(BaseModel): - data: list[VCasamento] - - class Config: - from_attributes = True diff --git a/AjustaFundos/packages/v1/serventias/schemas/v_pessoa_schema.py b/AjustaFundos/packages/v1/serventias/schemas/v_pessoa_schema.py deleted file mode 100644 index 2e53d86..0000000 --- a/AjustaFundos/packages/v1/serventias/schemas/v_pessoa_schema.py +++ /dev/null @@ -1,89 +0,0 @@ -from datetime import date -from pydantic import BaseModel - - -class VPessoaSearchSchema(BaseModel): - - nome: str - - class Config: - from_attributes = True - - -class VPessoaSaveSchema(BaseModel): - pessoa_id: int | None = None # PK opcional (create/update) - - nome: str - sexo: str | None = None - data_nascimento: date | None = None - - nacionalidade: str | None = None - naturalidade: str | None = None - cpf_cnpj: str | None = None - - tb_profissao_id: int | None = None - tb_estadocivil_id: int | None = None - tb_documentotipo_id: int | None = None - - documento: str | None = None - endereco: str | None = None - numero_endereco: str | None = None - bairro: str | None = None - cidade: str | None = None - cep: str | None = None - uf: str | None = None - - telefone: str | None = None - ddd: str | None = None - email: str | None = None - - pessoa_tipo: int | None = None - cpf_terceiro: str | None = None - - nome_pai: str | None = None - nome_mae: str | None = None - nome_especial_pai: str | None = None - nome_especial_mae: str | None = None - - tempo_residencia: int | None = None - - naturalidade_cidade_id: int | None = None - uf_naturalidade: str | None = None - pais_nascimento: str | None = None - cidade_nat_id: int | None = None - cidade_res_id: int | None = None - - data_falecimento: date | None = None - pai_falecido: bool | None = None - mae_falecida: bool | None = None - - data_emissao_doc: date | None = None - uf_emissor_doc: str | None = None - serie_doc: str | None = None - orgao_emissor_id: int | None = None - - texto_irmaos_gemeos: str | None = None - grupo_sanguineo: str | None = None - data_validade: date | None = None - - zona_secao: str | None = None - cidade_emissao_id: int | None = None - - cert_cartorio_id: int | None = None - cert_cidade_id: int | None = None - cert_folha: str | None = None - cert_livro: str | None = None - cert_termo: str | None = None - cert_uf: str | None = None - cert_data: date | None = None - - pessoa_conjuge_cpf: str | None = None - pessoa_conjuge_id: int | None = None - pessoa_conjuge_nome: str | None = None - - tabela_origem: str | None = None - chave_pessoa_imp: str | None = None - ignorar_documentos: bool | None = None - - class Config: - from_attributes = True diff --git a/AjustaFundos/packages/v1/serventias/schemas/v_pessoa_vinculo_schema.py b/AjustaFundos/packages/v1/serventias/schemas/v_pessoa_vinculo_schema.py deleted file mode 100644 index 8a1bce8..0000000 --- a/AjustaFundos/packages/v1/serventias/schemas/v_pessoa_vinculo_schema.py +++ /dev/null @@ -1,67 +0,0 @@ -from datetime import date -from pydantic import BaseModel - - -class VPessoaVinculoIndexSchema(BaseModel): - registro_id: int - livro_natureza_id: int - - class Config: - from_attributes = True - - -class VPessoaVinculo(BaseModel): - pessoa_vinculo_id: int - livro_natureza_id: int - registro_id: str - nome: str - cpf_cnpj: str - telefone: str - - class Config: - from_attributes = True - - -class ResponseVPessoaVinculo(BaseModel): - data: list[VPessoaVinculo] - - class Config: - from_attributes = True - - -class VPessoaVinculoSaveSchema(BaseModel): - pessoa_vinculo_id: int | None = None # PK opcional (create/update) - - nome: str - tb_estadocivil_id: int | None = None - tb_profissao_id: int | None = None - pessoa_id: int | None = None - falecido: bool | None = None - - tipo_cadastro_familia: int | None = None - livro_natureza_id: int - registro_id: int # ajuste para str se o seu modelo/trilha usar string - tipo_cadastro_geral: int | None = None - - cidade_residencia: str | None = None - idade: int | None = None - auxiliar: bool | None = None - ordem: int | None = None - tb_partelivroe_id: int | None = None - - declarante: bool | None = None - nome_especial: str | None = None - - cert_data: date | None = None - cert_folha: str | None = None - cert_livro: str | None = None - cert_termo: str | None = None - cert_uf: str | None = None - - chave_importacao: str | None = None - tabela_vinculo: str | None = None - abandonador_pessoa_id: int | None = None - assinatura: bool | None = None - - class Config: - from_attributes = True diff --git a/AjustaFundos/packages/v1/serventias/services/v_casamento/go/v_casamento_antigo_index_service.py b/AjustaFundos/packages/v1/serventias/services/v_casamento/go/v_casamento_antigo_index_service.py deleted file mode 100644 index 836c2d9..0000000 --- a/AjustaFundos/packages/v1/serventias/services/v_casamento/go/v_casamento_antigo_index_service.py +++ /dev/null @@ -1,31 +0,0 @@ -from packages.v1.serventias.actions.v_casamento.v_casamento_antigo_index_action import ( - VCasamentoAntigosIndexAction, -) - - -class VCasamentosAntigosIndexService: - """ - 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 - # ---------------------------------------------------- - antigos_index = VCasamentoAntigosIndexAction() - - # ---------------------------------------------------- - # Retorno da informação - # ---------------------------------------------------- - return antigos_index.execute() diff --git a/AjustaFundos/packages/v1/serventias/services/v_pessoa/go/v_pessoa_index_service.py b/AjustaFundos/packages/v1/serventias/services/v_pessoa/go/v_pessoa_index_service.py deleted file mode 100644 index 3623ae6..0000000 --- a/AjustaFundos/packages/v1/serventias/services/v_pessoa/go/v_pessoa_index_service.py +++ /dev/null @@ -1,43 +0,0 @@ -from packages.v1.serventias.actions.v_pessoa.v_pessoa_index_action import ( - VPessoaIndexAction, -) -from packages.v1.serventias.actions.v_pessoa_vinculo.v_pessoa_vinculo_index_action import ( - VPessoaVinculoIndexAction, -) -from packages.v1.serventias.schemas.v_pessoa_schema import VPessoaSearchSchema -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoIndexSchema, -) - - -class VPessoaIndexService: - """ - 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, v_pessoa_search: VPessoaSearchSchema): - """ - 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 - # ---------------------------------------------------- - v_pessoa_index_action = VPessoaIndexAction() - - # ---------------------------------------------------- - # Execução da ação - # ---------------------------------------------------- - data = v_pessoa_index_action.execute(v_pessoa_search) - - # ---------------------------------------------------- - # Retorno da informação - # ---------------------------------------------------- - return data diff --git a/AjustaFundos/packages/v1/serventias/services/v_pessoa/go/v_pessoa_save_service.py b/AjustaFundos/packages/v1/serventias/services/v_pessoa/go/v_pessoa_save_service.py deleted file mode 100644 index 7d7f2db..0000000 --- a/AjustaFundos/packages/v1/serventias/services/v_pessoa/go/v_pessoa_save_service.py +++ /dev/null @@ -1,37 +0,0 @@ -from packages.v1.serventias.actions.v_pessoa.v_pessoa_save_action import ( - VPessoaSaveAction, -) -from packages.v1.serventias.schemas.v_pessoa_schema import VPessoaSaveSchema - - -class VPessoaSaveService: - """ - 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, v_pessoa_save_schema: VPessoaSaveSchema): - """ - 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 - # ---------------------------------------------------- - v_pessoa_save = VPessoaSaveAction() - - # ---------------------------------------------------- - # Execução da ação - # ---------------------------------------------------- - data = v_pessoa_save.execute(v_pessoa_save_schema) - - # ---------------------------------------------------- - # Retorno da informação - # ---------------------------------------------------- - return data diff --git a/AjustaFundos/packages/v1/serventias/services/v_pessoa_vinculo/go/v_pessoa_vinculo_index_service.py b/AjustaFundos/packages/v1/serventias/services/v_pessoa_vinculo/go/v_pessoa_vinculo_index_service.py deleted file mode 100644 index a0f1288..0000000 --- a/AjustaFundos/packages/v1/serventias/services/v_pessoa_vinculo/go/v_pessoa_vinculo_index_service.py +++ /dev/null @@ -1,39 +0,0 @@ -from packages.v1.serventias.actions.v_pessoa_vinculo.v_pessoa_vinculo_index_action import ( - VPessoaVinculoIndexAction, -) -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoIndexSchema, -) - - -class VPessoaVinculoIndexService: - """ - 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, v_pessoa_vinculo_index_schema: VPessoaVinculoIndexSchema): - """ - 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 - # ---------------------------------------------------- - v_pessoa_vinculo_index_action = VPessoaVinculoIndexAction() - - # ---------------------------------------------------- - # Execução da ação - # ---------------------------------------------------- - data = v_pessoa_vinculo_index_action.execute(v_pessoa_vinculo_index_schema) - - # ---------------------------------------------------- - # Retorno da informação - # ---------------------------------------------------- - return data diff --git a/AjustaFundos/packages/v1/serventias/services/v_pessoa_vinculo/go/v_pessoa_vinculo_save_service.py b/AjustaFundos/packages/v1/serventias/services/v_pessoa_vinculo/go/v_pessoa_vinculo_save_service.py deleted file mode 100644 index b2915cc..0000000 --- a/AjustaFundos/packages/v1/serventias/services/v_pessoa_vinculo/go/v_pessoa_vinculo_save_service.py +++ /dev/null @@ -1,39 +0,0 @@ -from packages.v1.serventias.actions.v_pessoa_vinculo.v_pessoa_vinculo_save_action import ( - VPessoaVinculoSaveAction, -) -from packages.v1.serventias.schemas.v_pessoa_vinculo_schema import ( - VPessoaVinculoSaveSchema, -) - - -class VPessoaVInculoSaveService: - """ - 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, v_pessoa_vinculo_save_schema: VPessoaVinculoSaveSchema): - """ - 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 - # ---------------------------------------------------- - v_pessoa_vinculo_index_action = VPessoaVinculoSaveAction() - - # ---------------------------------------------------- - # Execução da ação - # ---------------------------------------------------- - data = v_pessoa_vinculo_index_action.execute(v_pessoa_vinculo_save_schema) - - # ---------------------------------------------------- - # Retorno da informação - # ---------------------------------------------------- - return data diff --git a/AjustaFundos/python_limpa_cache.bat b/AjustaFundos/python_limpa_cache.bat deleted file mode 100644 index c43fde9..0000000 --- a/AjustaFundos/python_limpa_cache.bat +++ /dev/null @@ -1,90 +0,0 @@ -@echo off -setlocal EnableExtensions EnableDelayedExpansion - -:: ===== Configuração/ajuda ===== -if /I "%~1"=="-h" goto :help -if /I "%~1"=="/h" goto :help -if /I "%~1"=="--help" goto :help - -:: Pasta raiz = 1º argumento ou pasta atual -set "ROOT=%~1" -if not defined ROOT set "ROOT=%cd%" - -:: Checa flag /dry-run em qualquer argumento -set "DRYRUN=" -for %%A in (%*) do ( - if /I "%%~A"=="/dry-run" set "DRYRUN=1" -) - -:: Normaliza ROOT removendo aspas extras -for %%# in ("%ROOT%") do set "ROOT=%%~f#" - -if not exist "%ROOT%" ( - echo [ERRO] Pasta nao encontrada: "%ROOT%" - exit /b 1 -) - -:: ===== Timestamp e log ===== -set "TS=%date%_%time%" -set "TS=%TS:/=%" -set "TS=%TS::=%" -set "TS=%TS:.=%" -set "TS=%TS:,=%" -set "TS=%TS: =0%" -set "LOG=%ROOT%\cleanup_pycache_%TS%.log" - -echo ================================================== > "%LOG%" -echo Limpeza de __pycache__ >> "%LOG%" -echo Pasta raiz: "%ROOT%" >> "%LOG%" -if defined DRYRUN (echo Modo: DRY-RUN (apenas listar) >> "%LOG%") else (echo Modo: EXECUTANDO REMOCOES >> "%LOG%") -echo Iniciado: %date% %time% >> "%LOG%" -echo ================================================== >> "%LOG%" - -set /a FOUND=0, OK=0, ERR=0 - -:: ===== Procura e (opcionalmente) remove ===== -for /d /r "%ROOT%" %%D in (__pycache__) do ( - set /a FOUND+=1 - if defined DRYRUN ( - echo [LISTAR] "%%~fD" - >>"%LOG%" echo [LISTAR] "%%~fD" - ) else ( - echo [APAGAR] "%%~fD" - rd /s /q "%%~fD" 1>nul 2>nul - if exist "%%~fD" ( - set /a ERR+=1 - >>"%LOG%" echo [FALHA] "%%~fD" - ) else ( - set /a OK+=1 - >>"%LOG%" echo [OK] "%%~fD" - ) - ) -) - -echo.>>"%LOG%" -echo Pastas encontradas: %FOUND% >> "%LOG%" -echo Removidas com sucesso: %OK% >> "%LOG%" -echo Falhas: %ERR% >> "%LOG%" -echo Finalizado: %date% %time% >> "%LOG%" - -:: ===== Resumo no console ===== -echo. -echo ===== RESUMO ===== -echo Pasta raiz: "%ROOT%" -if defined DRYRUN (echo Modo: DRY-RUN ^(nao removeu nada^)) -echo Pastas encontradas: %FOUND% -if not defined DRYRUN ( - echo Removidas com sucesso: %OK% - echo Falhas: %ERR% -) -echo Log salvo em: "%LOG%" -exit /b 0 - -:help -echo Uso: -echo cleanup_pycache.bat [PASTA_RAIZ] [/dry-run] -echo. -echo Ex.: cleanup_pycache.bat "D:\Projetos\MeuApp" -echo Ex.: cleanup_pycache.bat /dry-run -echo Ex.: cleanup_pycache.bat "D:\Repos" /dry-run -exit /b 0 diff --git a/AjustaFundos/requirements.txt b/AjustaFundos/requirements.txt deleted file mode 100644 index 8a543fd..0000000 --- a/AjustaFundos/requirements.txt +++ /dev/null @@ -1,62 +0,0 @@ -altgraph==0.17.4 -annotated-types==0.7.0 -anyio==4.10.0 -beautifulsoup4==4.14.2 -certifi==2025.10.5 -cffi==1.17.1 -charset-normalizer==3.4.4 -click==8.2.1 -colorama==0.4.6 -dnspython==2.7.0 -ecdsa==0.19.1 -email_validator==2.2.0 -fastapi==0.116.1 -firebird-base==2.0.2 -firebird-driver==2.0.2 -greenlet==3.2.4 -h11==0.16.0 -html2text==2025.4.15 -httpcore==1.0.9 -httpx==0.28.1 -idna==3.10 -lxml==6.0.2 -markdown-it-py==4.0.0 -mdurl==0.1.2 -packaging==25.0 -passlib==1.7.4 -pefile==2023.2.7 -pillow==12.0.0 -protobuf==5.29.5 -pyasn1==0.6.1 -pycparser==2.22 -pycurl==7.45.7 -pydantic==2.11.7 -pydantic_core==2.33.2 -Pygments==2.19.2 -pyinstaller==6.16.0 -pyinstaller-hooks-contrib==2025.9 -pypandoc==1.15 -pypandoc_binary==1.15 -pypdf==6.2.0 -PyPDF2==3.0.1 -python-dateutil==2.9.0.post0 -python-jose==3.5.0 -pytz==2025.2 -pywin32-ctypes==0.2.3 -reportlab==4.4.4 -rich==14.2.0 -rsa==4.9.1 -ruff==0.14.5 -setuptools==80.9.0 -six==1.17.0 -sniffio==1.3.1 -soupsieve==2.8 -SQLAlchemy==2.0.42 -sqlalchemy-firebird==2.1 -starlette==0.47.2 -striprtf==0.0.29 -typing-inspection==0.4.1 -typing_extensions==4.14.1 -uvicorn==0.35.0 -watchdog==6.0.0 -wptools==0.4.17