Compare commits

..

86 commits
QA-01 ... main

Author SHA1 Message Date
Kenio
09e8901e8c Merge branch 'main' of https://git.oriustecnologia.com/kenio/saas 2025-12-30 16:22:47 -03:00
Kenio
cae68daa70 feat(): Criado endpoint SEE/SESSIONS - Autenticação do cartório 2025-12-30 16:21:09 -03:00
Keven
b173bffcf1 feat(OnlyOffice): Ajusta o Processador de Documentos 2025-12-30 12:49:17 -03:00
Keven
63f0a81970 feat(OnlyOffice): Ajusta para trabalhar com rtf 2025-12-29 17:13:48 -03:00
Keven
659ec645a2 feat(OnlyOffice): Ajusta para trabalhar com rtf 2025-12-29 17:13:18 -03:00
Keven
ae1cbca20c feat(Readem): Atualiza o readme 2025-12-29 16:19:46 -03:00
Keven
2ce6843178 Merge branch 'main' of https://git.oriustecnologia.com/OriusTecnologia/saas_api 2025-12-26 15:51:33 -03:00
Keven
1e34ce9e9a feat(OnlyOffice): Ajustes diversos no editor de texto 2025-12-26 15:51:31 -03:00
d2954b6691 Debug 2025-12-23 11:46:37 -03:00
70b7757b5a Debug 2025-12-23 11:35:32 -03:00
ee4e4e77cd Debug 2025-12-23 11:27:27 -03:00
Keven
6ccf74e687 fix(0933): Ajuste do dockerfile 2025-12-23 09:33:31 -03:00
Keven
bd8f433846 fix(0929): Ajuste do dockerfile 2025-12-23 09:29:51 -03:00
Keven
007c0fb6a5 fix(0920): Ajuste do dockerfile 2025-12-23 09:20:56 -03:00
Keven
26f94c66ae fix(0919): Ajuste do dockerfile 2025-12-23 09:19:39 -03:00
Keven
a62ffde0de fix(requirements): Ajuste do freeze 2025-12-23 09:10:26 -03:00
Keven
a6c88e5056 feat(Certidao): Adiciona recursos para manipular certidões 2025-12-22 18:03:46 -03:00
Keven
433d889060 feat(ServiceFactory): Criação de importação de classes de forma dinâmica mais otimizada 2025-12-17 09:56:19 -03:00
Keven
2223db9d75 feat(TAto): Implementação inicial da listagem dos dados 2025-12-17 09:38:14 -03:00
Keven
9b784f8d1a feat(): Ajustes nos detalhes do pedido de Balcão 2025-12-16 15:06:47 -03:00
Keven
25d904b0bb 1610 2025-12-09 16:10:46 -03:00
Keven
c9c0741ecc deploy(Dockerfile): Ajusta o dockerfile para deploy 2025-12-09 09:46:37 -03:00
Keven
910f08b0a6 deploy(Dockerfile): Ajusta o dockerfile para deploy 2025-12-09 09:43:21 -03:00
Keven
8d444c968e deploy(Dockerfile): Ajusta o dockerfile para deploy 2025-12-09 09:40:36 -03:00
Keven
ea1c830010 fix(TServicoPEdido): Ajustes diversos 2025-12-08 17:40:56 -03:00
Keven
3b1654bf2c fix(Ruff): Ajuste automático do código 2025-12-08 16:35:00 -03:00
Keven
09948e158c feat(Env): Ajusta a conexão do firebird para variavel de ambiente - 15:40 2025-12-08 15:40:40 -03:00
Keven
5d5e8eb755 feat(Env): Ajusta a conexão do firebird para variavel de ambiente - 15:36 2025-12-08 15:36:59 -03:00
Keven
c7cfb05b4d feat(Env): Ajusta a conexão do firebird para variavel de ambiente 2025-12-08 15:30:23 -03:00
Keven
9970c3700f feat(Env): Ajusta a conexão do firebird para variavel de ambiente 2025-12-08 15:23:34 -03:00
Keven
e62cb2ab5c fix(Config): Ajusta o caminho do condig 2025-12-08 14:47:32 -03:00
Keven
698aa5633f fix(Config): Ajusta o caminho do condig 2025-12-08 14:46:26 -03:00
Keven
f539ac266c fix(Config): Ajusta o caminho do condig 2025-12-08 14:33:46 -03:00
Keven
32f18d1f33 fix(Config): Ajusta o caminho do condig 2025-12-08 14:26:58 -03:00
Keven
83f14cd442 12:56 2025-12-08 12:56:47 -03:00
Keven
b5505d1162 12:50 2025-12-08 12:51:01 -03:00
Keven
6bb4c10eb0 deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 12:47:53 -03:00
Keven
205a20b3ce deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 12:37:27 -03:00
Keven
6673e778af deploy(Dockerfile): Ajusta o dockerfile para produção 2025-12-08 12:10:01 -03:00
Keven
ffdda4f022 fix(Deploy): Ajustes diversos para deploy 2025-12-08 12:03:56 -03:00
Keven
c315185cd5 docs(Readme): Adiciona configurações de servidor em produção 2025-12-08 10:51:08 -03:00
Keven
8258ee97c3 Merge branch 'release(MVP/Sprint11)' 2025-12-08 10:44:44 -03:00
Keven
98a2087136 Merge remote-tracking branch 'origin/DSAAS-18' into release(DSAAS) 2025-12-08 10:41:52 -03:00
Keven
2dc535c0f9 [MVPTN-126] feat(Pedido): Cria endpoints e recursos para estornar e ativar um pedido 2025-12-05 16:03:05 -03:00
Keven
571e59bfb8 [MVPTN-126] feat(Pedido): Cria endpoints e recursos para estornar e ativar um item do pedido 2025-12-05 11:09:22 -03:00
Keven
6d8468a4e2 [MVPTN-126] feat(): Endpoint de cancelamento de itempedido 2025-12-04 18:00:42 -03:00
Keven
7e31386acd feat(ItemPedido): Altera a situação do item pedido 2025-12-03 18:02:42 -03:00
Keven
8d7cdac663 [MVPTN-37] feat(Pesquisa): Adiciona query params nas conultas sqls 2025-12-02 18:23:53 -03:00
Keven
c3b087808e [MVPTN-126] feta(Pedido): Implementa a solicitação de pedidos no balcão do tabelionato 2025-11-15 12:31:00 -03:00
Keven
42d76991b0 [MVPTN-126] fix(Importação): Corrige a importação de pacotes 2025-11-10 18:20:24 -03:00
Keven
4485488ef4 [MVPTN-126] feat(SQL): Ajusta o sql de retorno dos dados do item 2025-11-09 19:02:45 -03:00
Keven
f836daa07c [MVPTN-126] feat(Item): Adiciona o processamento de itens enviados através do pedido 2025-11-08 20:35:02 -03:00
Keven
0339cffc21 [MVPTN-126] fix(Dev): Ajusta os locais de importação de arquivos 2025-11-06 17:31:49 -03:00
125c654439 backup: Backup de código 2025-11-04 08:16:05 -03:00
11c43f22e4 fix(Merge): Corrige erro de conflito de merge 2025-10-30 16:07:47 -03:00
e871333992 Merge remote-tracking branch 'origin/release(MVP/Sprint6)' into MVPTN-126 2025-10-30 16:06:55 -03:00
12d39c4f87 [MVPTN-126] feat(CRUD): Implementa o crud de TServicoPEdido e TServicoItemPedido 2025-10-30 16:00:08 -03:00
b85557194b [MVPTN-34] feat(Calculo): Implementa Busca de parametros, pesquisa em faixa de valores e o calculo rápido 2025-10-28 18:10:28 -03:00
9ab315d273 Merge branch 'MVPTN-106' into release(MVP/Sprint6) 2025-10-28 15:47:33 -03:00
808bc15664 [MVPTN-106] feat(crud): Implementação de gerenciamento de etiqueta para o formulário Tipos de Serviço 2025-10-28 15:42:04 -03:00
0664786243 Merge branch 'MVPTN-123' into MVPTN-34 2025-10-27 17:43:20 -03:00
c12e4c6628 [MVPTN-34] feat(Calculo): Implementa parcialmente o calculo rapido 2025-10-27 17:41:37 -03:00
50aa6640a8 feat(Charts): Montado as consultas sqls para popular os gráficos 2025-10-27 15:29:11 -03:00
48a5bebff7 [MVPTN-123] feta(CRUD): Implementa o CRUD necessário para manipular a tabela GEmolumentoItem 2025-10-24 17:14:08 -03:00
59f462c7bd [MVPTN-32] feat(CRUD): Cria cruds para manipular GEmolumento e GSeloGrupo 2025-10-24 10:52:55 -03:00
252427ae0e [MVPTN-35] feat(CRUD): Cria o CRUD de Gerenciamento de PEriodos de Emolumento 2025-10-22 14:58:43 -03:00
890493639f [MVPTN-31] feat(CRUD): Cria o CRUD de cadastor de Cartório 2025-10-21 12:06:05 -03:00
d3a76b8106 [MVPTN-29] feat(CRUD): Criar o CRUD de Gramatica 2025-10-20 15:41:19 -03:00
76ecc4a4af [MVPTN-108] feat(Crud): Cria o CRUD para manipular a natureza do titulo 2025-10-20 12:34:29 -03:00
87d720629f [MVPTN-106] feat(Schema): Ajustado Schema para que apenas o campo descrição seja obrigatório 2025-10-20 09:13:58 -03:00
b93bf19bca fix(SQL): Ajuste o sql de retornar as cidades 2025-10-18 12:22:44 -03:00
a61ea6d33d [MVPTN-106] feat(c_caixa_servico): Adicionado endpint que retorna c_caixa_servico pelo sistema_id 2025-10-17 18:17:27 -03:00
8ac311e09b [MVPTN-121] feat(CRUD): Cria o Crud de Vincular as qualidades ao ato 2025-10-17 09:04:07 -03:00
241a7fdea2 [MVPTN-26] feat(CRUD): Cria o CRUD de T_CENSEC_TIPONATUREZA 2025-10-16 12:53:48 -03:00
348cc3169d [MVPTN-106] feat(GET): Criado endpointo que retorna todos os itens de emolumentos de um emolumento a partir do emolumento_id e adicionado endpoint que retorna item de emolumento a partir do emolumento_id e faixa de valor informados 2025-10-16 10:26:31 -03:00
440de7727c [MVPTN-25] feat(CRUD): Criar o CRUD de T_ATO_PARTETIPO 2025-10-15 15:36:52 -03:00
7d7aaf24b8 [MVPTN-106] feat(get): Feito o GET da tabela g_emolumento por sistema_id 2025-10-14 15:28:37 -03:00
17a1146f04 [MVPTN-103] fix(SQL): Ajusta a listagem por SISTEMA_ID 2025-10-14 08:06:04 -03:00
642f2ed826 feat(CRUD): Adiciona os endpoints para vinculadar qualidades ao ato 2025-10-13 15:24:01 -03:00
ebeb5e4827 [MVPTN-106] feat(Endpoint): Criado o novo endpoint para retornar g_marcacao_tipo com aplicação de filtro 2025-10-13 13:26:38 -03:00
88fd24c6b8 fix(Update): Ajusta a maneira de realizar o update 2025-10-13 10:43:53 -03:00
349350b03e Merge branch 'QA-01' into release(MVP/Sprint6) 2025-10-13 10:31:10 -03:00
b6cb92d2c1 [MVPTN-100] fix(CRUD): Ajustes diversos no CRUD de Imóveis e Unidades dos Imóveis 2025-10-10 18:05:28 -03:00
765d36a5f6 [MVPTN] feat(CRUD): Finalização do CRUD De pessoas Fisicas e Jurídicas 2025-10-10 13:55:56 -03:00
355dda6f53 [MVPTN-100] fix(Diversos): Ajustes diversos 2025-10-09 16:20:10 -03:00
2f1461d1e0 [MVPTN-100] feat(CRUD): Implementa endpoints para maniputar T_PEssoa_Representante 2025-10-08 18:20:54 -03:00
978 changed files with 27151 additions and 8314 deletions

View file

@ -1,13 +1,9 @@
# Usa a imagem oficial do Python
FROM python:3.12-slim FROM python:3.12-slim
# Define diretório de trabalho no container
WORKDIR /app WORKDIR /app
# Copia o arquivo de dependências
COPY requirements.txt . COPY requirements.txt .
# Instala dependências no sistema e no Python
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
gcc libffi-dev libssl-dev python3-dev firebird-dev \ gcc libffi-dev libssl-dev python3-dev firebird-dev \
&& pip install --upgrade pip \ && pip install --upgrade pip \
@ -16,11 +12,13 @@ RUN apt-get update && apt-get install -y \
&& apt-get autoremove -y \ && apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Copia o restante do projeto para o container # ===============================
# CRIA DIRETÓRIOS NECESSÁRIOS
# ===============================
RUN mkdir -p storage/temp
COPY . . COPY . .
# Expõe a porta padrão do Uvicorn/FastAPI
EXPOSE 8000 EXPOSE 8000
# Comando para iniciar o servidor CMD ["gunicorn", "main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]
CMD ["sh", "-c", "uvicorn main:app --host 0.0.0.0 --port 8000"]

View file

@ -70,7 +70,7 @@
"header": [], "header": [],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\r\n \"login\" : \"Kenio0\",\r\n \"senha_api\": \"123123\"\r\n}", "raw": "{\r\n \"login\" : \"Kenio\",\r\n \"senha_api\": \"123123\"\r\n}",
"options": { "options": {
"raw": { "raw": {
"language": "json" "language": "json"
@ -8501,6 +8501,81 @@
}, },
"response": [] "response": []
}, },
{
"name": "GET GRUPO",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"Status code é 201 ou 200\", function () {\r",
" pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r",
"});\r",
"\r",
"pm.test(\"Resposta contém ID ou confirmação\", function () {\r",
" const jsonData = pm.response.json();\r",
" pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r",
"});\r",
"\r",
"pm.test(\"Mensagem indica sucesso\", function () {\r",
" const jsonData = pm.response.json();\r",
" pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r",
"});\r",
""
],
"type": "text/javascript",
"packages": {},
"requests": {}
}
}
],
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{BearerToken}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "{{BaseUrlV1}}administrativo/g_marcacao_tipo/grupo?grupo=MODELO_ETIQUETA&sistema_id=2&situacao=A",
"host": [
"{{BaseUrlV1}}administrativo"
],
"path": [
"g_marcacao_tipo",
"grupo"
],
"query": [
{
"key": "grupo",
"value": "MODELO_ETIQUETA"
},
{
"key": "sistema_id",
"value": "2"
},
{
"key": "situacao",
"value": "A"
}
]
}
},
"response": []
},
{ {
"name": "GET ID", "name": "GET ID",
"event": [ "event": [
@ -8741,6 +8816,65 @@
} }
] ]
}, },
{
"name": "Emolumentos",
"item": [
{
"name": "GET",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"Status code é 201 ou 200\", function () {\r",
" pm.expect(pm.response.code).to.be.oneOf([200, 201]);\r",
"});\r",
"\r",
"pm.test(\"Resposta contém ID ou confirmação\", function () {\r",
" const jsonData = pm.response.json();\r",
" pm.expect(jsonData).to.have.any.keys(\"id\", \"message\", \"status\");\r",
"});\r",
"\r",
"pm.test(\"Mensagem indica sucesso\", function () {\r",
" const jsonData = pm.response.json();\r",
" pm.expect(jsonData.message || \"\").to.match(/sucesso|criado|registrado/i);\r",
"});\r",
""
],
"type": "text/javascript",
"packages": {},
"requests": {}
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{BearerToken}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{BaseUrlV1}}administrativo/g_emolumento/1",
"host": [
"{{BaseUrlV1}}administrativo"
],
"path": [
"g_emolumento",
"1"
]
}
},
"response": []
}
]
},
{ {
"name": "Andamento Serviço", "name": "Andamento Serviço",
"item": [ "item": [

258
README.md
View file

@ -1,12 +1,12 @@
# Configuração do Projeto Python # Configuração do Projeto Python
Este guia descreve o passo a passo para configurar o ambiente de desenvolvimento de um projeto Python, incluindo a preparação do ambiente virtual, instalação de dependências e configuração do banco de dados. Este guia descreve o passo a passo para configurar o ambiente de desenvolvimento e produção de um projeto Python, incluindo ambiente virtual, dependências, banco de dados, e ajuste de desempenho com múltiplos núcleos.
--- ---
## 1. Clonar o Projeto ## 1. Clonar o Projeto
Primeiro, clone o repositório do projeto a partir do Git: Clone o repositório do projeto a partir do Git:
```bash ```bash
git clone https://git.oriustecnologia.com/OriusTecnologia/saas_api.git git clone https://git.oriustecnologia.com/OriusTecnologia/saas_api.git
@ -16,7 +16,7 @@ git clone https://git.oriustecnologia.com/OriusTecnologia/saas_api.git
## 2. Criar o Ambiente Virtual ## 2. Criar o Ambiente Virtual
O uso de um **ambiente virtual** garante que as bibliotecas instaladas para este projeto não afetem o Python global da sua máquina. Crie um **ambiente virtual** isolado para o projeto:
```bash ```bash
python -m venv venv python -m venv venv
@ -26,14 +26,13 @@ python -m venv venv
## 3. Ativar o Ambiente Virtual ## 3. Ativar o Ambiente Virtual
Ative o ambiente virtual antes de instalar as dependências ou executar a aplicação. Ative o ambiente virtual antes de instalar as dependências:
```bash ```bash
venv\Scripts\activate venv\Scripts\activate
``` ```
> **Observação:** > **Em sistemas Linux/Mac:**
> Em sistemas Unix (Linux/Mac), o comando pode ser:
> >
> ```bash > ```bash
> source venv/bin/activate > source venv/bin/activate
@ -43,9 +42,11 @@ venv\Scripts\activate
## 4. Instalar Dependências do Sistema ## 4. Instalar Dependências do Sistema
A biblioteca de criptografia utilizada no projeto requer uma extensão da Microsoft para ser instalada. O projeto depende de compiladores nativos para algumas bibliotecas Python.
Baixe e instale o **Microsoft C++ Build Tools** através do link abaixo:
### Windows
Baixe e instale o **Microsoft C++ Build Tools**:
[https://visualstudio.microsoft.com/pt-br/visual-cpp-build-tools/](https://visualstudio.microsoft.com/pt-br/visual-cpp-build-tools/) [https://visualstudio.microsoft.com/pt-br/visual-cpp-build-tools/](https://visualstudio.microsoft.com/pt-br/visual-cpp-build-tools/)
Durante a instalação, selecione o pacote: Durante a instalação, selecione o pacote:
@ -54,6 +55,15 @@ Durante a instalação, selecione o pacote:
Desktop Development With C++ Desktop Development With C++
``` ```
### Linux
Execute no terminal:
```bash
sudo apt update
sudo apt install -y build-essential libpq-dev
```
--- ---
## 5. Instalar as Bibliotecas do Projeto ## 5. Instalar as Bibliotecas do Projeto
@ -66,77 +76,207 @@ pip install -r requirements.txt
--- ---
## 6. Configurar o Banco de Dados ## 6. Configuração do Banco de Dados (Firebird)
O projeto utiliza um banco **Firebird**. Crie o arquivo **`.env`** na raiz do projeto e configure as variáveis de ambiente necessárias para a conexão com o banco de dados Firebird:
Edite o arquivo de configuração localizado em:
``` ```env
api/config/database/firebird.json ORIUS_API_FDB_HOST=localhost
ORIUS_API_FDB_NAME=S:/Bases/SANTARITA.FDB
ORIUS_API_FDB_PORT=3050
ORIUS_API_FDB_USER=SYSDBA
ORIUS_API_FDB_PASSWORD=302b3c
ORIUS_API_FDB_CHARSET=UTF8
ORIUS_API_FDB_POOL_PRE_PING=true
ORIUS_API_FDB_POOL_SIZE=5
ORIUS_API_FDB_POOL_MAX_OVERFLOW=10
ORIUS_CLIENT_STATE=go
``` ```
Exemplo do conteúdo padrão: Essas configurações definem o acesso ao banco, o charset e o gerenciamento de conexões da aplicação.
```json
{
"host": "localhost",
"name": "D:/Orius/Base/CAIAPONIA.FDB",
"port": 3050,
"user": "SYSDBA",
"password": "",
"charset": "UTF8",
"pool": {
"pre_ping": true,
"size": 5,
"max_overflow": 10
}
}
```
### Ajustes Necessários:
* **host**: Endereço do servidor do banco de dados.
* **name**: Caminho completo do arquivo `.FDB`.
* **port**: Porta do Firebird (padrão: `3050`).
* **user**: Usuário do banco de dados.
* **password**: Senha do usuário configurado.
--- ---
## 7. Iniciar a Aplicação ## 7. Modo Desenvolvimento
Com o ambiente virtual **ativado**, execute o comando abaixo para iniciar a aplicação: Execute a aplicação em ambiente local:
```bash ```bash
uvicorn main:app --reload uvicorn main:app --reload
``` ```
> **Dica:** O modo `--reload` recarrega a aplicação automaticamente ao detectar alterações no código.
> O parâmetro `--reload` reinicia automaticamente a aplicação sempre que houver alterações no código.
--- Acesse a documentação da API em:
## 8. Testando a Aplicação ```
Após iniciar a aplicação, abra o navegador e acesse o seguinte endereço:
```http
http://localhost:8000/docs http://localhost:8000/docs
``` ```
Você deverá visualizar a interface do **Swagger**, onde estarão listados todos os endpoints disponíveis da API. Opcionalmente, para expor a aplicação na rede:
> **Observação:** ```bash
> O Swagger permite testar os endpoints diretamente pelo navegador, sem necessidade de ferramentas externas como Postman ou Insomnia. uvicorn main:app --host 0.0.0.0 --port 8000 --reload
```
--- ---
## Resumo dos Comandos ## 8. Modo Produção
| Etapa | Comando | A execução em produção varia conforme o sistema operacional.
| ----------------------- | ------------------------------------------------------------------------------- |
| Clonar o projeto | `git clone https://git.oriustecnologia.com/OriusTecnologia/saas_api.git` | ---
| Criar ambiente virtual | `python -m venv venv` |
| Ativar ambiente virtual | `venv\Scripts\activate` *(Windows)*<br>`source venv/bin/activate` *(Linux/Mac)* | ### **Windows (modo produção simulado)**
| Instalar dependências | `pip install -r requirements.txt` |
| Iniciar a aplicação | `uvicorn main:app --reload` | O **Gunicorn** não é compatível com Windows, pois depende do módulo `fcntl` exclusivo de sistemas Unix.
Portanto, em ambiente Windows, recomenda-se usar o **Uvicorn** diretamente com múltiplos _workers_:
```bash
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
```
> O parâmetro `--workers` define quantos processos simultâneos serão utilizados.
> Idealmente, use `(número_de_CPUs * 2) + 1`.
#### Alternativa compatível (Windows)
Instale e use o **Hypercorn**, uma alternativa semelhante ao Gunicorn:
```bash
pip install hypercorn
hypercorn main:app --workers 4 --bind 0.0.0.0:8000
```
---
### **Linux (modo produção real)**
Em ambientes Linux (ou Docker), utilize o **Gunicorn** com o **Uvicorn Worker** para obter o máximo desempenho.
#### Instalar Gunicorn (caso ainda não instalado)
```bash
pip install gunicorn uvicorn
```
#### Executar com múltiplos núcleos
```bash
gunicorn main:app \
-k uvicorn.workers.UvicornWorker \
--workers 4 \
--bind 0.0.0.0:8000 \
--timeout 120 \
--log-level info
```
#### Parâmetros principais
| Parâmetro | Função |
| ---------------------------------- | ---------------------------------------- |
| `-k uvicorn.workers.UvicornWorker` | Usa o Uvicorn como worker ASGI |
| `--workers 4` | Define o número de núcleos usados |
| `--bind 0.0.0.0:8000` | Expõe a aplicação em todas as interfaces |
| `--timeout 120` | Tempo limite de resposta (em segundos) |
| `--log-level info` | Define o nível de logs |
#### Dica de cálculo de workers
```
(número_de_CPUs * 2) + 1
```
Exemplo: servidor com 2 CPUs → `--workers 5`
---
### **Execução em segundo plano (Linux)**
Para rodar a aplicação continuamente:
```bash
nohup gunicorn main:app -k uvicorn.workers.UvicornWorker --workers 4 --bind 0.0.0.0:8000 &
```
Verifique se está rodando:
```bash
ps aux | grep gunicorn
```
---
## 9. Logs e Monitoramento
É possível direcionar os logs de acesso e erro para arquivos dedicados:
```bash
gunicorn main:app \
-k uvicorn.workers.UvicornWorker \
--workers 4 \
--bind 0.0.0.0:8000 \
--access-logfile logs/access.log \
--error-logfile logs/error.log
```
---
## 10. Estrutura Recomendada de Deploy
```
/app
├── main.py
├── api/
├── packages/
├── requirements.txt
├── logs/
│ ├── access.log
│ └── error.log
└── systemd/
└── saas_api.service
```
---
## 11. Resumo dos Comandos
| Etapa | Comando |
| --------------------------- | ------------------------------------------------------------------------------------ |
| Clonar projeto | `git clone https://git.oriustecnologia.com/OriusTecnologia/saas_api.git` |
| Criar venv | `python -m venv venv` |
| Ativar venv | `venv\Scripts\activate` _(Windows)_<br>`source venv/bin/activate` _(Linux/Mac)_ |
| Instalar dependências | `pip install -r requirements.txt` |
| Rodar em desenvolvimento | `uvicorn main:app --reload` |
| Rodar em produção (Windows) | `uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4` |
| Rodar em produção (Linux) | `gunicorn main:app -k uvicorn.workers.UvicornWorker --workers 4 --bind 0.0.0.0:8000` |
| Alternativa (Windows) | `hypercorn main:app --workers 4 --bind 0.0.0.0:8000` |
---
## 12. Recomendações Finais
- Em **Windows**, use Uvicorn ou Hypercorn apenas para testes e ambientes locais.
- Para **produção real**, use **Linux** com Gunicorn + Uvicorn Worker, idealmente em container **Docker**.
- Monitore o consumo de CPU/RAM e ajuste o número de _workers_ conforme o ambiente.
- Automatize o serviço em produção via **systemd** (ex: `/etc/systemd/system/saas_api.service`) para iniciar junto com o servidor.
---
uvicorn main:app --host 0.0.0.0 --port 8000
## 13. Configuração de acesso ao Firebird
1. Configurar o Firebird para aceitar conexões remotas:
Como o Firebird está "fora" do Docker, ele pode estar configurado para ouvir apenas em localhost. Para o Docker conseguir conectar, o Firebird precisa ouvir na interface de rede do Docker ou em todas as interfaces.
No arquivo firebird.conf (geralmente em /opt/firebird), verifique a linha: RemoteBindAddress =
Mude para: RemoteBindAddress = 0.0.0.0 (ou apenas para o IP 172.17.0.1).
Reinicie o serviço do Firebird.
2. Configurar as Variáveis no Easypanel:
Na aba Environment do seu serviço no Easypanel, configure sua conexão assim:
ORIUS_API_FDB_HOST=172.17.0.1

View file

@ -1,7 +1,8 @@
from abc import ABC, abstractmethod from abc import abstractmethod
class BaseAction: class BaseAction:
""" """
Classe abstrata base para todos as actions do sistema. Classe abstrata base para todos as actions do sistema.
Obriga implementação de um método execute(). Obriga implementação de um método execute().
@ -13,4 +14,4 @@ class BaseAction:
Método abstrato obrigatório a ser implementado pelas subclasses. Método abstrato obrigatório a ser implementado pelas subclasses.
Deve conter a lógica principal do repositório. Deve conter a lógica principal do repositório.
""" """
pass pass

View file

@ -1,49 +1,144 @@
from typing import Literal, Optional # Importa tipos utilitários para anotações estáticas e sobrecarga de assinaturas.
from typing import Any, Mapping, List, Optional, Literal, Union, overload
# Função `text` para construir SQL parametrizado de forma segura.
from sqlalchemy import text from sqlalchemy import text
# Tipo de retorno de execução bruta de SQL (cursor/result set) do SQLAlchemy.
from sqlalchemy.engine import CursorResult
# Exceção base do SQLAlchemy para capturar erros de banco.
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
# Provedor do engine de conexão com o Firebird, centralizado no projeto.
from database.firebird import Firebird from database.firebird import Firebird
# Define a classe base de repositórios, concentrando operações comuns de acesso a dados.
class BaseRepository: class BaseRepository:
def query(self, sql: str, params: Optional[dict] = None): # Sobrecarga 1: quando `fetch="all"`, o retorno é uma lista de mapeamentos (coluna->valor).
"""Executa uma consulta SQL e retorna o resultado como objeto ResultProxy""" @overload
return self._execute(sql, params, fetch="result") def _execute(
self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["all"]
) -> List[Mapping[str, Any]]: ...
def fetch_all(self, sql: str, params: Optional[dict] = None): # Sobrecarga 2: quando `fetch="one"`, o retorno é um único mapeamento ou None.
"""Executa uma consulta SQL e retorna todos os registros com mapeamento de colunas""" @overload
return self._execute(sql, params, fetch="all") def _execute(
self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["one"]
) -> Optional[Mapping[str, Any]]: ...
def fetch_one(self, sql: str, params: Optional[dict] = None): # Sobrecarga 3: quando `fetch="none"`, não há retorno (operações DML sem leitura).
"""Executa uma consulta SQL e retorna o primeiro registro com mapeamento de colunas""" @overload
return self._execute(sql, params, fetch="one") def _execute(
self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["none"]
) -> None: ...
def run(self, sql: str, params: Optional[dict] = None): # Sobrecarga 4: quando `fetch="result"`, retorna o objeto `CursorResult` bruto do SQLAlchemy.
"""Executa um SQL sem retorno de dados (ex: INSERT, UPDATE, DELETE)""" @overload
return self._execute(sql, params, fetch="none") def _execute(
self, sql: str, params: Optional[dict[str, Any]], fetch: Literal["result"]
) -> CursorResult[Any]: ...
def run_and_return(self, sql: str, params: Optional[dict] = None): # ===============================
"""Executa SQL com RETURNING e retorna o primeiro registro como dict""" # Helpers internos (BLOB)
return self._execute(sql, params, fetch="one") # ===============================
def _materialize_blob(self, value: Any) -> Any:
"""
Converte BLOBs do Firebird em bytes.
Retorna o valor original caso não seja BLOB.
"""
if value is None:
return None
if hasattr(value, "read") and callable(value.read):
try:
return value.read()
except Exception:
return None
return value
def _normalize_row(self, row: Mapping[str, Any]) -> dict[str, Any]:
"""
Converte RowMapping em dict mutável e materializa BLOBs.
"""
data = dict(row)
for key, value in data.items():
data[key] = self._materialize_blob(value)
return data
# Implementação concreta que atende às quatro sobrecargas por meio de um retorno em união.
def _execute( def _execute(
self, self,
sql: str, sql: str, # Comando SQL (SELECT/INSERT/UPDATE/DELETE) em texto.
params: Optional[dict] = None, params: Optional[dict[str, Any]] = None, # Parâmetros nomeados para o SQL.
fetch: Literal["all", "one", "result", "none"] = "result", fetch: Literal[
): "all", "one", "none", "result"
] = "result", # Modo de leitura/retorno.
) -> Union[
List[Mapping[str, Any]], # Retorno quando `fetch="all"`.
Optional[Mapping[str, Any]], # Retorno quando `fetch="one"`.
None, # Retorno quando `fetch="none"`.
CursorResult[Any], # Retorno quando `fetch="result"`.
]:
"""Método interno que executa o SQL conforme o modo de fetch especificado."""
# Obtém o engine de conexão com o Firebird a partir do provider central.
engine = Firebird.get_engine() engine = Firebird.get_engine()
try: try:
# Inicia um contexto transacional; `begin()` garante commit/rollback automáticos.
with engine.begin() as conn: with engine.begin() as conn:
# Executa o SQL com parâmetros (usa dict vazio quando `params` é None).
result = conn.execute(text(sql), params or {}) result = conn.execute(text(sql), params or {})
# Quando for solicitado "all", converte o resultado em lista de mapeamentos (coluna->valor).
if fetch == "all": if fetch == "all":
return result.mappings().all() return [self._normalize_row(row) for row in result.mappings().all()]
# Quando for solicitado "one", retorna apenas o primeiro registro (ou None).
elif fetch == "one": elif fetch == "one":
return result.mappings().first() row = result.mappings().first()
return self._normalize_row(row) if row else None
# Quando for solicitado "none", não retorna dados (apenas executa o comando).
elif fetch == "none": elif fetch == "none":
return None return None
return result # Result object # Caso padrão: retorna o objeto Result bruto para manipulações específicas.
return result
except SQLAlchemyError as e: except SQLAlchemyError as e:
# Log simples para facilitar diagnóstico em ambiente de desenvolvimento/produção.
print(f"[ERRO SQL]: {e}") print(f"[ERRO SQL]: {e}")
# Propaga a exceção para camadas superiores tratarem (ex.: FastAPI Exception Handler).
raise raise
# Executa uma consulta e retorna o objeto `CursorResult` bruto (uso avançado ou stream).
def query(
self, sql: str, params: Optional[dict[str, Any]] = None
) -> CursorResult[Any]:
"""Executa uma consulta SQL e retorna o resultado como objeto ResultProxy."""
return self._execute(sql, params, fetch="result")
# Executa uma consulta e retorna todos os registros como lista de mapeamentos.
def fetch_all(
self, sql: str, params: Optional[dict[str, Any]] = None
) -> List[Mapping[str, Any]]:
"""Executa uma consulta SQL e retorna todos os registros com mapeamento de colunas."""
return self._execute(sql, params, fetch="all")
# Executa uma consulta e retorna apenas o primeiro registro ou None.
def fetch_one(
self, sql: str, params: Optional[dict[str, Any]] = None
) -> Optional[Mapping[str, Any]]:
"""Executa uma consulta SQL e retorna o primeiro registro com mapeamento de colunas."""
return self._execute(sql, params, fetch="one")
# Executa comandos DML (INSERT/UPDATE/DELETE) sem retorno de dados.
def run(self, sql: str, params: Optional[dict[str, Any]] = None) -> None:
"""Executa um SQL sem retorno de dados (ex: INSERT, UPDATE, DELETE)."""
self._execute(sql, params, fetch="none")
# Executa comandos com cláusula RETURNING e devolve o registro retornado (ou None).
def run_and_return(
self, sql: str, params: Optional[dict[str, Any]] = None
) -> Optional[Mapping[str, Any]]:
"""Executa SQL com RETURNING e retorna o primeiro registro como dict."""
return self._execute(sql, params, fetch="one")

View file

@ -0,0 +1,31 @@
import json
from types import SimpleNamespace
def dict_to_namespace(d):
"""
Converte dict (ou string JSON) recursivamente em SimpleNamespace.
"""
# Caso venha uma string JSON
if isinstance(d, str):
try:
# tenta fazer parse do JSON interno
parsed = json.loads(d)
# se for mesmo JSON, converte recursivamente
return dict_to_namespace(parsed)
except (json.JSONDecodeError, TypeError):
# não era JSON, retorna string normal
return d
# Caso seja um dicionário
if isinstance(d, dict):
return SimpleNamespace(**{k: dict_to_namespace(v) for k, v in d.items()})
# Caso seja lista/tupla
if isinstance(d, list):
return [dict_to_namespace(i) for i in d]
if isinstance(d, tuple):
return tuple(dict_to_namespace(i) for i in d)
# Caso base (valor simples)
return d

View file

@ -0,0 +1,82 @@
from typing import Any, Mapping, Iterable
class DictToObj:
"""
Converte dicts (aninhados) em objetos com acesso por ponto.
- d["x"] -> o.x
- Listas/tuplas são convertidas recursivamente.
- Mantém método parse() para voltar ao dict original.
"""
__slots__ = ("__data__",)
def __init__(self, data: Mapping[str, Any] | None = None):
object.__setattr__(self, "__data__", {})
if data:
for k, v in data.items():
self.__data__[k] = self._convert(v)
# ===== Conversões =====
@classmethod
def _convert(cls, value: Any) -> Any:
if isinstance(value, Mapping):
return cls(value)
if isinstance(value, list):
return [cls._convert(v) for v in value]
if isinstance(value, tuple):
return tuple(cls._convert(v) for v in value)
return value
def parse(self) -> dict[str, Any]:
def back(v: Any) -> Any:
if isinstance(v, DictToObj):
return v.parse()
if isinstance(v, list):
return [back(i) for i in v]
if isinstance(v, tuple):
return tuple(back(i) for i in v)
return v
return {k: back(v) for k, v in self.__data__.items()}
# ===== Acesso por ponto / item =====
def __getattr__(self, name: str) -> Any:
try:
return self.__data__[name]
except KeyError as e:
raise AttributeError(name) from e
def __setattr__(self, name: str, value: Any) -> None:
# protege o atributo interno
if name == "__data__":
object.__setattr__(self, name, value)
else:
self.__data__[name] = self._convert(value)
def __getitem__(self, key: str) -> Any:
return self.__data__[key]
def __setitem__(self, key: str, value: Any) -> None:
self.__data__[key] = self._convert(value)
def __contains__(self, key: str) -> bool:
return key in self.__data__
def keys(self) -> Iterable[str]:
return self.__data__.keys()
def items(self) -> Iterable[tuple[str, Any]]:
return self.__data__.items()
def values(self) -> Iterable[Any]:
return self.__data__.values()
def __iter__(self):
return iter(self.__data__)
def __len__(self) -> int:
return len(self.__data__)
def __repr__(self) -> str:
return f"DictToObj({self.__data__!r})"

View file

@ -0,0 +1,51 @@
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

View file

@ -0,0 +1,5 @@
from fastapi import Request
async def get_url_params(request: Request):
return dict(request.query_params)

View file

@ -0,0 +1,37 @@
import json
from pathlib import Path
from typing import Any, Union
class JsonToDict:
"""
Converte conteúdo JSON (string, bytes ou arquivo) em dicionário Python.
"""
@staticmethod
def parse(data: Union[str, bytes, Path]) -> dict[str, Any]:
"""
Recebe uma string JSON, bytes ou caminho de arquivo .json
e retorna um dicionário Python.
"""
try:
# Caso seja um caminho de arquivo
if isinstance(data, Path):
with open(data, "r", encoding="utf-8") as file:
return json.load(file)
# Caso seja conteúdo JSON (str ou bytes)
if isinstance(data, bytes):
data = data.decode("utf-8")
# Garante que é string JSON
if isinstance(data, str):
return json.loads(data)
raise TypeError("Tipo de entrada inválido. Use str, bytes ou Path.")
except json.JSONDecodeError as e:
raise ValueError(f"Erro ao decodificar JSON: {e}")
except Exception as e:
raise ValueError(f"Erro ao converter JSON para dict: {e}")

31
actions/data/microtime.py Normal file
View file

@ -0,0 +1,31 @@
import time
class Microtime:
"""
Utilitário para manipulação de tempo com alta precisão (microssegundos).
"""
@staticmethod
def get() -> float:
"""
Retorna o timestamp Unix atual com precisão de microssegundos.
Equivalente ao microtime(true) do PHP.
"""
return time.time()
@staticmethod
def as_int() -> int:
"""
Retorna o tempo atual puramente em microssegundos (Inteiro).
Útil para gerar IDs únicos ou ordenação precisa.
"""
# Pega em nanosegundos e converte para microssegundos
return time.time_ns() // 1000
@staticmethod
def diff(start_time: float) -> float:
"""
Calcula a diferença (duração) em segundos com precisão.
"""
return time.time() - start_time

View file

@ -0,0 +1,30 @@
from typing import Tuple, Dict, Any
from pydantic import BaseModel
def prepare_update_data(
schema: BaseModel, exclude_fields: list[str] = None, id_field: str = "id"
) -> Tuple[Dict[str, Any], str]:
"""
Gera dinamicamente os dados e SQL para update com base em um schema Pydantic.
Args:
schema: Instância do schema (ex: t_pessoa_save_schema)
exclude_fields: Lista de campos a serem ignorados no SET (ex: ['pessoa_id'])
id_field: Nome do campo identificador primário (ex: 'pessoa_id')
Returns:
Tuple contendo:
- data_dict: dicionário com apenas campos preenchidos (sem unset)
- update_sql: string SQL do tipo "campo1 = :campo1, campo2 = :campo2"
"""
exclude_fields = exclude_fields or [id_field]
# Cria o dicionário apenas com os campos enviados
data_dict = schema.model_dump(exclude_unset=True)
# Monta lista dinâmica de campos para o SET
update_fields = [f"{k} = :{k}" for k in data_dict.keys() if k not in exclude_fields]
update_sql = ", ".join(update_fields)
return data_dict, update_sql

View file

@ -0,0 +1,221 @@
import os
import subprocess
from pathlib import Path
import uuid
from fastapi import HTTPException, status
from actions.data.text import Text
from schemas.process_document_schema import ProcessDocumentSchema
# Caminho absoluto do executável do LibreOffice no Windows.
# Usar caminho fixo evita problemas de PATH em serviços, venv e produção.
SOFFICE_PATH = r"C:\Program Files\LibreOffice\program\soffice.exe"
class ProcessDocumentAction:
"""
Action responsável por processar documentos editáveis.
REGRAS IMPORTANTES:
- TODO texto recebido vem COMPRIMIDO (RTF ou DOCX)
- A descompressão acontece SEMPRE
- Após descompressão:
- DOCX salvo diretamente
- RTF convertido para DOCX via LibreOffice
A saída final é SEMPRE um arquivo DOCX em disco.
"""
# ======================================================
# MÉTODO PÚBLICO (ENTRYPOINT DA ACTION)
# ======================================================
def execute(self, data: ProcessDocumentSchema) -> str:
"""
Orquestra todo o fluxo de processamento do documento.
"""
# 1) Prepara diretório e caminhos únicos
diretorio = self._prepare_directory()
rtf_path, docx_path = self._generate_paths(diretorio, data.id)
# 2) Descompacta obrigatoriamente o conteúdo
conteudo = self._decompress_content(data.texto)
# Remove apenas espaços iniciais para detecção segura
conteudo_strip = conteudo.lstrip()
# 3) Se após descompressão for DOCX, salva direto
if self._is_docx(conteudo_strip):
self._save_docx(docx_path, conteudo)
return docx_path.name
# 4) Caso contrário, valida se é RTF
self._validate_rtf(conteudo_strip)
# 5) Normaliza e salva RTF (simples ou complexo)
texto_rtf = conteudo_strip.strip()
self._save_rtf(rtf_path, texto_rtf)
# 6) Converte RTF → DOCX via LibreOffice
self._convert_rtf_to_docx(diretorio, rtf_path)
# 7) Valida resultado final
self._validate_docx(docx_path)
# 8) Retorno final
return docx_path.name
# ======================================================
# MÉTODOS PRIVADOS — PREPARAÇÃO
# ======================================================
def _prepare_directory(self) -> Path:
"""
Garante que o diretório temporário exista.
"""
diretorio = Path("./storage/temp").resolve()
diretorio.mkdir(parents=True, exist_ok=True)
return diretorio
def _generate_paths(self, diretorio: Path, document_id) -> tuple[Path, Path]:
"""
Gera nomes de arquivos únicos por execução,
evitando conflitos e lock de arquivos no Windows.
"""
base_name = f"{document_id}_{uuid.uuid4().hex}"
return (
diretorio / f"{base_name}.rtf",
diretorio / f"{base_name}.docx",
)
# ======================================================
# MÉTODOS PRIVADOS — CONTEÚDO
# ======================================================
def _decompress_content(self, texto: bytes | None) -> str:
"""
Descompacta obrigatoriamente o conteúdo recebido.
Caso não exista texto, cria um RTF vazio válido.
"""
if not texto:
return r"{\rtf1\ansi\deff0\pard\par}"
return Text.decompress(texto) or ""
def _is_docx(self, conteudo: str) -> bool:
"""
DOCX é um arquivo ZIP e sempre inicia com PK\\x03\\x04.
"""
return conteudo.startswith("PK\x03\x04")
def _validate_rtf(self, conteudo: str) -> None:
"""
Garante que o conteúdo seja um RTF válido.
"""
if not conteudo.startswith("{\\rtf"):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Conteúdo descompactado não é RTF nem DOCX válido",
)
# ======================================================
# MÉTODOS PRIVADOS — ESCRITA DE ARQUIVOS
# ======================================================
def _save_docx(self, path: Path, conteudo: str) -> None:
"""
Salva DOCX diretamente em disco.
"""
with open(path, "wb") as f:
# DOCX descompactado ainda está em latin1
f.write(conteudo.encode("latin1"))
def _save_rtf(self, path: Path, texto_rtf: str) -> None:
"""
Salva RTF em disco.
Detecta automaticamente RTFs complexos (WPTools, tabelas, bookmarks, unicode)
para escolher a forma correta de escrita.
"""
rtf_complexo = self._is_complex_rtf(texto_rtf)
if rtf_complexo:
# Escrita binária preserva estruturas complexas
rtf_bytes = texto_rtf.encode("cp1252", errors="ignore")
with open(path, "wb") as f:
f.write(rtf_bytes)
else:
# Escrita textual para RTFs simples
with open(path, "w", encoding="cp1252", errors="replace") as f:
f.write(texto_rtf)
def _is_complex_rtf(self, texto_rtf: str) -> bool:
"""
Detecta padrões comuns de RTFs complexos gerados por WPTools,
OnlyOffice, Word, etc.
"""
return any(
token in texto_rtf
for token in (
"\\u",
"{\\*\\bkmkstart",
"\\trowd",
"\\cellx",
"\\wppr",
)
)
# ======================================================
# MÉTODOS PRIVADOS — CONVERSÃO
# ======================================================
def _convert_rtf_to_docx(self, diretorio: Path, rtf_path: Path) -> None:
"""
Executa o LibreOffice em modo headless para conversão RTF DOCX.
"""
cmd = [
SOFFICE_PATH,
"--headless",
"--nologo",
"--nolockcheck",
"--nodefault",
"--nofirststartwizard",
"--convert-to",
"docx",
"--outdir",
str(diretorio),
str(rtf_path),
]
clean_env = {
"SYSTEMROOT": os.environ.get("SYSTEMROOT", ""),
"WINDIR": os.environ.get("WINDIR", ""),
"PATH": os.environ.get("PATH", ""),
"TEMP": os.environ.get("TEMP", ""),
"TMP": os.environ.get("TMP", ""),
}
result = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
timeout=180,
env=clean_env,
)
if result.returncode != 0:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Erro ao converter RTF para DOCX via LibreOffice",
)
# ======================================================
# MÉTODOS PRIVADOS — VALIDAÇÃO FINAL
# ======================================================
def _validate_docx(self, docx_path: Path) -> None:
"""
Garante que o DOCX final realmente foi gerado.
"""
if not docx_path.exists():
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="DOCX não foi gerado pelo LibreOffice",
)

97
actions/data/text.py Normal file
View file

@ -0,0 +1,97 @@
import zlib
from striprtf.striprtf import rtf_to_text
class Text:
@staticmethod
def decompress_bytes(vf_string):
"""
Descomprime e retorna BYTES (sem decode/ignore), ideal para RTF/DOCX.
REGRA:
- Se estiver compactado (zlib) retorna bytes descompactados
- Se NÃO estiver compactado retorna os bytes originais
"""
if vf_string is None:
return b""
# 1) Se for stream (BLOB)
if hasattr(vf_string, "read"):
try:
vf_string = vf_string.read()
except Exception:
return b""
if not vf_string:
return b""
# 2) Garantir bytes
if isinstance(vf_string, str):
vf_bytes = vf_string.encode("latin1", errors="ignore")
else:
try:
vf_bytes = bytes(vf_string)
except Exception:
return b""
# 3) Detectar zlib (header 0x78 0x01/0x9C/0xDA)
is_zlib = (
len(vf_bytes) > 2
and vf_bytes[0] == 0x78
and vf_bytes[1] in (0x01, 0x9C, 0xDA)
)
# 4) Descompactar se necessário (RETORNA BYTES)
if is_zlib:
try:
return zlib.decompress(vf_bytes)
except Exception:
# fallback: retorna bytes originais
return vf_bytes
return vf_bytes
@staticmethod
def decompress(vf_string):
"""
Mantido para compatibilidade: retorna STR (uso geral).
ATENÇÃO: para RTF/DOCX use decompress_bytes().
"""
raw = Text.decompress_bytes(vf_string)
if not raw:
return ""
try:
return raw.decode("iso-8859-1", errors="ignore")
except Exception:
return ""
@staticmethod
def compress(text, *, encoding: str = "iso-8859-1"):
if text is None or text == "":
return b""
if hasattr(text, "read"):
raw = text.read()
else:
raw = text
if isinstance(raw, str):
raw_bytes = raw.encode(encoding, errors="ignore")
else:
raw_bytes = bytes(raw)
return zlib.compress(raw_bytes)
@staticmethod
def to_text(raw_text: str) -> str:
if not raw_text:
return ""
if raw_text.strip().startswith("{\\rtf"):
try:
return rtf_to_text(raw_text).strip()
except Exception:
return raw_text
return raw_text.strip()

View file

@ -1,7 +1,6 @@
import importlib import importlib
from typing import Any, Optional, Type
from actions.config.config import Config from actions.config.config import Config
from typing import Optional, Any, Type
class DynamicImport: class DynamicImport:

View file

@ -0,0 +1,64 @@
import importlib
import re
from functools import lru_cache
from typing import Type, TypeVar, Optional
from actions.config.config import Config
from actions.env.env_config_loader import EnvConfigLoader
# Genérico para garantir que o retorno respeite o Protocolo
T = TypeVar("T")
class ServiceFactory:
def __init__(self, package: str, table: str):
# Instancia o loader com o prefixo correto
env = EnvConfigLoader(".env")
# Ex: "packages.v1"
self.base_root = "packages.v1"
self.package = package
self.table = table
# Carrega config apenas uma vez
self.app_config = Config.get("app.json")
# Define a UF da aplicação
self.current_state = env.ORIUS_CLIENT_STATE
@lru_cache(maxsize=32)
def make(self, class_name: str, interface: Type[T]) -> T:
"""
Instancia um serviço dinamicamente com comportamento de Autoload.
"""
# 1. Converte CamelCase para snake_case (Autoload style)
# Ex: TAtoIndexService -> t_ato_index_service
module_name = re.sub(r"(?<!^)(?=[A-Z])", "_", class_name).lower()
# 2. Monta o caminho completo
# Ex: packages.v1.servicos.balcao.services.t_ato.SP.t_ato_index_service
import_path = (
f"{self.base_root}.{self.package}.services."
f"{self.table}.{self.current_state}.{module_name}"
)
try:
# 3. Importação Dinâmica
module = importlib.import_module(import_path)
# 4. Pega a classe do módulo
clazz = getattr(module, class_name)
# 5. Retorna a INSTÂNCIA da classe (já com () )
# Se seus serviços precisam de argumentos no __init__, altere aqui.
return clazz()
except ImportError as e:
raise ImportError(
f"FATAL: Não foi possível carregar o serviço '{class_name}' para o estado '{self.current_state}'.\nCaminho tentado: {import_path}\nErro: {e}"
)
except AttributeError:
raise AttributeError(
f"FATAL: O arquivo '{module_name}.py' existe, mas a classe '{class_name}' não foi encontrada dentro dele."
)

36
actions/env/env_config_loader.py vendored Normal file
View file

@ -0,0 +1,36 @@
from dotenv import dotenv_values, load_dotenv
import os
class EnvConfigLoader:
"""
Classe para carregar todas as variáveis de ambiente (.env)
e permitir acesso via atributo (settings.VAR).
"""
def __init__(self, env_file: str = ".env"):
# Garante que o .env será carregado no ambiente do sistema
load_dotenv(env_file)
# Lê todas as variáveis (do arquivo + sistema)
self._values = {
**dotenv_values(env_file), # Conteúdo do .env
**os.environ, # Variáveis já existentes no ambiente
}
def __getattr__(self, name: str):
"""Permite acessar como settings.VAR"""
# Normaliza o nome para maiúsculo
key = name.upper()
if key in self._values:
return self._values[key]
raise AttributeError(f"A variável '{name}' não existe no .env")
def __repr__(self):
"""Exibe todas as variáveis carregadas"""
return f"<Settings {self._values}>"
def all(self) -> dict:
"""Retorna todas as variáveis como dicionário"""
return dict(self._values)

View file

@ -4,14 +4,14 @@ import os
class File: class File:
def create(self, data, caminho_arquivo="storage/temp.json"): def create(self, data, caminho_arquivo='storage/temp.json'):
try: try:
# Garante que a pasta existe # Garante que a pasta existe
os.makedirs(os.path.dirname(caminho_arquivo), exist_ok=True) os.makedirs(os.path.dirname(caminho_arquivo), exist_ok=True)
# Lê dados existentes (ou cria nova lista) # Lê dados existentes (ou cria nova lista)
if os.path.exists(caminho_arquivo): if os.path.exists(caminho_arquivo):
with open(caminho_arquivo, "r", encoding="utf-8") as arquivo: with open(caminho_arquivo, 'r', encoding='utf-8') as arquivo:
try: try:
dados_existentes = json.load(arquivo) dados_existentes = json.load(arquivo)
if not isinstance(dados_existentes, list): if not isinstance(dados_existentes, list):
@ -25,8 +25,8 @@ class File:
dados_existentes.append(data) dados_existentes.append(data)
# Salva novamente no arquivo com indentação # Salva novamente no arquivo com indentação
with open(caminho_arquivo, "w", encoding="utf-8") as arquivo: with open(caminho_arquivo, 'w', encoding='utf-8') as arquivo:
json.dump(dados_existentes, arquivo, indent=4, ensure_ascii=False) json.dump(dados_existentes, arquivo, indent=4, ensure_ascii=False)
except Exception as e: except Exception as e:
print(f"❌ Erro ao salvar o dado: {e}") print(f"❌ Erro ao salvar o dado: {e}")

View file

@ -1,5 +1,4 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from jose import jwt from jose import jwt
from pytz import timezone from pytz import timezone
@ -9,6 +8,7 @@ from actions.config.config import Config
class CreateToken(BaseAction): class CreateToken(BaseAction):
def __init__(self): def __init__(self):
# Busca as configurações da aplicação # Busca as configurações da aplicação
self.config = Config.get("app.json") self.config = Config.get("app.json")

View file

@ -1,8 +1,7 @@
from fastapi import Depends, HTTPException, Request, status from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer from fastapi.security import OAuth2PasswordBearer
from actions.jwt.verify_token import \ from actions.jwt.verify_token import VerifyToken # A classe que criamos anteriormente
VerifyToken # A classe que criamos anteriormente
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") # Apenas requerido pelo FastAPI oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") # Apenas requerido pelo FastAPI

View file

@ -1,7 +1,4 @@
from datetime import datetime from jose import jwt, JWTError, ExpiredSignatureError
from jose import ExpiredSignatureError, JWTError, jwt
from pytz import timezone
from actions.config.config import Config from actions.config.config import Config
@ -9,13 +6,15 @@ from actions.config.config import Config
class VerifyToken: class VerifyToken:
def __init__(self): def __init__(self):
# Carrega configurações # Carrega configurações
self.config = Config.get("app.json") self.config = Config.get('app.json')
def execute(self, token: str, expected_type: str = "access-token") -> dict: def execute(self, token: str, expected_type: str = 'access-token') -> dict:
try: try:
# Decodifica o token # Decodifica o token
payload = jwt.decode( payload = jwt.decode(
token, self.config.jwt.token, algorithms=[self.config.jwt.algorithm] token,
self.config.jwt.token,
algorithms=[self.config.jwt.algorithm]
) )
# Valida expiração # Valida expiração
@ -32,16 +31,25 @@ class VerifyToken:
if "data" not in payload: if "data" not in payload:
raise ValueError("Token malformado: campo 'data' ausente.") raise ValueError("Token malformado: campo 'data' ausente.")
return {"status": "valid", "payload": payload} return {
"status": "valid",
"payload": payload
}
except ExpiredSignatureError: except ExpiredSignatureError:
return {"status": "expired", "message": "O token expirou."} return {
"status": "expired",
"message": "O token expirou."
}
except JWTError as e: except JWTError as e:
return {"status": "invalid", "message": f"Token inválido: {str(e)}"} return {
"status": "invalid",
"message": f"Token inválido: {str(e)}"
}
except Exception as e: except Exception as e:
return { return {
"status": "error", "status": "error",
"message": f"Erro na validação do token: {str(e)}", "message": f"Erro na validação do token: {str(e)}"
} }

View file

@ -4,14 +4,14 @@ import os
class Log: class Log:
def register(self, data, caminho_arquivo="storage/temp.json"): def register(self, data, caminho_arquivo='storage/temp.json'):
try: try:
# Garante que a pasta existe # Garante que a pasta existe
os.makedirs(os.path.dirname(caminho_arquivo), exist_ok=True) os.makedirs(os.path.dirname(caminho_arquivo), exist_ok=True)
# Lê dados existentes (ou cria nova lista) # Lê dados existentes (ou cria nova lista)
if os.path.exists(caminho_arquivo): if os.path.exists(caminho_arquivo):
with open(caminho_arquivo, "r", encoding="utf-8") as arquivo: with open(caminho_arquivo, 'r', encoding='utf-8') as arquivo:
try: try:
dados_existentes = json.load(arquivo) dados_existentes = json.load(arquivo)
if not isinstance(dados_existentes, list): if not isinstance(dados_existentes, list):
@ -25,8 +25,8 @@ class Log:
dados_existentes.append(data) dados_existentes.append(data)
# Salva novamente no arquivo com indentação # Salva novamente no arquivo com indentação
with open(caminho_arquivo, "w", encoding="utf-8") as arquivo: with open(caminho_arquivo, 'w', encoding='utf-8') as arquivo:
json.dump(dados_existentes, arquivo, indent=4, ensure_ascii=False) json.dump(dados_existentes, arquivo, indent=4, ensure_ascii=False)
except Exception as e: except Exception as e:
print(f"❌ Erro ao salvar o dado: {e}") print(f"❌ Erro ao salvar o dado: {e}")

View file

@ -6,7 +6,7 @@ from passlib.context import CryptContext
# Cria uma instância do contexto de criptografia # Cria uma instância do contexto de criptografia
# O esquema usado é 'bcrypt', que é seguro e amplamente aceito # O esquema usado é 'bcrypt', que é seguro e amplamente aceito
# O parâmetro 'deprecated="auto"' marca versões antigas como inseguras, se aplicável # O parâmetro 'deprecated="auto"' marca versões antigas como inseguras, se aplicável
CRYPTO = CryptContext(schemes=["bcrypt"], deprecated="auto") CRYPTO = CryptContext(schemes=['bcrypt'], deprecated='auto')
class Security: class Security:
@ -19,17 +19,19 @@ class Security:
""" """
return CRYPTO.identify(senha) return CRYPTO.identify(senha)
# Verifica se uma senha fornecida corresponde ao hash armazenado # Verifica se uma senha fornecida corresponde ao hash armazenado
def verify_senha_api(plain_senha_api: str, hashed_senha_api: str) -> bool: def verify_senha_api(plain_senha_api: str, hashed_senha_api: str) -> bool:
""" """
Compara a senha fornecida em texto puro com o hash armazenado. Compara a senha fornecida em texto puro com o hash armazenado.
:param plain_senha_api: Senha digitada pelo usuário :param plain_senha_api: Senha digitada pelo usuário
:param hashed_senha_api: Hash da senha armazenado no banco de dados :param hashed_senha_api: Hash da senha armazenado no banco de dados
:return: True se corresponder, False se não :return: True se corresponder, False se não
""" """
return CRYPTO.verify(plain_senha_api, hashed_senha_api) return CRYPTO.verify(plain_senha_api, hashed_senha_api)
# Gera o hash de uma senha fornecida # Gera o hash de uma senha fornecida
def hash_senha_api(plain_senha_api: str) -> str: def hash_senha_api(plain_senha_api: str) -> str:
""" """

View file

@ -0,0 +1,11 @@
from fastapi import Request, HTTPException, status
def get_session_user(request: Request) -> dict:
user = request.session.get("user")
if not user:
# ajuste conforme sua regra (pode só retornar None)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Sessão inválida"
)
return user

View file

@ -0,0 +1,16 @@
# services/session_service.py
from fastapi import Request
class SessionService:
def __init__(self, request: Request):
self._session = request.session
def set(self, k, v):
self._session[k] = v
def get(self, k, d=None):
return self._session.get(k, d)
def clear(self):
self._session.clear()

View file

@ -1,4 +1,4 @@
# exceptions.py # exceptions.py
class BusinessRuleException(Exception): class BusinessRuleException(Exception):
def __init__(self, message: str): def __init__(self, message: str):
self.message = message self.message = message

View file

@ -1,5 +1,4 @@
# handlers.py # handlers.py
import json
import traceback import traceback
from fastapi import Request from fastapi import Request
@ -7,8 +6,8 @@ from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from starlette.exceptions import HTTPException as StarletteHTTPException from starlette.exceptions import HTTPException as StarletteHTTPException
from actions.log.log import Log
from actions.system.exceptions import BusinessRuleException from actions.system.exceptions import BusinessRuleException
from actions.log.log import Log
def register_exception_handlers(app): def register_exception_handlers(app):

View file

@ -7,7 +7,7 @@ class CNPJ:
def validate(data: str) -> bool: def validate(data: str) -> bool:
# Remove caracteres não numéricos # Remove caracteres não numéricos
data = re.sub(r"\D", "", data) data = re.sub(r'\D', '', data)
# Verifica se tem 14 dígitos # Verifica se tem 14 dígitos
if len(data) != 14: if len(data) != 14:
@ -21,7 +21,7 @@ class CNPJ:
def calcular_digito(data, peso): def calcular_digito(data, peso):
soma = sum(int(a) * b for a, b in zip(data, peso)) soma = sum(int(a) * b for a, b in zip(data, peso))
resto = soma % 11 resto = soma % 11
return "0" if resto < 2 else str(11 - resto) return '0' if resto < 2 else str(11 - resto)
# Primeiro dígito verificador # Primeiro dígito verificador
peso1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] peso1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]

View file

@ -6,7 +6,7 @@ class CPF:
@staticmethod @staticmethod
def is_valid_cpf(data: str) -> bool: def is_valid_cpf(data: str) -> bool:
# Remove caracteres não numéricos # Remove caracteres não numéricos
data = re.sub(r"\D", "", data) data = re.sub(r'\D', '', data)
# Verifica se tem 11 dígitos # Verifica se tem 11 dígitos
if len(data) != 11: if len(data) != 11:
@ -20,7 +20,7 @@ class CPF:
def calcular_digito(digitos, peso): def calcular_digito(digitos, peso):
soma = sum(int(a) * b for a, b in zip(digitos, peso)) soma = sum(int(a) * b for a, b in zip(digitos, peso))
resto = soma % 11 resto = soma % 11
return "0" if resto < 2 else str(11 - resto) return '0' if resto < 2 else str(11 - resto)
# Primeiro dígito verificador # Primeiro dígito verificador
peso1 = range(10, 1, -1) peso1 = range(10, 1, -1)
@ -31,4 +31,4 @@ class CPF:
digito2 = calcular_digito(data[:10], peso2) digito2 = calcular_digito(data[:10], peso2)
# Verifica se os dígitos batem # Verifica se os dígitos batem
return data[-2:] == digito1 + digito2 return data[-2:] == digito1 + digito2

View file

@ -6,4 +6,4 @@ class Email:
@staticmethod @staticmethod
def is_valid_email(email: str) -> bool: def is_valid_email(email: str) -> bool:
"""Check if email has a valid structure""" """Check if email has a valid structure"""
return bool(re.match(r"^[\w\.-]+@[\w\.-]+\.\w+$", email)) return bool(re.match(r"^[\w\.-]+@[\w\.-]+\.\w+$", email))

View file

@ -1,3 +1,4 @@
class Phone: class Phone:
@staticmethod @staticmethod
@ -8,4 +9,4 @@ class Phone:
@staticmethod @staticmethod
def validate_telephone(data: str) -> bool: def validate_telephone(data: str) -> bool:
# Verifica e retorna se o numero de telefone é igual a 11 # Verifica e retorna se o numero de telefone é igual a 11
return len(data) == 10 return len(data) == 10

View file

@ -7,15 +7,16 @@ class Text:
# Remove as mascaras de números # Remove as mascaras de números
@staticmethod @staticmethod
def just_numbers(data: str) -> str: def just_numbers(data: str) -> str:
"""Mantêm apenas os numeros""" """ Mantêm apenas os numeros """
data = re.sub(r"[^\d]", "", data) data = re.sub(r"[^\d]", "", data)
return data return data
# Verifica se um e-mail é válido # Verifica se um e-mail é válido
@staticmethod @staticmethod
def is_valid_email(email: str) -> bool: def is_valid_email(email: str) -> bool:
"""Check if email has a valid structure""" """Check if email has a valid structure"""
return bool(re.match(r"^[\w\.-]+@[\w\.-]+\.\w+$", email)) return bool(re.match(r"^[\w\.-]+@[\w\.-]+\.\w+$", email))
""" """
Sanitiza entradas de texto contra XSS e SQL Injection básicos. Sanitiza entradas de texto contra XSS e SQL Injection básicos.
@ -24,7 +25,6 @@ class Text:
- Remove padrões suspeitos de XSS e SQL Injection - Remove padrões suspeitos de XSS e SQL Injection
- Normaliza múltiplos espaços em um - Normaliza múltiplos espaços em um
""" """
@staticmethod @staticmethod
def sanitize_input(data: str) -> str: def sanitize_input(data: str) -> str:
@ -41,36 +41,23 @@ class Text:
data = re.sub(r"\s+", " ", data) data = re.sub(r"\s+", " ", data)
# 4) Remove tags <script> (com atributos) # 4) Remove tags <script> (com atributos)
data = re.sub(r"<\s*script[^>]*>", "", data, flags=re.IGNORECASE) data = re.sub(r'<\s*script[^>]*>', '', data, flags=re.IGNORECASE)
data = re.sub(r"<\s*/\s*script\s*>", "", data, flags=re.IGNORECASE) data = re.sub(r'<\s*/\s*script\s*>', '', data, flags=re.IGNORECASE)
# 5) Remove javascript: de links # 5) Remove javascript: de links
data = re.sub(r"javascript\s*:", "", data, flags=re.IGNORECASE) data = re.sub(r'javascript\s*:', '', data, flags=re.IGNORECASE)
# 6) Remove palavras-chave SQL Injection comuns # 6) Remove palavras-chave SQL Injection comuns
blacklist = [ blacklist = [
"--", "--", ";", "/*", "*/", "@@",
";", "char(", "nchar(", "varchar(",
"/*", "alter", "drop", "exec", "insert",
"*/", "delete", "update", "union", "select",
"@@", "from", "where"
"char(",
"nchar(",
"varchar(",
"alter",
"drop",
"exec",
"insert",
"delete",
"update",
"union",
"select",
"from",
"where",
] ]
for word in blacklist: for word in blacklist:
# Verificar se 'word' é uma string não vazia e válida para a regex # Verificar se 'word' é uma string não vazia e válida para a regex
if word: if word:
data = re.sub(re.escape(word), "", data, flags=re.IGNORECASE) data = re.sub(re.escape(word), "", data, flags=re.IGNORECASE)
return data return data

14
actions/values/values.py Normal file
View file

@ -0,0 +1,14 @@
from decimal import ROUND_HALF_UP, Decimal
class Values:
@staticmethod
def percent(value: Decimal, percent: Decimal) -> Decimal:
return value / percent
@staticmethod
def money(scale: str, value: Decimal) -> Decimal:
return value.quantize(scale, rounding=ROUND_HALF_UP)

186
api.code-workspace Normal file
View file

@ -0,0 +1,186 @@
{
"folders": [
{
"path": "D:/IIS/Orius/api"
}
],
"settings": {
// === ⚙️ GERAL ===
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.formatOnPaste": false,
"editor.formatOnType": false,
"editor.minimap.enabled": false,
"files.trimTrailingWhitespace": true,
"files.autoSave": "onFocusChange",
"telemetry.telemetryLevel": "off",
"update.mode": "manual",
"workbench.startupEditor": "none",
"workbench.editor.enablePreview": false,
// === ⚡ PERFORMANCE ===
"files.watcherExclude": {
"**/__pycache__/**": true,
"**/.mypy_cache/**": true,
"**/.pytest_cache/**": true,
"**/.venv/**": true,
"**/venv/**": true,
"**/.git/**": true
},
"search.exclude": {
"**/__pycache__": true,
"**/.git": true,
"**/.mypy_cache": true,
"**/.pytest_cache": true
},
// === 🐍 PYTHON ===
"python.defaultInterpreterPath": "D:/IIS/Orius/api/venv/Scripts/python.exe",
"python.languageServer": "Pylance",
"python.analysis.autoImportCompletions": true,
"python.analysis.indexing": true,
"python.analysis.typeCheckingMode": "basic",
"python.analysis.useLibraryCodeForTypes": true,
"python.analysis.memory.keepLibraryAst": false,
// === 🧹 FORMATADOR ===
"python.formatting.provider": "black",
"python.formatting.blackArgs": [
"--line-length",
"100"
],
// === ✅ LINTING ===
"python.linting.enabled": true,
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": [
"--max-line-length=100"
],
// === 🧩 FORMATAÇÃO LOCAL ===
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true
},
// === 🧠 GIT ===
"git.enabled": true,
"git.autorefresh": true,
"git.confirmSync": false,
"git.fetchOnPull": true,
"git.countBadge": "tracked",
"git.pruneOnFetch": true,
"git.postCommitCommand": "sync",
"git.openDiffOnClick": true,
"git.decorations.enabled": true,
// === 🔍 GITLENS ===
"gitlens.advanced.messages": {
"suppressShowKeyBindingsNotice": true
},
"gitlens.codeLens.enabled": false,
"gitlens.currentLine.enabled": false,
"gitlens.hovers.enabled": true,
"gitlens.views.repositories.autoRefresh": true,
"gitlens.views.repositories.location": "scm",
"gitlens.defaultDateFormat": "DD/MM/YYYY HH:mm",
"gitlens.defaultDateShortFormat": "DD/MM HH:mm",
"gitlens.statusBar.enabled": true,
// === 💻 TERMINAIS INTEGRADOS ===
"terminal.integrated.profiles.windows": {
"FastAPI Dev": {
"path": "cmd.exe",
"args": [
"/k",
"cd D:\\IIS\\Orius\\api && venv\\Scripts\\activate && uvicorn main:app --reload --log-level debug"
]
},
"FastAPI Prod": {
"path": "cmd.exe",
"args": [
"/k",
"cd D:\\IIS\\Orius\\api && venv\\Scripts\\activate && uvicorn main:app --host 0.0.0.0 --port 8000"
]
},
"FastAPI Test": {
"path": "cmd.exe",
"args": [
"/k",
"cd D:\\IIS\\Orius\\api && venv\\Scripts\\activate && pytest -v"
]
},
"Python Shell": {
"path": "cmd.exe",
"args": [
"/k",
"cd D:\\IIS\\Orius\\api && venv\\Scripts\\activate"
]
},
"Git Bash": {
"path": "C:\\Program Files\\Git\\bin\\bash.exe"
}
},
"terminal.integrated.defaultProfile.windows": "FastAPI Dev",
"terminal.integrated.scrollback": 10000,
"terminal.integrated.enablePersistentSessions": false,
// === 🧪 TESTES ===
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.autoTestDiscoverOnSaveEnabled": true,
// === 🗂️ ARQUIVOS ===
"files.exclude": {
"**/.DS_Store": true,
"**/*.log": true
}
},
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "Debug FastAPI",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": [
"main:app",
"--reload",
"--host",
"127.0.0.1",
"--port",
"8000"
],
"jinja": true,
"justMyCode": true,
"cwd": "${workspaceFolder}",
"env": {
"PYTHONPATH": "${workspaceFolder}"
}
},
{
"name": "Pytest All",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/venv/Scripts/pytest.exe",
"args": [
"-v"
],
"console": "integratedTerminal"
}
]
},
"extensions": {
"recommendations": [
// === 🐍 PYTHON ===
"ms-python.python",
"ms-python.pylance",
"ms-python.black-formatter",
"ms-python.flake8",
"littlefoxteam.vscode-python-test-adapter",
// === 🔍 GIT ===
"eamodio.gitlens",
"mhutchie.git-graph",
"donjayamanne.githistory",
// === 🧰 UTILITÁRIOS ===
"formulahendry.code-runner",
"streetsidesoftware.code-spell-checker",
"tamasfe.even-better-toml"
]
}
}

View file

@ -0,0 +1,13 @@
{
"host": "localhost",
"name": "/database/BASE.FDB",
"port": 3050,
"user": "SYSDBA",
"password": "302b3c",
"charset": "UTF8",
"pool" : {
"pre_ping" : true,
"size" : 5,
"max_overflow" :10
}
}

View file

@ -1,9 +1,7 @@
from typing import Optional from typing import Optional
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.engine import Engine from sqlalchemy.engine import Engine
from actions.env.env_config_loader import EnvConfigLoader
from actions.config.config import Config
class Firebird: class Firebird:
@ -11,28 +9,29 @@ class Firebird:
@classmethod @classmethod
def get_engine(cls) -> Engine: def get_engine(cls) -> Engine:
# Obtem as configurações do arquivo JSON
database = Config.get("database/firebird.json") # Instancia o loader com o prefixo correto
env_database = EnvConfigLoader(".env")
# Cria a engine apenas uma vez # Cria a engine apenas uma vez
if cls._engine is None: if cls._engine is None:
# DSN para o SQLAlchemy usando firebird-driver # DSN para o SQLAlchemy usando firebird-driver
dsn = ( dsn = (
f"firebird+firebird://{database.user}:" f"firebird+firebird://{env_database.ORIUS_API_FDB_USER}:"
f"{database.password}@" f"{env_database.ORIUS_API_FDB_PASSWORD}@"
f"{database.host}:" f"{env_database.ORIUS_API_FDB_HOST}:"
f"{database.port}/" f"{env_database.ORIUS_API_FDB_PORT}/"
f"{database.name}" f"{env_database.ORIUS_API_FDB_NAME}"
) )
# Criação da engine SQLAlchemy # Criação da engine SQLAlchemy
cls._engine = create_engine( cls._engine = create_engine(
dsn, dsn,
connect_args={"charset": database.charset}, connect_args={"charset": env_database.ORIUS_API_FDB_CHARSET},
pool_pre_ping=bool(database.pool.pre_ping), pool_pre_ping=bool(env_database.ORIUS_API_FDB_POOL_PRE_PING),
pool_size=database.pool.size, pool_size=int(env_database.ORIUS_API_FDB_POOL_SIZE),
max_overflow=database.pool.max_overflow, max_overflow=int(env_database.ORIUS_API_FDB_POOL_MAX_OVERFLOW),
) )
return cls._engine return cls._engine

17
env.bat Normal file
View file

@ -0,0 +1,17 @@
@echo off
echo === Registrando variáveis de ambiente ORIUS_API ===
setx ORIUS_API_FDB_HOST "localhost"
setx ORIUS_API_FDB_NAME "S:\Bases\SANTARITA.FDB"
setx ORIUS_API_FDB_PORT "3050"
setx ORIUS_API_FDB_USER "SYSDBA"
setx ORIUS_API_FDB_PASSWORD "302b3c"
setx ORIUS_API_FDB_CHARSET "UTF8"
setx ORIUS_API_FDB_POOL_PRE_PING "true"
setx ORIUS_API_FDB_POOL_SIZE "5"
setx ORIUS_API_FDB_POOL_MAX_OVERFLOW "10"
echo.
echo Variáveis ORIUS_API registradas com sucesso!
echo Reinicie o terminal ou o computador para aplicar as alterações.
pause

View file

@ -0,0 +1,10 @@
from typing import Protocol, Any, runtime_checkable
@runtime_checkable
class ServiceProtocolsInterface(Protocol):
"""
Contrato que garante que todo serviço tenha um método execute.
"""
def execute(self, schema: Any) -> Any: ...

45
main.py
View file

@ -1,27 +1,41 @@
# Ajuste para garantir que o diretório base do projeto seja incluído no PYTHONPATH # Ajuste para garantir que o diretório base do projeto seja incluído no PYTHONPATH
import os import os
import platform
import sys import sys
from starlette.middleware.sessions import SessionMiddleware
# Adiciona o diretório atual (onde está o main.py) ao sys.path # Adiciona o diretório atual (onde está o main.py) ao sys.path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from pathlib import Path from firebird.driver import driver_config
# Importa a classe principal do FastAPI # Importa a classe principal do FastAPI
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from pathlib import Path
# Importa o middleware de CORS # Importa o middleware de CORS
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import Response from fastapi.staticfiles import StaticFiles
from starlette.middleware.base import BaseHTTPMiddleware
from actions.config.config import Config
# Importa as configurações globais da aplicação
from actions.log.log import Log
from actions.system.handlers import register_exception_handlers
# Importa o roteador principal da API versão 1 # Importa o roteador principal da API versão 1
from packages.v1.api import api_router from packages.v1.api import api_router
from packages.v1.system.service.startup_check_service import \ from packages.v1.system.service.startup_check_service import StartupCheckService
StartupCheckService
# Importa as configurações globais da aplicação
from actions.log.log import Log
from actions.config.config import Config
from actions.system.handlers import register_exception_handlers
if platform.system() == "Windows":
# Ajuste o caminho abaixo para onde o Firebird está instalado:
FB_DIR = r"C:\Program Files\Firebird\Firebird_4_0"
os.add_dll_directory(FB_DIR)
driver_config.fb_client_library.value = (
r"C:\Program Files\Firebird\Firebird_4_0\fbclient.dll"
)
config = Config.get("app.json") config = Config.get("app.json")
@ -34,12 +48,23 @@ register_exception_handlers(app)
# Adiciona o middleware de CORS # Adiciona o middleware de CORS
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=["http://localhost:3000"], # Domínio do frontend allow_origins=["*"], # Domínio do frontend
allow_credentials=True, allow_credentials=True,
allow_methods=["*"], allow_methods=["*"],
allow_headers=["*"], allow_headers=["*"],
) )
app.add_middleware(
SessionMiddleware,
secret_key="coloque-uma-secret-bem-grande-e-aleatoria",
session_cookie="sid",
same_site="lax",
https_only=True,
max_age=60 * 60 * 8,
)
app.mount(path="/temp", app=StaticFiles(directory="./storage/temp"), name="temp")
@app.on_event("startup") @app.on_event("startup")
async def on_startup(): async def on_startup():

View file

@ -1,16 +1,14 @@
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_delete import Delete
from packages.v1.administrativo.schemas.c_caixa_item_schema import CaixaItemSchema
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_delete import \
Delete
from packages.v1.administrativo.schemas.c_caixa_item_schema import \
CaixaItemSchema
class DeleteAction(BaseAction): class DeleteAction(BaseAction):
def execute(self, caixa_item_schema: CaixaItemSchema): def execute(self, caixa_item_schema : CaixaItemSchema):
# Instânciamento de repoistório # Instânciamento de repoistório
delete = Delete() delete = Delete()
# Retorna o resultado da operação # Retorna o resultado da operação
return delete.execute(caixa_item_schema) return delete.execute(caixa_item_schema)

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_index import \ from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_index import \
Index Index
from packages.v1.administrativo.schemas.c_caixa_item_schema import \ from abstracts.action import BaseAction
CaixaItemSearchSchema
class IndexAction(BaseAction): class IndexAction(BaseAction):
@ -13,4 +11,4 @@ class IndexAction(BaseAction):
index = Index() index = Index()
# Retorna todos produtos # Retorna todos produtos
return index.execute() return index.execute()

View file

@ -1,16 +1,15 @@
from abstracts.action import BaseAction from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_save import Save
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_save import \
Save
from packages.v1.administrativo.schemas.c_caixa_item_schema import \ from packages.v1.administrativo.schemas.c_caixa_item_schema import \
CaixaItemSchema CaixaItemSchema
from abstracts.action import BaseAction
class SaveAction(BaseAction): class SaveAction(BaseAction):
def execute(self, caixa_item_schema: CaixaItemSchema): def execute(self, caixa_item_schema : CaixaItemSchema):
# Instância o repositório desejado # Instância o repositório desejado
save = Save() save = Save()
# Executa o respositório desejado # Executa o respositório desejado
return save.execute(caixa_item_schema) return save.execute(caixa_item_schema)

View file

@ -1,16 +1,14 @@
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_show import Show
from packages.v1.administrativo.schemas.c_caixa_item_schema import CaixaItemSchema
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_show import \
Show
from packages.v1.administrativo.schemas.c_caixa_item_schema import \
CaixaItemSchema
class ShowAction(BaseAction): class ShowAction(BaseAction):
def execute(self, caixa_item_schema: CaixaItemSchema): def execute(self, caixa_item_schema : CaixaItemSchema):
# Instânciamento do repositório # Instânciamento do repositório
show = Show() show = Show()
# Retorna os dados localizados # Retorna os dados localizados
return show.execute(caixa_item_schema) return show.execute(caixa_item_schema)

View file

@ -1,16 +1,14 @@
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_update_repository import UpdateRepository
from packages.v1.administrativo.schemas.c_caixa_item_schema import CaixaItemSchema
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.c_caixa_item.c_caixa_item_update_repository import \
UpdateRepository
from packages.v1.administrativo.schemas.c_caixa_item_schema import \
CaixaItemSchema
class UpdateAction(BaseAction): class UpdateAction(BaseAction):
def execute(self, caixa_item_id: int, caixa_item_schema: CaixaItemSchema): def execute(self, caixa_item_id : int, caixa_item_schema : CaixaItemSchema):
# Instância o repositório desejado # Instância o repositório desejado
update = UpdateRepository() update = UpdateRepository()
# Executa o respositório desejado # Executa o respositório desejado
return update.execute(caixa_item_id, caixa_item_schema) return update.execute(caixa_item_id, caixa_item_schema)

View file

@ -1,13 +1,11 @@
from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_delete_repository import \ from packages.v1.administrativo.schemas.c_caixa_servico_schema import CCaixaServicoIdSchema
DeleteRepository from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_delete_repository import DeleteRepository
from packages.v1.administrativo.schemas.c_caixa_servico_schema import \
CCaixaServicoIdSchema
class DeleteAction: class DeleteAction:
def execute(self, usuario_schema: CCaixaServicoIdSchema): def execute(self, usuario_schema : CCaixaServicoIdSchema):
delete_repository = DeleteRepository() delete_repository = DeleteRepository()
return delete_repository.execute(usuario_schema) return delete_repository.execute(usuario_schema)

View file

@ -1,13 +1,10 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_get_by_descricao_repository import \ from packages.v1.administrativo.schemas.c_caixa_servico_schema import CCaixaServicoDescricaoSchema
ShowRepository from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_get_by_descricao_repository import ShowRepository
from packages.v1.administrativo.schemas.c_caixa_servico_schema import \
CCaixaServicoDescricaoSchema
class ShowAction(BaseAction): class ShowAction(BaseAction):
def execute(self, caixa_servico_schema: CCaixaServicoDescricaoSchema): def execute(self, caixa_servico_schema : CCaixaServicoDescricaoSchema):
# Instânciamento do repositório sql # Instânciamento do repositório sql
show_repository = ShowRepository() show_repository = ShowRepository()
@ -16,4 +13,4 @@ class ShowAction(BaseAction):
response = show_repository.execute(caixa_servico_schema) response = show_repository.execute(caixa_servico_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -0,0 +1,16 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.schemas.c_caixa_servico_schema import CCaixaServicoSistemaIdSchema
from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_get_by_sistema_id_repository import ShowSistemaIdRepository
class ShowSistemaIdAction(BaseAction):
def execute(self, caixa_servico_schema : CCaixaServicoSistemaIdSchema):
# Instânciamento do repositório sql
show_sistema_id_repository = ShowSistemaIdRepository()
# Execução do sql
response = show_sistema_id_repository.execute(caixa_servico_schema)
# Retorno da informação
return response

View file

@ -1,6 +1,7 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_index_repository import \ from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_index_repository import (
IndexRepository IndexRepository,
)
class IndexAction(BaseAction): class IndexAction(BaseAction):

View file

@ -1,7 +1,9 @@
from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_save_repository import \ from packages.v1.administrativo.schemas.c_caixa_servico_schema import (
SaveRepository CCaixaServicoSaveSchema,
from packages.v1.administrativo.schemas.c_caixa_servico_schema import \ )
CCaixaServicoSaveSchema from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_save_repository import (
SaveRepository,
)
class SaveAction: class SaveAction:

View file

@ -1,13 +1,10 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_show_repository import \ from packages.v1.administrativo.schemas.c_caixa_servico_schema import CCaixaServicoSchema
ShowRepository from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_show_repository import ShowRepository
from packages.v1.administrativo.schemas.c_caixa_servico_schema import \
CCaixaServicoSchema
class ShowAction(BaseAction): class ShowAction(BaseAction):
def execute(self, usuario_schema: CCaixaServicoSchema): def execute(self, usuario_schema : CCaixaServicoSchema):
# Instânciamento do repositório sql # Instânciamento do repositório sql
show_repository = ShowRepository() show_repository = ShowRepository()
@ -16,4 +13,4 @@ class ShowAction(BaseAction):
response = show_repository.execute(usuario_schema) response = show_repository.execute(usuario_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,15 +1,11 @@
from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_update_repository import \ from packages.v1.administrativo.schemas.c_caixa_servico_schema import CCaixaServicoUpdateSchema
UpdateRepository from packages.v1.administrativo.repositories.c_caixa_servico.c_caixa_servico_update_repository import UpdateRepository
from packages.v1.administrativo.schemas.c_caixa_servico_schema import \
CCaixaServicoUpdateSchema
class UpdateAction: class UpdateAction:
def execute( def execute(self, caixa_servico_id : int, c_caixa_servico_schema : CCaixaServicoUpdateSchema):
self, caixa_servico_id: int, c_caixa_servico_schema: CCaixaServicoUpdateSchema
):
save_repository = UpdateRepository() save_repository = UpdateRepository()
return save_repository.execute(caixa_servico_id, c_caixa_servico_schema) return save_repository.execute(caixa_servico_id, c_caixa_servico_schema)

View file

@ -0,0 +1,35 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cartorio.g_cartorio_delete_repository import (
GCartorioDeleteRepository,
)
from packages.v1.administrativo.schemas.g_cartorio_schema import GCartorioIdSchema
class GCartorioDeleteAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de exclusão de um registro na tabela G_CARTORIO.
"""
def execute(self, g_cartorio_id_schema: GCartorioIdSchema):
"""
Executa a operação de exclusão no banco de dados.
Args:
g_cartorio_id_schema (GCartorioIdSchema):
O esquema contendo o ID do registro a ser excluído.
Returns:
O resultado da operação de exclusão.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_cartorio_delete_repository = GCartorioDeleteRepository()
# ----------------------------------------------------
# Execução da exclusão
# ----------------------------------------------------
response = g_cartorio_delete_repository.execute(g_cartorio_id_schema)
return response

View file

@ -0,0 +1,37 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cartorio.g_cartorio_index_repository import (
GCartorioIndexRepository,
)
class GCartorioIndexAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de listagem de todos os registros na tabela G_NATUREZA_TITULO.
"""
def execute(self):
"""
Executa a operação de listagem no banco de dados.
Args:
g_cartorio_index_schema (GCartorioIndexSchema):
Esquema contendo parâmetros opcionais de filtro.
Returns:
A lista de registros encontrados.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_cartorio_index_repository = GCartorioIndexRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_cartorio_index_repository.execute()
# ----------------------------------------------------
# Retorno da informação
# --------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cartorio.g_cartorio_save_repository import (
GCartorioSaveRepository,
)
from packages.v1.administrativo.schemas.g_cartorio_schema import GCartorioSaveSchema
class GCartorioSaveAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de salvamento de um novo registro na tabela G_GRAMATICA.
"""
def execute(self, g_cartorio_save_schema: GCartorioSaveSchema):
"""
Executa a operação de salvamento.
Args:
g_cartorio_schema (GCartorioSchema):
O esquema com os dados a serem persistidos.
Returns:
O resultado da operação de salvamento.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_cartorio_save_repository = GCartorioSaveRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_cartorio_save_repository.execute(g_cartorio_save_schema)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cartorio.g_cartorio_show_repository import (
GCartorioShowRepository,
)
from packages.v1.administrativo.schemas.g_cartorio_schema import GCartorioIdSchema
class GCartorioShowAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a exibição
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_cartorio_id_schema: GCartorioIdSchema):
"""
Executa a operação de exibição.
Args:
g_cartorio_id_schema (GCartorioIdSchema):
O esquema com o ID do registro a ser exibido.
Returns:
O resultado da operação de exibição.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_cartorio_show_repository = GCartorioShowRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_cartorio_show_repository.execute(g_cartorio_id_schema)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cartorio.g_cartorio_update_repository import (
GCartorioUpdateRepository,
)
from packages.v1.administrativo.schemas.g_cartorio_schema import GCartorioUpdateSchema
class GCartorioUpdateAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_cartorio_update_schema: GCartorioUpdateSchema):
"""
Executa a operação de atualização.
Args:
g_cartorio_update_schema (GCartorioUpdateSchema):
O esquema com os dados a serem atualizados.
Returns:
O resultado da operação de atualização.
"""
# ----------------------------------------------------
# Instanciamento do repositório de atualização
# ----------------------------------------------------
g_cartorio_update_repository = GCartorioUpdateRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_cartorio_update_repository.execute(g_cartorio_update_schema)
# ----------------------------------------------------
# Retorno do resultado
# ----------------------------------------------------
return response

View file

@ -1,7 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cidade.g_cidade_delete_repository import \
DeleteRepository
from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema
from packages.v1.administrativo.repositories.g_cidade.g_cidade_delete_repository import DeleteRepository
class DeleteAction(BaseAction): class DeleteAction(BaseAction):
@ -24,4 +23,4 @@ class DeleteAction(BaseAction):
delete_repository = DeleteRepository() delete_repository = DeleteRepository()
# Execução do repositório # Execução do repositório
return delete_repository.execute(g_cidade_schema) return delete_repository.execute(g_cidade_schema)

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cidade.g_cidade_get_by_nome_repository import \ from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeNomeSchema
GetByNomeRepository from packages.v1.administrativo.repositories.g_cidade.g_cidade_get_by_nome_repository import GetByNomeRepository
from packages.v1.administrativo.schemas.g_cidade_schema import \
GCidadeNomeSchema
class GetByNomeAction(BaseAction): class GetByNomeAction(BaseAction):
@ -28,4 +26,4 @@ class GetByNomeAction(BaseAction):
response = show_repository.execute(g_cidade_schema) response = show_repository.execute(g_cidade_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,7 +1,5 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cidade.g_cidade_index_repository import \ from packages.v1.administrativo.repositories.g_cidade.g_cidade_index_repository import IndexRepository
IndexRepository
class IndexAction(BaseAction): class IndexAction(BaseAction):
""" """
@ -23,4 +21,4 @@ class IndexAction(BaseAction):
response = index_repository.execute() response = index_repository.execute()
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,9 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cidade.g_cidade_save_repository import \ from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeSaveSchema
SaveRepository from packages.v1.administrativo.repositories.g_cidade.g_cidade_save_repository import SaveRepository
from packages.v1.administrativo.schemas.g_cidade_schema import \
GCidadeSaveSchema
class SaveAction(BaseAction): class SaveAction(BaseAction):
""" """
@ -28,4 +25,4 @@ class SaveAction(BaseAction):
response = save_repository.execute(g_cidade_schema) response = save_repository.execute(g_cidade_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_cidade.g_cidade_show_repository import \
ShowRepository
from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeIdSchema
from packages.v1.administrativo.repositories.g_cidade.g_cidade_show_repository import ShowRepository
class ShowAction(BaseAction): class ShowAction(BaseAction):
""" """
@ -13,7 +11,7 @@ class ShowAction(BaseAction):
def execute(self, g_cidade_schema: GCidadeIdSchema): def execute(self, g_cidade_schema: GCidadeIdSchema):
""" """
Executa a operação de exibição. Executa a operação de exibição.
Args: Args:
g_cidade_schema (GCidadeIdSchema): O esquema com o ID (CIDADE_ID) do registro a ser exibido. g_cidade_schema (GCidadeIdSchema): O esquema com o ID (CIDADE_ID) do registro a ser exibido.
@ -27,4 +25,4 @@ class ShowAction(BaseAction):
response = show_repository.execute(g_cidade_schema) response = show_repository.execute(g_cidade_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,13 +1,11 @@
from packages.v1.administrativo.repositories.g_cidade.g_cidade_update_repository import \ from packages.v1.administrativo.schemas.g_cidade_schema import GCidadeUpdateSchema
UpdateRepository from packages.v1.administrativo.repositories.g_cidade.g_cidade_update_repository import UpdateRepository
from packages.v1.administrativo.schemas.g_cidade_schema import \
GCidadeUpdateSchema
class UpdateAction: class UpdateAction:
""" """
Serviço responsável por encapsular a lógica de negócio para a atualização Serviço responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela G_CIDADE. de um registro na tabela G_CIDADE.
""" """
def execute(self, cidade_id: int, g_cidade_schema: GCidadeUpdateSchema): def execute(self, cidade_id: int, g_cidade_schema: GCidadeUpdateSchema):
@ -25,4 +23,4 @@ class UpdateAction:
update_repository = UpdateRepository() update_repository = UpdateRepository()
# Chama o método de execução do repositório para realizar a atualização # Chama o método de execução do repositório para realizar a atualização
return update_repository.execute(cidade_id, g_cidade_schema) return update_repository.execute(cidade_id, g_cidade_schema)

View file

@ -0,0 +1,35 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento.g_emolumento_delete_repository import (
GEmolumentoDeleteRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_schema import GEmolumentoIdSchema
class GEmolumentoDeleteAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de exclusão de um registro na tabela G_EMOLUMENTO.
"""
def execute(self, g_emolumento_id_schema: GEmolumentoIdSchema):
"""
Executa a operação de exclusão no banco de dados.
Args:
g_emolumento_id_schema (GEmolumentoIdSchema):
O esquema contendo o ID do registro a ser excluído.
Returns:
O resultado da operação de exclusão.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_delete_repository = GEmolumentoDeleteRepository()
# ----------------------------------------------------
# Execução da exclusão
# ----------------------------------------------------
response = g_emolumento_delete_repository.execute(g_emolumento_id_schema)
return response

View file

@ -0,0 +1,44 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento.g_emolumento_index_by_sistema_id_repository import (
GEmolumentoIndexBySistemaIdRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_schema import (
GEmolumentoSistemaIdSchema,
)
class GEmolumentoIndexBySistemaIdAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a exibição
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_emolumento_sistema_id_schema: GEmolumentoSistemaIdSchema):
"""
Executa a operação de exibição.
Args:
g_emolumento_id_schema (GEmolumentoIdSchema):
O esquema com o ID do registro a ser exibido.
Returns:
O resultado da operação de exibição.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_index_by_sistema_id_repository = (
GEmolumentoIndexBySistemaIdRepository()
)
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_index_by_sistema_id_repository.execute(
g_emolumento_sistema_id_schema
)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento.g_emolumento_save_repository import (
GEmolumentoSaveRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_schema import GEmolumentoSaveSchema
class GEmolumentoSaveAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de salvamento de um novo registro na tabela G_EMOLUMENTO.
"""
def execute(self, g_emolumento_save_schema: GEmolumentoSaveSchema):
"""
Executa a operação de salvamento.
Args:
g_emolumento_schema (GEmolumentoSchema):
O esquema com os dados a serem persistidos.
Returns:
O resultado da operação de salvamento.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_save_repository = GEmolumentoSaveRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_save_repository.execute(g_emolumento_save_schema)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento.g_emolumento_show_repository import (
GEmolumentoShowRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_schema import GEmolumentoIdSchema
class GEmolumentoShowAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a exibição
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_emolumento_id_schema: GEmolumentoIdSchema):
"""
Executa a operação de exibição.
Args:
g_emolumento_id_schema (GEmolumentoIdSchema):
O esquema com o ID do registro a ser exibido.
Returns:
O resultado da operação de exibição.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_show_repository = GEmolumentoShowRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_show_repository.execute(g_emolumento_id_schema)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,40 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento.g_emolumento_update_repository import (
GEmolumentoUpdateRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_schema import (
GEmolumentoUpdateSchema,
)
class GEmolumentoUpdateAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_emolumento_update_schema: GEmolumentoUpdateSchema):
"""
Executa a operação de atualização.
Args:
g_emolumento_update_schema (GEmolumentoUpdateSchema):
O esquema com os dados a serem atualizados.
Returns:
O resultado da operação de atualização.
"""
# ----------------------------------------------------
# Instanciamento do repositório de atualização
# ----------------------------------------------------
g_emolumento_update_repository = GEmolumentoUpdateRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_update_repository.execute(g_emolumento_update_schema)
# ----------------------------------------------------
# Retorno do resultado
# ----------------------------------------------------
return response

View file

@ -0,0 +1,39 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_item.g_emolumento_item_delete_repository import (
GEmolumentoItemDeleteRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_item_schema import (
GEmolumentoItemIdSchema,
)
class GEmolumentoItemDeleteAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de exclusão de um registro na tabela G_EMOLUMENTO_ITEM.
"""
def execute(self, g_emolumento_item_id_schema: GEmolumentoItemIdSchema):
"""
Executa a operação de exclusão no banco de dados.
Args:
g_emolumento_item_id_schema (GEmolumentoItemIdSchema):
O esquema contendo o ID do registro a ser excluído.
Returns:
O resultado da operação de exclusão.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_item_delete_repository = GEmolumentoItemDeleteRepository()
# ----------------------------------------------------
# Execução da exclusão
# ----------------------------------------------------
response = g_emolumento_item_delete_repository.execute(
g_emolumento_item_id_schema
)
return response

View file

@ -0,0 +1,74 @@
from __future__ import annotations
from decimal import Decimal
from typing import Iterable, Optional, Protocol, Any
class EmolumentoItemLike(Protocol):
"""Protocolo mínimo esperado para um item de emolumento."""
valor_inicio: Optional[Decimal]
valor_fim: Optional[Decimal]
class GEmolumentoItemGetFaixaValorAction:
"""
Responsável por escolher, dentre uma coleção de itens de emolumento,
aquele cuja faixa [valor_inicio, valor_fim] contem o valor_documento.
- Se houver mais de um candidato, prioriza o de maior valor_inicio (faixa mais específica).
- Se não houver faixa que contenha o valor_documento, tenta a faixa 'aberta' (valor_fim nulo).
- Persistindo a ausência, retorna o item cujo valor_inicio é o mais próximo abaixo do valor_documento.
"""
@staticmethod
def _para_decimal(valor: Any, padrao: str = "0") -> Decimal:
return valor if isinstance(valor, Decimal) else Decimal(str(valor or padrao))
def execute(
self,
itens: Iterable[EmolumentoItemLike],
valor_documento: Decimal,
) -> EmolumentoItemLike:
lista = list(itens)
if not lista:
raise ValueError("Nenhum item de emolumento foi informado.")
valor_doc = self._para_decimal(valor_documento)
candidatos: list[tuple[Decimal, Decimal, EmolumentoItemLike]] = []
abertos: list[tuple[Decimal, EmolumentoItemLike]] = []
abaixo: list[tuple[Decimal, EmolumentoItemLike]] = []
for item in lista:
ini = self._para_decimal(getattr(item, "valor_inicio", None))
fim_raw = getattr(item, "valor_fim", None)
fim = (
self._para_decimal(fim_raw, padrao="Infinity")
if fim_raw is not None
else Decimal("Infinity")
)
if ini <= valor_doc <= fim:
candidatos.append((ini, fim, item))
elif fim == Decimal("Infinity") and ini <= valor_doc:
abertos.append((ini, item))
elif ini <= valor_doc:
abaixo.append((ini, item))
if candidatos:
candidatos.sort(key=lambda t: (t[0], t[1])) # maior ini e menor fim
return candidatos[-1][2]
if abertos:
abertos.sort(key=lambda t: t[0]) # maior ini
return abertos[-1][1]
if abaixo:
abaixo.sort(key=lambda t: t[0]) # maior ini
return abaixo[-1][1]
# Fallback: não há faixa adequada nem valores abaixo; devolve o de menor valor_inicio
lista_ordenada = sorted(
lista, key=lambda it: self._para_decimal(getattr(it, "valor_inicio", None))
)
return lista_ordenada[0]

View file

@ -0,0 +1,44 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_item.g_emolumento_item_index_repository import (
GEmolumentoItemIndexRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_item_schema import (
GEmolumentoItemIndexSchema,
)
class GEmolumentoItemIndexAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de listagem de todos os registros na tabela G_NATUREZA_TITULO.
"""
def execute(
self, g_emolumento_item_emolumento_index_schema: GEmolumentoItemIndexSchema
):
"""
Executa a operação de listagem no banco de dados.
Args:
g_emolumento_item_index_schema (GEmolumentoItemIndexSchema):
Esquema contendo parâmetros opcionais de filtro.
Returns:
A lista de registros encontrados.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_item_index_repository = GEmolumentoItemIndexRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_item_index_repository.execute(
g_emolumento_item_emolumento_index_schema
)
# ----------------------------------------------------
# Retorno da informação
# --------------------------------
return response

View file

@ -0,0 +1,36 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_item.g_emolumento_item_save_repository import GEmolumentoItemSaveRepository
from packages.v1.administrativo.schemas.g_emolumento_item_schema import GEmolumentoItemSaveSchema
class GEmolumentoItemSaveAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de salvamento de um novo registro na tabela G_EMOLUMENTO_ITEM.
"""
def execute(self, g_emolumento_item_save_schema: GEmolumentoItemSaveSchema):
"""
Executa a operação de salvamento.
Args:
g_emolumento_item_schema (GEmolumentoItemSchema):
O esquema com os dados a serem persistidos.
Returns:
O resultado da operação de salvamento.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_item_save_repository = GEmolumentoItemSaveRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_item_save_repository.execute(g_emolumento_item_save_schema)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,42 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_item.g_emolumento_item_show_repository import (
GEmolumentoItemShowRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_item_schema import (
GEmolumentoItemIdSchema,
)
class GEmolumentoItemShowAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a exibição
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_emolumento_item_id_schema: GEmolumentoItemIdSchema):
"""
Executa a operação de exibição.
Args:
g_emolumento_item_id_schema (GEmolumentoItemIdSchema):
O esquema com o ID do registro a ser exibido.
Returns:
O resultado da operação de exibição.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_item_show_repository = GEmolumentoItemShowRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_item_show_repository.execute(
g_emolumento_item_id_schema
)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,42 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_item.g_emolumento_item_update_repository import (
GEmolumentoItemUpdateRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_item_schema import (
GEmolumentoItemUpdateSchema,
)
class GEmolumentoItemUpdateAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_emolumento_item_update_schema: GEmolumentoItemUpdateSchema):
"""
Executa a operação de atualização.
Args:
g_emolumento_item_update_schema (GEmolumentoItemUpdateSchema):
O esquema com os dados a serem atualizados.
Returns:
O resultado da operação de atualização.
"""
# ----------------------------------------------------
# Instanciamento do repositório de atualização
# ----------------------------------------------------
g_emolumento_item_update_repository = GEmolumentoItemUpdateRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_item_update_repository.execute(
g_emolumento_item_update_schema
)
# ----------------------------------------------------
# Retorno do resultado
# ----------------------------------------------------
return response

View file

@ -0,0 +1,44 @@
from abstracts.action import BaseAction
# O Schema precisa ser adaptado para GEmolumentoItem, talvez recebendo um ID de Emolumento
# ou um ID do próprio Item, dependendo da necessidade de listagem.
# Vamos sugerir um Schema específico para a listagem (Index) que pode receber um Emolumento ID
# para listar todos os seus itens, mantendo o padrão do arquivo original que usava um 'SistemaIdSchema'.
# Para simplificar, vamos assumir um schema de filtro ou um schema base para Index.
# Sugerimos a criação de:
# from packages.v1.administrativo.schemas.g_emolumento_item_schema import GEmolumentoItemIndexSchema
# (ou GEmolumentoItemEmolumentoIdSchema se for o padrão da aplicação)
from packages.v1.administrativo.schemas.g_emolumento_item_schema import GEmolumentoItemValorSchema
# O repositório ValorRepository deve ser substituído pelo GEmolumentoItemValorRepository.
from packages.v1.administrativo.repositories.g_emolumento_item.g_emolumento_item_valor_repository import ValorRepository
class ValorAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de listagem de todos os registros na tabela G_EMOLUMENTO_ITEM,
utilizando a DDL fornecida.
"""
# Mantendo o padrão de nome de método do arquivo original
def execute(self, emolumento_item_schema: GEmolumentoItemValorSchema):
"""
Executa a operação de listagem de G_EMOLUMENTO_ITEM no banco de dados.
Args:
emolumento_item_schema: Esquema com parâmetros de filtro/listagem
(por exemplo, ID do Emolumento pai, se a listagem for
filtrada por ele, ou parâmetros de paginação).
Returns:
A lista de todos os registros de G_EMOLUMENTO_ITEM que satisfazem o filtro.
"""
# Instanciamento do repositório
# O nome do repositório foi adaptado com o prefixo 'GEmolumentoItem'
index_repository = ValorRepository()
# Execução do repositório
# O nome do parâmetro foi adaptado para 'emolumento_item_schema'
response = index_repository.execute(emolumento_item_schema)
# Retorno da informação
return response

View file

@ -0,0 +1,39 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_periodo.g_emolumento_periodo_delete_repository import (
GEmolumentoPeriodoDeleteRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_periodo_schema import (
GEmolumentoPeriodoIdSchema,
)
class GEmolumentoPeriodoDeleteAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de exclusão de um registro na tabela G_EMOLUMENTO_PERIODO.
"""
def execute(self, g_emolumento_periodo_id_schema: GEmolumentoPeriodoIdSchema):
"""
Executa a operação de exclusão no banco de dados.
Args:
g_emolumento_periodo_id_schema (GEmolumentoPeriodoIdSchema):
O esquema contendo o ID do registro a ser excluído.
Returns:
O resultado da operação de exclusão.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_periodo_delete_repository = GEmolumentoPeriodoDeleteRepository()
# ----------------------------------------------------
# Execução da exclusão
# ----------------------------------------------------
response = g_emolumento_periodo_delete_repository.execute(
g_emolumento_periodo_id_schema
)
return response

View file

@ -0,0 +1,37 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_periodo.g_emolumento_periodo_index_repository import (
GEmolumentoPeriodoIndexRepository,
)
class GEmolumentoPeriodoIndexAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de listagem de todos os registros na tabela G_NATUREZA_TITULO.
"""
def execute(self):
"""
Executa a operação de listagem no banco de dados.
Args:
g_emolumento_periodo_index_schema (GEmolumentoPeriodoIndexSchema):
Esquema contendo parâmetros opcionais de filtro.
Returns:
A lista de registros encontrados.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_periodo_index_repository = GEmolumentoPeriodoIndexRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_periodo_index_repository.execute()
# ----------------------------------------------------
# Retorno da informação
# --------------------------------
return response

View file

@ -0,0 +1,42 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_periodo.g_emolumento_periodo_save_repository import (
GEmolumentoPeriodoSaveRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_periodo_schema import (
GEmolumentoPeriodoSaveSchema,
)
class GEmolumentoPeriodoSaveAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de salvamento de um novo registro na tabela G_GRAMATICA.
"""
def execute(self, g_emolumento_periodo_save_schema: GEmolumentoPeriodoSaveSchema):
"""
Executa a operação de salvamento.
Args:
g_emolumento_periodo_schema (GEmolumentoPeriodoSchema):
O esquema com os dados a serem persistidos.
Returns:
O resultado da operação de salvamento.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_periodo_save_repository = GEmolumentoPeriodoSaveRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_periodo_save_repository.execute(
g_emolumento_periodo_save_schema
)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,42 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_periodo.g_emolumento_periodo_show_repository import (
GEmolumentoPeriodoShowRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_periodo_schema import (
GEmolumentoPeriodoIdSchema,
)
class GEmolumentoPeriodoShowAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a exibição
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_emolumento_periodo_id_schema: GEmolumentoPeriodoIdSchema):
"""
Executa a operação de exibição.
Args:
g_emolumento_periodo_id_schema (GEmolumentoPeriodoIdSchema):
O esquema com o ID do registro a ser exibido.
Returns:
O resultado da operação de exibição.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_emolumento_periodo_show_repository = GEmolumentoPeriodoShowRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_periodo_show_repository.execute(
g_emolumento_periodo_id_schema
)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,44 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_emolumento_periodo.g_emolumento_periodo_update_repository import (
GEmolumentoPeriodoUpdateRepository,
)
from packages.v1.administrativo.schemas.g_emolumento_periodo_schema import (
GEmolumentoPeriodoUpdateSchema,
)
class GEmolumentoPeriodoUpdateAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(
self, g_emolumento_periodo_update_schema: GEmolumentoPeriodoUpdateSchema
):
"""
Executa a operação de atualização.
Args:
g_emolumento_periodo_update_schema (GEmolumentoPeriodoUpdateSchema):
O esquema com os dados a serem atualizados.
Returns:
O resultado da operação de atualização.
"""
# ----------------------------------------------------
# Instanciamento do repositório de atualização
# ----------------------------------------------------
g_emolumento_periodo_update_repository = GEmolumentoPeriodoUpdateRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_emolumento_periodo_update_repository.execute(
g_emolumento_periodo_update_schema
)
# ----------------------------------------------------
# Retorno do resultado
# ----------------------------------------------------
return response

View file

@ -0,0 +1,35 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_gramatica.g_gramatica_delete_repository import (
GGramaticaDeleteRepository,
)
from packages.v1.administrativo.schemas.g_gramatica_schema import GGramaticaIdSchema
class GGramaticaDeleteAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de exclusão de um registro na tabela G_GRAMATICA.
"""
def execute(self, g_gramatica_id_schema: GGramaticaIdSchema):
"""
Executa a operação de exclusão no banco de dados.
Args:
g_gramatica_id_schema (GGramaticaIdSchema):
O esquema contendo o ID do registro a ser excluído.
Returns:
O resultado da operação de exclusão.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_gramatica_delete_repository = GGramaticaDeleteRepository()
# ----------------------------------------------------
# Execução da exclusão
# ----------------------------------------------------
response = g_gramatica_delete_repository.execute(g_gramatica_id_schema)
return response

View file

@ -0,0 +1,37 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_gramatica.g_gramatica_index_repository import (
GGramaticaIndexRepository,
)
class GGramaticaIndexAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de listagem de todos os registros na tabela G_NATUREZA_TITULO.
"""
def execute(self):
"""
Executa a operação de listagem no banco de dados.
Args:
g_gramatica_index_schema (GGramaticaIndexSchema):
Esquema contendo parâmetros opcionais de filtro.
Returns:
A lista de registros encontrados.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_gramatica_index_repository = GGramaticaIndexRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_gramatica_index_repository.execute()
# ----------------------------------------------------
# Retorno da informação
# --------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_gramatica.g_gramatica_save_repository import (
GGramaticaSaveRepository,
)
from packages.v1.administrativo.schemas.g_gramatica_schema import GGramaticaSaveSchema
class GGramaticaSaveAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de salvamento de um novo registro na tabela G_GRAMATICA.
"""
def execute(self, g_gramatica_save_schema: GGramaticaSaveSchema):
"""
Executa a operação de salvamento.
Args:
g_gramatica_schema (GGramaticaSchema):
O esquema com os dados a serem persistidos.
Returns:
O resultado da operação de salvamento.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_gramatica_save_repository = GGramaticaSaveRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_gramatica_save_repository.execute(g_gramatica_save_schema)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_gramatica.g_gramatica_show_repository import (
GGramaticaShowRepository,
)
from packages.v1.administrativo.schemas.g_gramatica_schema import GGramaticaIdSchema
class GGramaticaShowAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a exibição
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_gramatica_id_schema: GGramaticaIdSchema):
"""
Executa a operação de exibição.
Args:
g_gramatica_id_schema (GGramaticaIdSchema):
O esquema com o ID do registro a ser exibido.
Returns:
O resultado da operação de exibição.
"""
# ----------------------------------------------------
# Instanciamento do repositório
# ----------------------------------------------------
g_gramatica_show_repository = GGramaticaShowRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_gramatica_show_repository.execute(g_gramatica_id_schema)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return response

View file

@ -0,0 +1,38 @@
from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_gramatica.g_gramatica_update_repository import (
GGramaticaUpdateRepository,
)
from packages.v1.administrativo.schemas.g_gramatica_schema import GGramaticaUpdateSchema
class GGramaticaUpdateAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela G_NATUREZA_TITULO.
"""
def execute(self, g_gramatica_update_schema: GGramaticaUpdateSchema):
"""
Executa a operação de atualização.
Args:
g_gramatica_update_schema (GGramaticaUpdateSchema):
O esquema com os dados a serem atualizados.
Returns:
O resultado da operação de atualização.
"""
# ----------------------------------------------------
# Instanciamento do repositório de atualização
# ----------------------------------------------------
g_gramatica_update_repository = GGramaticaUpdateRepository()
# ----------------------------------------------------
# Execução do repositório
# ----------------------------------------------------
response = g_gramatica_update_repository.execute(g_gramatica_update_schema)
# ----------------------------------------------------
# Retorno do resultado
# ----------------------------------------------------
return response

View file

@ -1,11 +1,9 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
# O repositório TServicoTipoDeleteRepository deve ser substituído pelo GMarcacaoTipoDeleteRepository.
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_delete_repository import \
DeleteRepository
# O schema TServicoTipoIdSchema deve ser substituído por GMarcacaoTipoIdSchema # O schema TServicoTipoIdSchema deve ser substituído por GMarcacaoTipoIdSchema
# que contém o campo-chave MARCACAO_TIPO_ID. # que contém o campo-chave MARCACAO_TIPO_ID.
from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import \ from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import GMarcacaoTipoIdSchema
GMarcacaoTipoIdSchema # O repositório TServicoTipoDeleteRepository deve ser substituído pelo GMarcacaoTipoDeleteRepository.
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_delete_repository import DeleteRepository
class DeleteAction(BaseAction): class DeleteAction(BaseAction):
@ -28,4 +26,4 @@ class DeleteAction(BaseAction):
delete_repository = DeleteRepository() delete_repository = DeleteRepository()
# Execução do repositório # Execução do repositório
return delete_repository.execute(marcacao_tipo_schema) return delete_repository.execute(marcacao_tipo_schema)

View file

@ -1,10 +1,8 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
# Ajuste do repositório
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_get_by_descricao_repository import \
GetByDescricaoRepository
# Ajuste do schema de entrada # Ajuste do schema de entrada
from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import \ from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import GMarcacaoTipoDescricaoSchema
GMarcacaoTipoDescricaoSchema # Ajuste do repositório
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_get_by_descricao_repository import GetByDescricaoRepository
class GetByDescricaoAction(BaseAction): class GetByDescricaoAction(BaseAction):
@ -30,4 +28,4 @@ class GetByDescricaoAction(BaseAction):
response = show_repository.execute(marcacao_tipo_schema) response = show_repository.execute(marcacao_tipo_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -0,0 +1,31 @@
from abstracts.action import BaseAction
# Ajuste do schema de entrada
from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import GMarcacaoTipoGrupoSchema
# Ajuste do repositório
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_get_by_grupo_repository import GetByGrupoRepository
class GetByGrupoAction(BaseAction):
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de busca de um registro na tabela G_MARCACAO_TIPO por filtro.
"""
def execute(self, marcacao_tipo_schema: GMarcacaoTipoGrupoSchema):
"""
Executa a operação de busca no banco de dados.
Args:
marcacao_tipo_schema (GMarcacaoTipoGrupoSchema): O esquema com os filtros a serem buscados.
Returns:
O registro encontrado ou None.
"""
# Instanciamento do repositório
show_repository = GetByGrupoRepository()
# Execução do repositório
response = show_repository.execute(marcacao_tipo_schema)
# Retorno da informação
return response

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
# O repositório TServicoTipoIndexRepository deve ser substituído pelo GMarcacaoTipoIndexRepository. # O repositório TServicoTipoIndexRepository deve ser substituído pelo GMarcacaoTipoIndexRepository.
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_index_repository import \ from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_index_repository import IndexRepository
IndexRepository
class IndexAction(BaseAction): class IndexAction(BaseAction):
""" """
@ -24,4 +22,4 @@ class IndexAction(BaseAction):
response = index_repository.execute() response = index_repository.execute()
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,11 +1,8 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
# Ajuste do repositório
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_save_repository import \
SaveRepository
# Ajuste do schema de entrada # Ajuste do schema de entrada
from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import \ from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import GMarcacaoTipoSaveSchema
GMarcacaoTipoSaveSchema # Ajuste do repositório
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_save_repository import SaveRepository
class SaveAction(BaseAction): class SaveAction(BaseAction):
""" """
@ -30,4 +27,4 @@ class SaveAction(BaseAction):
response = save_repository.execute(marcacao_tipo_schema) response = save_repository.execute(marcacao_tipo_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,11 +1,8 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
# Ajuste do repositório
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_show_repository import \
ShowRepository
# Ajuste do schema de entrada # Ajuste do schema de entrada
from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import \ from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import GMarcacaoTipoIdSchema
GMarcacaoTipoIdSchema # Ajuste do repositório
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_show_repository import ShowRepository
class ShowAction(BaseAction): class ShowAction(BaseAction):
""" """
@ -16,7 +13,7 @@ class ShowAction(BaseAction):
def execute(self, marcacao_tipo_schema: GMarcacaoTipoIdSchema): def execute(self, marcacao_tipo_schema: GMarcacaoTipoIdSchema):
""" """
Executa a operação de exibição. Executa a operação de exibição.
Args: Args:
marcacao_tipo_schema (GMarcacaoTipoIdSchema): O esquema com o ID (MARCACAO_TIPO_ID) do registro a ser exibido. marcacao_tipo_schema (GMarcacaoTipoIdSchema): O esquema com o ID (MARCACAO_TIPO_ID) do registro a ser exibido.
@ -30,4 +27,4 @@ class ShowAction(BaseAction):
response = show_repository.execute(marcacao_tipo_schema) response = show_repository.execute(marcacao_tipo_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,22 +1,16 @@
# Importação do Schema ajustada # Importação do Schema ajustada
from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import GMarcacaoTipoUpdateSchema
# Importação do Repositório ajustada # Importação do Repositório ajustada
from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_update_repository import \ from packages.v1.administrativo.repositories.g_marcacao_tipo.g_marcacao_tipo_update_repository import UpdateRepository
UpdateRepository
from packages.v1.administrativo.schemas.g_marcacao_tipo_schema import \
GMarcacaoTipoUpdateSchema
# A classe UpdateAction não herda de BaseAction no arquivo original, mantemos o padrão. # A classe UpdateAction não herda de BaseAction no arquivo original, mantemos o padrão.
class UpdateAction: class UpdateAction:
""" """
Service responsável por encapsular a lógica de negócio para a atualização Service responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela G_MARCACAO_TIPO. de um registro na tabela G_MARCACAO_TIPO.
""" """
def execute( def execute(self, marcacao_tipo_id: int, marcacao_tipo_schema: GMarcacaoTipoUpdateSchema):
self, marcacao_tipo_id: int, marcacao_tipo_schema: GMarcacaoTipoUpdateSchema
):
""" """
Executa a operação de atualização. Executa a operação de atualização.
@ -31,4 +25,4 @@ class UpdateAction:
update_repository = UpdateRepository() update_repository = UpdateRepository()
# Chama o método de execução do repositório para realizar a atualização # Chama o método de execução do repositório para realizar a atualização
return update_repository.execute(marcacao_tipo_id, marcacao_tipo_schema) return update_repository.execute(marcacao_tipo_id, marcacao_tipo_schema)

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_delete_repository import \ from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema
DeleteRepository from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_delete_repository import DeleteRepository
from packages.v1.administrativo.schemas.g_medida_tipo_schema import \
GMedidaTipoIdSchema
class DeleteAction(BaseAction): class DeleteAction(BaseAction):
@ -25,4 +23,4 @@ class DeleteAction(BaseAction):
delete_repository = DeleteRepository() delete_repository = DeleteRepository()
# Execução do repositório # Execução do repositório
return delete_repository.execute(medida_tipo_schema) return delete_repository.execute(medida_tipo_schema)

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_get_by_descricao_repository import \ from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoDescricaoSchema
GetByDescricaoRepository from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_get_by_descricao_repository import GetByDescricaoRepository
from packages.v1.administrativo.schemas.g_medida_tipo_schema import \
GMedidaTipoDescricaoSchema
class GetByDescricaoAction(BaseAction): class GetByDescricaoAction(BaseAction):
@ -28,4 +26,4 @@ class GetByDescricaoAction(BaseAction):
response = show_repository.execute(medida_tipo_schema) response = show_repository.execute(medida_tipo_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,7 +1,5 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_index_repository import \ from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_index_repository import IndexRepository
IndexRepository
class IndexAction(BaseAction): class IndexAction(BaseAction):
""" """
@ -23,4 +21,4 @@ class IndexAction(BaseAction):
response = index_repository.execute() response = index_repository.execute()
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,9 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_save_repository import \ from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoSaveSchema
SaveRepository from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_save_repository import SaveRepository
from packages.v1.administrativo.schemas.g_medida_tipo_schema import \
GMedidaTipoSaveSchema
class SaveAction(BaseAction): class SaveAction(BaseAction):
""" """
@ -28,4 +25,4 @@ class SaveAction(BaseAction):
response = save_repository.execute(medida_tipo_schema) response = save_repository.execute(medida_tipo_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,9 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_show_repository import \ from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoIdSchema
ShowRepository from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_show_repository import ShowRepository
from packages.v1.administrativo.schemas.g_medida_tipo_schema import \
GMedidaTipoIdSchema
class ShowAction(BaseAction): class ShowAction(BaseAction):
""" """
@ -14,7 +11,7 @@ class ShowAction(BaseAction):
def execute(self, medida_tipo_schema: GMedidaTipoIdSchema): def execute(self, medida_tipo_schema: GMedidaTipoIdSchema):
""" """
Executa a operação de exibição. Executa a operação de exibição.
Args: Args:
medida_tipo_schema (GMedidaTipoIdSchema): O esquema com o ID do registro a ser exibido. medida_tipo_schema (GMedidaTipoIdSchema): O esquema com o ID do registro a ser exibido.
@ -28,4 +25,4 @@ class ShowAction(BaseAction):
response = show_repository.execute(medida_tipo_schema) response = show_repository.execute(medida_tipo_schema)
# Retorno da informação # Retorno da informação
return response return response

View file

@ -1,13 +1,11 @@
from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_update_repository import \ from packages.v1.administrativo.schemas.g_medida_tipo_schema import GMedidaTipoUpdateSchema
UpdateRepository from packages.v1.administrativo.repositories.g_medida_tipo.g_medida_tipo_update_repository import UpdateRepository
from packages.v1.administrativo.schemas.g_medida_tipo_schema import \
GMedidaTipoUpdateSchema
class UpdateAction: class UpdateAction:
""" """
Service responsável por encapsular a lógica de negócio para a atualização Service responsável por encapsular a lógica de negócio para a atualização
de um registro na tabela g_medida_tipo. de um registro na tabela g_medida_tipo.
""" """
def execute(self, medida_tipo_id: int, medida_tipo_schema: GMedidaTipoUpdateSchema): def execute(self, medida_tipo_id: int, medida_tipo_schema: GMedidaTipoUpdateSchema):
@ -25,4 +23,4 @@ class UpdateAction:
update_repository = UpdateRepository() update_repository = UpdateRepository()
# Chama o método de execução do repositório para realizar a atualização # Chama o método de execução do repositório para realizar a atualização
return update_repository.execute(medida_tipo_id, medida_tipo_schema) return update_repository.execute(medida_tipo_id, medida_tipo_schema)

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_natureza.g_natureza_delete_repository import \ from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaIdSchema
DeleteRepository from packages.v1.administrativo.repositories.g_natureza.g_natureza_delete_repository import DeleteRepository
from packages.v1.administrativo.schemas.g_natureza_schema import \
GNaturezaIdSchema
class DeleteAction(BaseAction): class DeleteAction(BaseAction):
@ -25,4 +23,4 @@ class DeleteAction(BaseAction):
delete_repository = DeleteRepository() delete_repository = DeleteRepository()
# Execução do repositório # Execução do repositório
return delete_repository.execute(natureza_schema) return delete_repository.execute(natureza_schema)

View file

@ -1,8 +1,6 @@
from abstracts.action import BaseAction from abstracts.action import BaseAction
from packages.v1.administrativo.repositories.g_natureza.g_natureza_get_by_descricao_repository import \ from packages.v1.administrativo.schemas.g_natureza_schema import GNaturezaDescricaoSchema
GetByDescricaoRepository from packages.v1.administrativo.repositories.g_natureza.g_natureza_get_by_descricao_repository import GetByDescricaoRepository
from packages.v1.administrativo.schemas.g_natureza_schema import \
GNaturezaDescricaoSchema
class GetByDescricaoAction(BaseAction): class GetByDescricaoAction(BaseAction):
@ -28,4 +26,4 @@ class GetByDescricaoAction(BaseAction):
response = show_repository.execute(natureza_schema) response = show_repository.execute(natureza_schema)
# Retorno da informação # Retorno da informação
return response return response

Some files were not shown because too many files have changed in this diff Show more