[MVPTN-126] feat(Item): Adiciona o processamento de itens enviados através do pedido

This commit is contained in:
Keven 2025-11-08 20:35:02 -03:00
parent 0339cffc21
commit f836daa07c
25 changed files with 811 additions and 194 deletions

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,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}")

View file

@ -5,6 +5,7 @@ from actions.jwt.verify_token import VerifyToken # A classe que criamos anterio
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") # Apenas requerido pelo FastAPI oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") # Apenas requerido pelo FastAPI
def get_current_user(token: str = Depends(oauth2_scheme)): def get_current_user(token: str = Depends(oauth2_scheme)):
# Ação que válida o tokne # Ação que válida o tokne
@ -13,12 +14,12 @@ def get_current_user(token: str = Depends(oauth2_scheme)):
result = verify_token.execute(token) result = verify_token.execute(token)
# Verifica se a resposta é diferente de inválida # Verifica se a resposta é diferente de inválida
if result['status'] != 'valid': if result["status"] != "valid":
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail=result.get('message', 'Token inválido ou expirado'), detail=result.get("message", "Token inválido ou expirado"),
headers={"WWW-Authenticate": "Bearer"}, headers={"WWW-Authenticate": "Bearer"},
) )
# Retorna apenas os dados do token # Retorna apenas os dados do token
return result['payload'] return result["payload"]

View file

@ -0,0 +1,12 @@
from typing import Any, Optional
from fastapi import Depends, 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()

11
main.py
View file

@ -3,6 +3,8 @@ import os
import platform 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__), "..")))
@ -53,6 +55,15 @@ app.add_middleware(
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.on_event("startup") @app.on_event("startup")
async def on_startup(): async def on_startup():

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

@ -1,6 +1,7 @@
from actions.dynamic_import.dynamic_import import DynamicImport from actions.dynamic_import.dynamic_import import DynamicImport
from packages.v1.administrativo.schemas.g_calculo_schema import ( from packages.v1.administrativo.schemas.g_calculo_schema import (
GCalculoRapidoSchema, GCalculoRapidoSchema,
GCalculoServico,
) )
@ -32,3 +33,23 @@ class GCalculoController:
"message": "Cálculo realizado com sucesso", "message": "Cálculo realizado com sucesso",
"data": self.rapido_service.execute(g_calculo_rapido_schema), "data": self.rapido_service.execute(g_calculo_rapido_schema),
} }
# ----------------------------------------------------
# Lista todos os registros de G_EMOLUMENTO
# ----------------------------------------------------
def servico(self, g_calculo_servico: GCalculoServico):
# Importação da classe desejada
service = self.dynamic_import.service(
"g_calculo_servico_service", "GCalculoServicoService"
)
# Instância da classe service
self.service = service()
# Execução da listagem
return {
"message": "Cálculo realizado com sucesso",
"data": self.service.execute(g_calculo_servico),
}

View file

@ -1,6 +1,7 @@
from actions.dynamic_import.dynamic_import import DynamicImport from actions.dynamic_import.dynamic_import import DynamicImport
from packages.v1.administrativo.schemas.g_emolumento_schema import ( from packages.v1.administrativo.schemas.g_emolumento_schema import (
GEmolumentoSaveSchema, GEmolumentoSaveSchema,
GEmolumentoSistemaIdSchema,
GEmolumentoUpdateSchema, GEmolumentoUpdateSchema,
GEmolumentoIdSchema, GEmolumentoIdSchema,
) )
@ -38,6 +39,26 @@ class GEmolumentoController:
"data": self.index_service.execute(), "data": self.index_service.execute(),
} }
# ----------------------------------------------------
# Lista todos os registros de G_EMOLUMENTO
# ----------------------------------------------------
def indexBySistemaId(self, g_emolumento_sistema_id: GEmolumentoSistemaIdSchema):
# Importação da classe desejada
service = self.dynamic_import.service(
"g_emolumento_index_by_sistema_id_service",
"GEmolumentoIndexBySistemaIdService",
)
# Instância da classe service
self.service = service()
# Execução da listagem
return {
"message": "Registros de G_EMOLUMENTO localizados com sucesso.",
"data": self.service.execute(g_emolumento_sistema_id),
}
# ---------------------------------------------------- # ----------------------------------------------------
# Busca um registro específico de G_EMOLUMENTO pelo ID # Busca um registro específico de G_EMOLUMENTO pelo ID
# ---------------------------------------------------- # ----------------------------------------------------

View file

@ -1,3 +1,4 @@
from fastapi import Request
from actions.dynamic_import.dynamic_import import DynamicImport from actions.dynamic_import.dynamic_import import DynamicImport
from packages.v1.administrativo.schemas.g_usuario_schema import ( from packages.v1.administrativo.schemas.g_usuario_schema import (
GUsuarioSchema, GUsuarioSchema,
@ -25,7 +26,11 @@ class GUsuarioController:
pass pass
# Efetua o acesso junto ao sistema por um determinado usuário # Efetua o acesso junto ao sistema por um determinado usuário
def authenticate(self, g_usuario_authenticate_schema: GUsuarioAuthenticateSchema): def authenticate(
self,
request: Request,
g_usuario_authenticate_schema: GUsuarioAuthenticateSchema,
):
# Importação de service de Authenticate # Importação de service de Authenticate
authenticate_service = self.dynamic_import.service( authenticate_service = self.dynamic_import.service(
@ -40,7 +45,7 @@ class GUsuarioController:
"message": "Usuário localizado com sucesso", "message": "Usuário localizado com sucesso",
"data": { "data": {
"token": self.authenticate_service.execute( "token": self.authenticate_service.execute(
g_usuario_authenticate_schema g_usuario_authenticate_schema, request
) )
}, },
} }

View file

@ -6,6 +6,7 @@ from packages.v1.administrativo.controllers.g_calculo_controller import (
) )
from packages.v1.administrativo.schemas.g_calculo_schema import ( from packages.v1.administrativo.schemas.g_calculo_schema import (
GCalculoRapidoSchema, GCalculoRapidoSchema,
GCalculoServico,
ResponseGCalculoRapidoSchema, ResponseGCalculoRapidoSchema,
) )
@ -36,3 +37,23 @@ async def index(
""" """
response = g_calculo_controller.rapido(g_calculo_rapido_schema) response = g_calculo_controller.rapido(g_calculo_rapido_schema)
return response return response
# ----------------------------------------------------
# Lista todos os registros de G_EMOLUMENTO
# ----------------------------------------------------
@router.post(
"/servico",
status_code=status.HTTP_200_OK,
summary="Realiza um cáculo simples dos emolumentos",
response_description="Realiza um cáculo simples dos emolumentos",
)
async def servico(
g_calculo_servico: GCalculoServico,
current_user: dict = Depends(get_current_user),
):
"""
Retorna todos os registros da tabela G_EMOLUMENTO.
"""
response = g_calculo_controller.servico(g_calculo_servico)
return response

View file

@ -6,6 +6,7 @@ from packages.v1.administrativo.controllers.g_emolumento_controller import (
) )
from packages.v1.administrativo.schemas.g_emolumento_schema import ( from packages.v1.administrativo.schemas.g_emolumento_schema import (
GEmolumentoSaveSchema, GEmolumentoSaveSchema,
GEmolumentoSistemaIdSchema,
GEmolumentoUpdateSchema, GEmolumentoUpdateSchema,
GEmolumentoIdSchema, GEmolumentoIdSchema,
) )
@ -36,6 +37,25 @@ async def index(current_user: dict = Depends(get_current_user)):
return response return response
# ----------------------------------------------------
# Lista todos os registros de G_EMOLUMENTO
# ----------------------------------------------------
@router.get(
"/sistema/{sistema_id}",
status_code=status.HTTP_200_OK,
summary="Lista todos os registros de G_EMOLUMENTO cadastrados",
response_description="Lista todos os registros de G_EMOLUMENTO cadastrados",
)
async def index(sistema_id: int, current_user: dict = Depends(get_current_user)):
"""
Retorna todos os registros da tabela G_EMOLUMENTO.
"""
response = g_emolumento_controller.indexBySistemaId(
GEmolumentoSistemaIdSchema(sistema_id=sistema_id)
)
return response
# ---------------------------------------------------- # ----------------------------------------------------
# Busca um registro específico de G_EMOLUMENTO pelo ID # Busca um registro específico de G_EMOLUMENTO pelo ID
# ---------------------------------------------------- # ----------------------------------------------------

View file

@ -1,8 +1,10 @@
# Importação de bibliotecas # Importação de bibliotecas
from typing import Optional from typing import Optional
from fastapi import APIRouter, Body, Depends, status from fastapi import APIRouter, Body, Depends, status, Request
from actions.jwt.get_current_user import get_current_user from actions.jwt.get_current_user import get_current_user
from packages.v1.administrativo.controllers.g_usuario_controller import GUsuarioController from packages.v1.administrativo.controllers.g_usuario_controller import (
GUsuarioController,
)
from packages.v1.administrativo.schemas.g_usuario_schema import ( from packages.v1.administrativo.schemas.g_usuario_schema import (
GUsuarioSchema, GUsuarioSchema,
GUsuarioAuthenticateSchema, GUsuarioAuthenticateSchema,
@ -11,7 +13,7 @@ from packages.v1.administrativo.schemas.g_usuario_schema import (
GUsuarioEmailSchema, GUsuarioEmailSchema,
GUsuarioCpfSchema, GUsuarioCpfSchema,
GUsuarioLoginSchema, GUsuarioLoginSchema,
GUsuarioIdSchema GUsuarioIdSchema,
) )
# Inicializa o roteador para as rotas de usuário # Inicializa o roteador para as rotas de usuário
@ -20,24 +22,32 @@ router = APIRouter()
# Instânciamento do controller desejado # Instânciamento do controller desejado
g_usuario_controller = GUsuarioController() g_usuario_controller = GUsuarioController()
# Autenticação de usuário # Autenticação de usuário
@router.post('/authenticate', @router.post(
status_code=status.HTTP_200_OK, "/authenticate",
summary='Cria o token de acesso do usuário', status_code=status.HTTP_200_OK,
response_description='Retorna o token de acesso do usuário') summary="Cria o token de acesso do usuário",
async def index(g_usuario_authenticate_schema : GUsuarioAuthenticateSchema): response_description="Retorna o token de acesso do usuário",
)
async def index(
request: Request, g_usuario_authenticate_schema: GUsuarioAuthenticateSchema
):
# Efetua a autenticação de um usuário junto ao sistema # Efetua a autenticação de um usuário junto ao sistema
response = g_usuario_controller.authenticate(g_usuario_authenticate_schema) response = g_usuario_controller.authenticate(g_usuario_authenticate_schema, request)
# Retorna os dados localizados # Retorna os dados localizados
return response return response
# Dados do usuário logado # Dados do usuário logado
@router.get('/me', @router.get(
status_code=status.HTTP_200_OK, "/me",
summary='Retorna os dados do usuário que efetuou o login', status_code=status.HTTP_200_OK,
response_description='Dados do usuário que efetuou o login' ) summary="Retorna os dados do usuário que efetuou o login",
response_description="Dados do usuário que efetuou o login",
)
async def me(current_user: dict = Depends(get_current_user)): async def me(current_user: dict = Depends(get_current_user)):
# Busca os dados do usuário logado # Busca os dados do usuário logado
@ -46,11 +56,14 @@ async def me(current_user: dict = Depends(get_current_user)):
# Retorna os dados localizados # Retorna os dados localizados
return response return response
# Lista todos os usuários # Lista todos os usuários
@router.get('/', @router.get(
status_code=status.HTTP_200_OK, "/",
summary='Lista todos os usuário cadastrados', status_code=status.HTTP_200_OK,
response_description='Lista todos os usuário cadastrados') summary="Lista todos os usuário cadastrados",
response_description="Lista todos os usuário cadastrados",
)
async def index(current_user: dict = Depends(get_current_user)): async def index(current_user: dict = Depends(get_current_user)):
# Busca todos os usuários cadastrados # Busca todos os usuários cadastrados
@ -59,12 +72,15 @@ async def index(current_user: dict = Depends(get_current_user)):
# Retorna os dados localizados # Retorna os dados localizados
return response return response
# Localiza um usuário pelo email # Localiza um usuário pelo email
@router.get('/email', @router.get(
status_code=status.HTTP_200_OK, "/email",
summary='Busca um registro em especifico por e-mail informado', status_code=status.HTTP_200_OK,
response_description='Busca um registro em especifico') summary="Busca um registro em especifico por e-mail informado",
async def getEmail(email : str, current_user: dict = Depends(get_current_user)): response_description="Busca um registro em especifico",
)
async def getEmail(email: str, current_user: dict = Depends(get_current_user)):
# Cria o schema com os dados recebidos # Cria o schema com os dados recebidos
usuario_schema = GUsuarioEmailSchema(email=email) usuario_schema = GUsuarioEmailSchema(email=email)
@ -75,12 +91,15 @@ async def getEmail(email : str, current_user: dict = Depends(get_current_user)):
# Retorna os dados localizados # Retorna os dados localizados
return response return response
# Localiza um usuário pelo login # Localiza um usuário pelo login
@router.get('/login', @router.get(
status_code=status.HTTP_200_OK, "/login",
summary='Busca um registro em especifico por login informado', status_code=status.HTTP_200_OK,
response_description='Busca um registro em especifico') summary="Busca um registro em especifico por login informado",
async def getLogin(login : str, current_user: dict = Depends(get_current_user)): response_description="Busca um registro em especifico",
)
async def getLogin(login: str, current_user: dict = Depends(get_current_user)):
# Cria o schema com os dados recebidos # Cria o schema com os dados recebidos
usuario_schema = GUsuarioLoginSchema(login=login) usuario_schema = GUsuarioLoginSchema(login=login)
@ -93,11 +112,13 @@ async def getLogin(login : str, current_user: dict = Depends(get_current_user)):
# Localiza um usuário pelo cpf # Localiza um usuário pelo cpf
@router.get('/cpf', @router.get(
status_code=status.HTTP_200_OK, "/cpf",
summary='Busca um registro em especifico por número de CPF', status_code=status.HTTP_200_OK,
response_description='Busca um registro em especifico') summary="Busca um registro em especifico por número de CPF",
async def getCpf(cpf : str, current_user: dict = Depends(get_current_user)): response_description="Busca um registro em especifico",
)
async def getCpf(cpf: str, current_user: dict = Depends(get_current_user)):
# Cria o schema com os dados recebidos # Cria o schema com os dados recebidos
usuario_schema = GUsuarioCpfSchema(cpf=cpf) usuario_schema = GUsuarioCpfSchema(cpf=cpf)
@ -108,12 +129,15 @@ async def getCpf(cpf : str, current_user: dict = Depends(get_current_user)):
# Retorna os dados localizados # Retorna os dados localizados
return response return response
# Localiza um usuário pelo ID # Localiza um usuário pelo ID
@router.get('/{usuario_id}', @router.get(
status_code=status.HTTP_200_OK, "/{usuario_id}",
summary='Busca um registro em especifico pelo ID do usuário', status_code=status.HTTP_200_OK,
response_description='Busca um registro em especifico') summary="Busca um registro em especifico pelo ID do usuário",
async def show(usuario_id : int, current_user: dict = Depends(get_current_user)): response_description="Busca um registro em especifico",
)
async def show(usuario_id: int, current_user: dict = Depends(get_current_user)):
# Cria o schema com os dados recebidos # Cria o schema com os dados recebidos
usuario_schema = GUsuarioIdSchema(usuario_id=usuario_id) usuario_schema = GUsuarioIdSchema(usuario_id=usuario_id)
@ -126,11 +150,15 @@ async def show(usuario_id : int, current_user: dict = Depends(get_current_user))
# Cadastro de usuários # Cadastro de usuários
@router.post('/', @router.post(
status_code=status.HTTP_200_OK, "/",
summary='Cadastra um usuário', status_code=status.HTTP_200_OK,
response_description='Cadastra um usuário') summary="Cadastra um usuário",
async def save(usuario_schema : GUsuarioSaveSchema, current_user: dict = Depends(get_current_user)): response_description="Cadastra um usuário",
)
async def save(
usuario_schema: GUsuarioSaveSchema, current_user: dict = Depends(get_current_user)
):
# Efetua o cadastro do usuário junto ao banco de dados # Efetua o cadastro do usuário junto ao banco de dados
response = g_usuario_controller.save(usuario_schema) response = g_usuario_controller.save(usuario_schema)
@ -138,12 +166,19 @@ async def save(usuario_schema : GUsuarioSaveSchema, current_user: dict = Depends
# Retorna os dados localizados # Retorna os dados localizados
return response return response
# Atualiza os dados de usuário # Atualiza os dados de usuário
@router.put('/{usuario_id}', @router.put(
status_code=status.HTTP_200_OK, "/{usuario_id}",
summary='Atualiza um usuário', status_code=status.HTTP_200_OK,
response_description='Atualiza um usuário') summary="Atualiza um usuário",
async def update(usuario_id : int, usuario_schema : GUsuarioUpdateSchema, current_user: dict = Depends(get_current_user)): response_description="Atualiza um usuário",
)
async def update(
usuario_id: int,
usuario_schema: GUsuarioUpdateSchema,
current_user: dict = Depends(get_current_user),
):
# Efetua a atualização dos dados de usuário # Efetua a atualização dos dados de usuário
response = g_usuario_controller.update(usuario_id, usuario_schema) response = g_usuario_controller.update(usuario_id, usuario_schema)
@ -151,12 +186,15 @@ async def update(usuario_id : int, usuario_schema : GUsuarioUpdateSchema, curren
# Retorna os dados localizados # Retorna os dados localizados
return response return response
# Exclui um determinado usuário # Exclui um determinado usuário
@router.delete('/{usuario_id}', @router.delete(
status_code=status.HTTP_200_OK, "/{usuario_id}",
summary='Remove um usuário', status_code=status.HTTP_200_OK,
response_description='Remove um usuário') summary="Remove um usuário",
async def delete(usuario_id : int, current_user: dict = Depends(get_current_user)): response_description="Remove um usuário",
)
async def delete(usuario_id: int, current_user: dict = Depends(get_current_user)):
# Cria o schema com os dados recebidos # Cria o schema com os dados recebidos
usuario_schema = GUsuarioIdSchema(usuario_id=usuario_id) usuario_schema = GUsuarioIdSchema(usuario_id=usuario_id)

View file

@ -0,0 +1,33 @@
from abstracts.repository import BaseRepository
from packages.v1.administrativo.schemas.g_emolumento_schema import (
GEmolumentoSistemaIdSchema,
)
class GEmolumentoIndexBySistemaIdRepository(BaseRepository):
"""
Repositório para a operação de listagem de todos os registros
na tabela t_censec_qualidade.
"""
def execute(self, g_emolumento_sistema_id: GEmolumentoSistemaIdSchema):
"""
Executa a consulta SQL para buscar todos os registros.
Returns:
Uma lista de dicionários contendo os dados dos registros.
"""
# Montagem do SQL
sql = """ SELECT
GE.*
FROM G_EMOLUMENTO GE
WHERE GE.SISTEMA_ID = :sistema_id
"""
params = {"sistema_id": g_emolumento_sistema_id.sistema_id}
# Execução do sql
response = self.fetch_all(sql, params)
# Retorna os dados localizados
return response

View file

@ -1,3 +1,4 @@
from decimal import Decimal
from pydantic import BaseModel, ConfigDict from pydantic import BaseModel, ConfigDict
from typing import Optional from typing import Optional
@ -14,6 +15,17 @@ class GCalculoRapidoSchema(BaseModel):
from_attributes = True from_attributes = True
class GCalculoServico(BaseModel):
sistema_id: Optional[float] = None
emolumento_id: Optional[float] = None
valor_documento: Optional[float] = None
quantidade: Optional[Decimal] = None
# valida e coerce em atribuições após criar o objeto
model_config = ConfigDict(from_attributes=True, validate_assignment=True)
class ResponseGCalculoRapidoSchema(GCalculoRapidoSchema): class ResponseGCalculoRapidoSchema(GCalculoRapidoSchema):
valor_emolumento: Optional[float] = None valor_emolumento: Optional[float] = None

View file

@ -1,3 +1,4 @@
from decimal import Decimal
from pydantic import BaseModel from pydantic import BaseModel
from typing import Optional from typing import Optional
@ -38,6 +39,16 @@ class GEmolumentoIdSchema(BaseModel):
from_attributes = True from_attributes = True
# ----------------------------------------------------
# Schema para localizar um registro pelo ID (GET /{id})
# ----------------------------------------------------
class GEmolumentoSistemaIdSchema(BaseModel):
sistema_id: Decimal
class Config:
from_attributes = True
# ---------------------------------------------------- # ----------------------------------------------------
# Schema para criação (POST) # Schema para criação (POST)
# ---------------------------------------------------- # ----------------------------------------------------

View file

@ -0,0 +1,147 @@
from __future__ import annotations
from decimal import Decimal
from types import SimpleNamespace
from typing import Optional
from actions.values.values import Values
from packages.v1.administrativo.actions.g_emolumento_item.g_emolumento_item_get_faixa_valor_action import (
GEmolumentoItemGetFaixaValorAction,
)
from packages.v1.administrativo.schemas.g_calculo_schema import (
GCalculoRapidoSchema,
GCalculoServico,
ResponseGCalculoRapidoSchema,
)
from packages.v1.administrativo.schemas.g_emolumento_item_schema import (
GEmolumentoItemIndexSchema,
)
from packages.v1.administrativo.schemas.g_emolumento_schema import GEmolumentoIdSchema
from packages.v1.administrativo.services.g_emolumento.go.g_emolumento_show_service import (
GEmolumentoShowService,
)
from packages.v1.administrativo.services.g_emolumento_item.go.g_emolumento_item_index_service import (
GEmolumentoItemIndexService,
)
from packages.v1.parametros.schemas.g_config_schema import GConfigNomeSchema
from packages.v1.parametros.services.g_config.g_config_show_by_nome_service import (
GConfigShowByNomeService,
)
class GCalculoServicoService:
"""
Cálculo rápido de emolumentos + taxas.
- Usa DI para serviços (facilita teste/mocks).
- Centraliza leitura de configs/percentuais.
- Normaliza moeda com quantize (por padrão 3 casas, conforme NUMERIC(14,3)).
"""
def __init__(
self,
config_service: Optional[GConfigShowByNomeService] = None,
emolumento_show_service: Optional[GEmolumentoShowService] = None,
emolumento_item_index_service: Optional[GEmolumentoItemIndexService] = None,
emolumento_item_get_faixa_valor_action: Optional[
GEmolumentoItemGetFaixaValorAction
] = None,
scale: str = "0.001", # 3 casas decimais (ex.: Firebird NUMERIC(14,3))
) -> None:
self._config_service = config_service or GConfigShowByNomeService()
self._emolumento_show_service = (
emolumento_show_service or GEmolumentoShowService()
)
self._emolumento_item_index_service = (
emolumento_item_index_service or GEmolumentoItemIndexService()
)
self._emolumento_item_get_faixa_valor_action = (
emolumento_item_get_faixa_valor_action
or GEmolumentoItemGetFaixaValorAction()
)
self._scale = Decimal(scale)
def execute(self, data: GCalculoServico):
# Busca os parâmetros da aplicação
periodo_id = float(
self._config_service.execute(
GConfigNomeSchema(nome="PERIODO_PADRAO", sistema_id=data.sistema_id)
).valor
)
# Gerar o percentual do iss de acordo com o parâmetro
percentual_iss = Values.percent(
Decimal(
self._config_service.execute(
GConfigNomeSchema(nome="PERCENTUAL_ISS", sistema_id=5)
).valor
),
100,
)
# Gerar o percentual do iss de acordo com o parâmetro
percentual_fundos = Values.percent(
Decimal(
self._config_service.execute(
GConfigNomeSchema(nome="PERCENTUAL_FUNDOS_ESTADUAIS", sistema_id=5)
).valor
),
100,
)
# Busca o emolumento desejado
emolumento = self._emolumento_show_service.execute(
GEmolumentoIdSchema(emolumento_id=data.emolumento_id)
)
# Busca os itens do emolumento
emolumento_itens = self._emolumento_item_index_service.execute(
GEmolumentoItemIndexSchema(
emolumento_id=float(emolumento.emolumento_id),
emolumento_periodo_id=periodo_id,
)
)
# Se vier lista, usa o primeiro (ou ajuste a regra aqui, se necessário)
emolumento_item = self._emolumento_item_get_faixa_valor_action.execute(
emolumento_itens, Decimal(data.valor_documento)
)
# Converter o valor para decimal
quantidade = Decimal(data.quantidade)
# Cálculos
emolumento_total = Values.money(
self._scale, (emolumento_item.valor_emolumento * quantidade)
)
taxa_judiciaria_total = Values.money(
self._scale, (emolumento_item.valor_taxa_judiciaria * quantidade)
)
iss_total = Values.money(
self._scale,
(emolumento_item.valor_emolumento * percentual_iss * quantidade),
)
fundos_total = Values.money(
self._scale,
(emolumento_item.valor_emolumento * percentual_fundos * quantidade),
)
total = Values.money(
self._scale,
(emolumento_total + taxa_judiciaria_total + iss_total + fundos_total),
)
# Resposta
return SimpleNamespace(
emolumento_id=float(data.emolumento_id),
emolumento_item_id=float(emolumento_item.emolumento_item_id),
valor_documento=float(data.valor_documento),
valor_emolumento=emolumento_total,
valor_taxa_judiciaria=taxa_judiciaria_total,
valor_iss=iss_total,
valor_fundos=fundos_total,
valor_total=total,
)

View file

@ -0,0 +1,52 @@
from fastapi import HTTPException, status
from packages.v1.administrativo.actions.g_emolumento.g_emolumento_index_by_sistema_id_action import (
GEmolumentoIndexBySistemaIdAction,
)
from packages.v1.administrativo.schemas.g_emolumento_schema import (
GEmolumentoSistemaIdSchema,
)
class GEmolumentoIndexBySistemaIdService:
"""
Serviço responsável por encapsular a lógica de negócio para a operação
de listagem de registros na tabela G_EMOLUMENTO.
"""
def execute(self, g_emolumento_index_by_sistema_id: GEmolumentoSistemaIdSchema):
"""
Executa a operação de busca de todos os registros no banco de dados.
Args:
g_emolumento_index_schema (GEmolumentoIndexSchema):
Esquema que pode conter filtros ou parâmetros de busca.
Returns:
A lista de registros encontrados.
"""
# ----------------------------------------------------
# Instanciamento da ação
# ----------------------------------------------------
g_emolumento_index_by_sistema_id_action = GEmolumentoIndexBySistemaIdAction()
# ----------------------------------------------------
# Execução da ação
# ----------------------------------------------------
data = g_emolumento_index_by_sistema_id_action.execute(
g_emolumento_index_by_sistema_id
)
# ----------------------------------------------------
# Verificação de retorno
# ----------------------------------------------------
if not data:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Não foi possível localizar registros de G_EMOLUMENTO.",
)
# ----------------------------------------------------
# Retorno da informação
# ----------------------------------------------------
return data

View file

@ -1,4 +1,4 @@
from fastapi import HTTPException, status from fastapi import HTTPException, status, Request
from actions.jwt.create_token import CreateToken from actions.jwt.create_token import CreateToken
from packages.v1.administrativo.schemas.g_usuario_schema import ( from packages.v1.administrativo.schemas.g_usuario_schema import (
GUsuarioAuthenticateSchema, GUsuarioAuthenticateSchema,
@ -14,7 +14,11 @@ from actions.security.security import Security
class AuthenticateService: class AuthenticateService:
def execute(self, g_usuario_authenticate_schema: GUsuarioAuthenticateSchema): def execute(
self,
request: Request,
g_usuario_authenticate_schema: GUsuarioAuthenticateSchema,
):
# Instânciamento da action de authenticate # Instânciamento da action de authenticate
get_by_authenticate_action = GetByAuthenticateAction() get_by_authenticate_action = GetByAuthenticateAction()
@ -67,5 +71,8 @@ class AuthenticateService:
"email": str(get_by_authenticate_result.email), "email": str(get_by_authenticate_result.email),
} }
# Cria os dados da sessão
request.session["user"] = jwtUser
# Retorna o token dos dados do usuário # Retorna o token dos dados do usuário
return create_token.execute("access-token", json.dumps(jwtUser)) return create_token.execute("access-token", json.dumps(jwtUser))

View file

@ -1,5 +1,6 @@
# Importação de bibliotecas # Importação de bibliotecas
from fastapi import APIRouter, Depends, status from fastapi import APIRouter, Depends, status
from actions.data.dict_to_namespace import dict_to_namespace
from actions.jwt.get_current_user import get_current_user from actions.jwt.get_current_user import get_current_user
from packages.v1.servicos.balcao.controllers.t_servico_pedido_controller import ( from packages.v1.servicos.balcao.controllers.t_servico_pedido_controller import (
TServicoPedidoController, TServicoPedidoController,
@ -72,7 +73,12 @@ async def save(
""" """
Cria um novo registro na tabela T_SERVICO_PEDIDO. Cria um novo registro na tabela T_SERVICO_PEDIDO.
""" """
current_user = dict_to_namespace(current_user)
t_servico_pedido_schema.usuario_id = current_user.data.usuario_id
response = t_servico_pedido_controller.save(t_servico_pedido_schema) response = t_servico_pedido_controller.save(t_servico_pedido_schema)
return response return response

View file

@ -30,7 +30,9 @@ class TServicoPedidoSaveRepository(BaseRepository):
# ---------------------------------------------------- # ----------------------------------------------------
# Preenchimento dos parâmetros # Preenchimento dos parâmetros
# ---------------------------------------------------- # ----------------------------------------------------
params = t_servico_pedido_save_schema.model_dump(exclude_unset=True) params = t_servico_pedido_save_schema.model_dump(
exclude={"itens"}, exclude_unset=True
)
# ---------------------------------------------------- # ----------------------------------------------------
# Montagem do SQL dinâmico # Montagem do SQL dinâmico

View file

@ -8,55 +8,81 @@ from datetime import datetime
# Schema base - representa a tabela T_SERVICO_ITEMPEDIDO # Schema base - representa a tabela T_SERVICO_ITEMPEDIDO
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoItemPedidoSchema(BaseModel): class TServicoItemPedidoSchema(BaseModel):
servico_itempedido_id: Optional[int] = None servico_itempedido_id: Optional[Decimal] = None
servico_pedido_id: Optional[Decimal] = None
servico_pedido_id: Optional[int] = None servico_tipo_id: Optional[Decimal] = None
servico_tipo_id: Optional[int] = None
pessoa_id: Optional[int] = None
pessoa_auxiliar_id: Optional[int] = None
valor: Optional[Decimal] = None valor: Optional[Decimal] = None
qtd: Optional[Decimal] = None qtd: Optional[Decimal] = None
pessoa_id: Optional[Decimal] = None
impressao_etiqueta: Optional[str] = None
situacao: Optional[str] = None
etiqueta_numero: Optional[Decimal] = None
pessoa_auxiliar_id: Optional[Decimal] = None
pessoa_sp_abono_rep: Optional[str] = None
tipo_item: Optional[str] = None
imprimir: Optional[str] = None
observacao: Optional[str] = None
impressao_direta: Optional[str] = None
selo_livro_id: Optional[Decimal] = None
emolumento: Optional[Decimal] = None emolumento: Optional[Decimal] = None
fundesp: Optional[Decimal] = None fundesp: Optional[Decimal] = None
taxa_judiciaria: Optional[Decimal] = None taxa_judiciaria: Optional[Decimal] = None
desconto: Optional[Decimal] = None desconto: Optional[Decimal] = None
valor_base_calculo: Optional[Decimal] = None
valor_avaliacao: Optional[Decimal] = None
situacao: Optional[str] = None
tipo_item: Optional[str] = None
desc_complementar: Optional[str] = None desc_complementar: Optional[str] = None
nome_juridico: Optional[str] = None valor_manual: Optional[str] = None
motivo_diferido: Optional[str] = None valor_documento: Optional[Decimal] = None
etiqueta_apenas_frete: Optional[str] = None # (campo char/flag) outra_taxa1: Optional[Decimal] = None
emolumento_item_id: Optional[Decimal] = None
selo_livro_id: Optional[int] = None certidao_impressa: Optional[str] = None
etiqueta_numero: Optional[int] = None certidao_ato_id: Optional[Decimal] = None
certidao_ato_id: Optional[int] = None emolumento_id: Optional[Decimal] = None
indexacao_id: Optional[int] = None certidao_previsao: Optional[datetime] = None
nfse_id: Optional[int] = None certidao_ato_antigo: Optional[str] = None
certidao_data_emissao: Optional[datetime] = None certidao_data_emissao: Optional[datetime] = None
certidao_data_lavratura: Optional[datetime] = None certidao_texto: Optional[str] = None
certidao_texto: Optional[bytes] = None # BLOB (binário)
ato_antigo_tipo: Optional[str] = None ato_antigo_tipo: Optional[str] = None
valor_iss: Optional[Decimal] = None
id_ato_isentado: Optional[Decimal] = None
motivo_isencao: Optional[str] = None
pessoas_etiquetas: Optional[Decimal] = None
abonador: Optional[str] = None
servico_cartao: Optional[str] = None
valor_informacoes_centrais: Optional[Decimal] = None
situacao_diferido: Optional[str] = None
sigla_numero: Optional[str] = None
motivo_diferido: Optional[str] = None
nome_juridico: Optional[str] = None
etiqueta_apenas_frente: Optional[str] = None
indexacao_id: Optional[Decimal] = None
certidao_data_lavratura: Optional[datetime] = None
nfse_id: Optional[Decimal] = None
qtd_pagina_certidao: Optional[Decimal] = None
placa: Optional[str] = None placa: Optional[str] = None
dut: Optional[str] = None dut: Optional[str] = None
pessoa_sp_abono_rep: Optional[str] = None chave_importacao: Optional[Decimal] = None
chave_importacao: Optional[int] = None etiqueta_unica: Optional[str] = None
fundo_abonador: Optional[str] = None
instrumento_publico: Optional[str] = None
data_lavratura_abono: Optional[datetime] = None
valor_base_calculo: Optional[Decimal] = None
valor_avaliacao: Optional[Decimal] = None
ato_abonado: Optional[Decimal] = None
transferencia_veiculo: Optional[str] = None
usar_a4: Optional[str] = None
cpf_abono_rep: Optional[str] = None
vrcext: Optional[Decimal] = None
valor_fundo_selo: Optional[Decimal] = None
averbacao: Optional[str] = None
class Config: class Config:
from_attributes = True from_attributes = True
# ----------------------------------------------------
# ----------------------------------------------------
# Schema para localizar um registro pelo ID (GET /{id}) # Schema para listagem (GET index)
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoItemIndexSchema(BaseModel): class TServicoItemIndexSchema(BaseModel):
servico_pedido_id: int servico_pedido_id: Optional[Decimal] = None
class Config: class Config:
from_attributes = True from_attributes = True
@ -65,8 +91,8 @@ class TServicoItemIndexSchema(BaseModel):
# ---------------------------------------------------- # ----------------------------------------------------
# Schema para localizar um registro pelo ID (GET /{id}) # Schema para localizar um registro pelo ID (GET /{id})
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoItemPedidoIdSchema(BaseModel): class TServicoItemPedidoIdSchema(TServicoItemPedidoSchema):
servico_itempedido_id: int servico_itempedido_id: Decimal
class Config: class Config:
from_attributes = True from_attributes = True
@ -76,44 +102,7 @@ class TServicoItemPedidoIdSchema(BaseModel):
# Schema para criação (POST) # Schema para criação (POST)
# - normalmente sem o ID (gerado pelo banco) # - normalmente sem o ID (gerado pelo banco)
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoItemPedidoSaveSchema(BaseModel): class TServicoItemPedidoSaveSchema(TServicoItemPedidoSchema):
servico_itempedido_id: Optional[int] = None
servico_pedido_id: Optional[int] = None
servico_tipo_id: Optional[int] = None
pessoa_id: Optional[int] = None
pessoa_auxiliar_id: Optional[int] = None
valor: Optional[Decimal] = None
qtd: Optional[Decimal] = None
emolumento: Optional[Decimal] = None
fundesp: Optional[Decimal] = None
taxa_judiciaria: Optional[Decimal] = None
desconto: Optional[Decimal] = None
valor_base_calculo: Optional[Decimal] = None
valor_avaliacao: Optional[Decimal] = None
situacao: Optional[str] = None
tipo_item: Optional[str] = None
desc_complementar: Optional[str] = None
nome_juridico: Optional[str] = None
motivo_diferido: Optional[str] = None
etiqueta_apenas_frete: Optional[str] = None
selo_livro_id: Optional[int] = None
etiqueta_numero: Optional[int] = None
certidao_ato_id: Optional[int] = None
indexacao_id: Optional[int] = None
nfse_id: Optional[int] = None
certidao_data_emissao: Optional[datetime] = None
certidao_data_lavratura: Optional[datetime] = None
certidao_texto: Optional[bytes] = None
ato_antigo_tipo: Optional[str] = None
placa: Optional[str] = None
dut: Optional[str] = None
pessoa_sp_abono_rep: Optional[str] = None
chave_importacao: Optional[int] = None
class Config: class Config:
from_attributes = True from_attributes = True
@ -123,45 +112,7 @@ class TServicoItemPedidoSaveSchema(BaseModel):
# Schema para atualização (PUT) # Schema para atualização (PUT)
# - inclui o ID + campos opcionais para alterar # - inclui o ID + campos opcionais para alterar
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoItemPedidoUpdateSchema(BaseModel): class TServicoItemPedidoUpdateSchema(TServicoItemPedidoSchema):
servico_itempedido_id: Optional[int] = None
servico_pedido_id: Optional[int] = None
servico_tipo_id: Optional[int] = None
pessoa_id: Optional[int] = None
pessoa_auxiliar_id: Optional[int] = None
valor: Optional[Decimal] = None
qtd: Optional[Decimal] = None
emolumento: Optional[Decimal] = None
fundesp: Optional[Decimal] = None
taxa_judiciaria: Optional[Decimal] = None
desconto: Optional[Decimal] = None
valor_base_calculo: Optional[Decimal] = None
valor_avaliacao: Optional[Decimal] = None
situacao: Optional[str] = None
tipo_item: Optional[str] = None
desc_complementar: Optional[str] = None
nome_juridico: Optional[str] = None
motivo_diferido: Optional[str] = None
etiqueta_apenas_frete: Optional[str] = None
selo_livro_id: Optional[int] = None
etiqueta_numero: Optional[int] = None
certidao_ato_id: Optional[int] = None
indexacao_id: Optional[int] = None
nfse_id: Optional[int] = None
certidao_data_emissao: Optional[datetime] = None
certidao_data_lavratura: Optional[datetime] = None
certidao_texto: Optional[bytes] = None
ato_antigo_tipo: Optional[str] = None
placa: Optional[str] = None
dut: Optional[str] = None
pessoa_sp_abono_rep: Optional[str] = None
chave_importacao: Optional[int] = None
class Config: class Config:
from_attributes = True from_attributes = True

View file

@ -1,26 +1,30 @@
from pydantic import BaseModel from pydantic import BaseModel
from typing import Optional from typing import Optional, List
from decimal import Decimal from decimal import Decimal
from datetime import datetime from datetime import datetime
from packages.v1.servicos.balcao.schemas.t_servico_itempedido_schema import (
TServicoItemPedidoSchema,
)
# ---------------------------------------------------- # ----------------------------------------------------
# Schema base - representa a tabela T_SERVICO_PEDIDO # Schema base - representa a tabela T_SERVICO_PEDIDO
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoPedidoSchema(BaseModel): class TServicoPedidoSchema(BaseModel):
servico_pedido_id: int servico_pedido_id: Decimal
valor_pedido: Optional[Decimal] = None valor_pedido: Optional[Decimal] = None
valor_pago: Optional[Decimal] = None valor_pago: Optional[Decimal] = None
usuario_id: Optional[int] = None usuario_id: Optional[Decimal] = None
data_pedido: Optional[datetime] = None data_pedido: Optional[datetime] = None
mensalista_livrocaixa_id: Optional[int] = None mensalista_livrocaixa_id: Optional[Decimal] = None
observacao: Optional[str] = None observacao: Optional[str] = None
escrevente_id: Optional[int] = None escrevente_id: Optional[Decimal] = None
situacao: Optional[str] = None situacao: Optional[str] = None
estornado: Optional[str] = None estornado: Optional[str] = None
apresentante: Optional[str] = None apresentante: Optional[str] = None
nfse_id: Optional[int] = None nfse_id: Optional[Decimal] = None
chave_importacao: Optional[int] = None chave_importacao: Optional[Decimal] = None
cpfcnpj_apresentante: Optional[str] = None cpfcnpj_apresentante: Optional[str] = None
class Config: class Config:
@ -31,7 +35,7 @@ class TServicoPedidoSchema(BaseModel):
# Schema para localizar um registro pelo ID (GET /{id}) # Schema para localizar um registro pelo ID (GET /{id})
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoPedidoIdSchema(BaseModel): class TServicoPedidoIdSchema(BaseModel):
servico_pedido_id: int servico_pedido_id: Decimal
class Config: class Config:
from_attributes = True from_attributes = True
@ -42,20 +46,21 @@ class TServicoPedidoIdSchema(BaseModel):
# - normalmente sem o ID (gerado pelo banco) # - normalmente sem o ID (gerado pelo banco)
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoPedidoSaveSchema(BaseModel): class TServicoPedidoSaveSchema(BaseModel):
servico_pedido_id: Optional[int] = None servico_pedido_id: Optional[Decimal] = None
valor_pedido: Optional[Decimal] = None valor_pedido: Optional[Decimal] = None
valor_pago: Optional[Decimal] = None valor_pago: Optional[Decimal] = None
usuario_id: Optional[int] = None usuario_id: Optional[Decimal] = None
data_pedido: Optional[datetime] = None data_pedido: Optional[datetime] = None
mensalista_livrocaixa_id: Optional[int] = None mensalista_livrocaixa_id: Optional[Decimal] = None
observacao: Optional[str] = None observacao: Optional[str] = None
escrevente_id: Optional[int] = None escrevente_id: Optional[Decimal] = None
situacao: Optional[str] = None situacao: Optional[str] = None
estornado: Optional[str] = None estornado: Optional[str] = None
apresentante: Optional[str] = None apresentante: Optional[str] = None
nfse_id: Optional[int] = None nfse_id: Optional[Decimal] = None
chave_importacao: Optional[int] = None chave_importacao: Optional[Decimal] = None
cpfcnpj_apresentante: Optional[str] = None cpfcnpj_apresentante: Optional[str] = None
itens: Optional[List[TServicoItemPedidoSchema]] = None
class Config: class Config:
from_attributes = True from_attributes = True
@ -66,19 +71,19 @@ class TServicoPedidoSaveSchema(BaseModel):
# - inclui o ID + campos opcionais para alterar # - inclui o ID + campos opcionais para alterar
# ---------------------------------------------------- # ----------------------------------------------------
class TServicoPedidoUpdateSchema(BaseModel): class TServicoPedidoUpdateSchema(BaseModel):
servico_pedido_id: Optional[int] = None servico_pedido_id: Optional[Decimal] = None
valor_pedido: Optional[Decimal] = None valor_pedido: Optional[Decimal] = None
valor_pago: Optional[Decimal] = None valor_pago: Optional[Decimal] = None
usuario_id: Optional[int] = None usuario_id: Optional[Decimal] = None
data_pedido: Optional[datetime] = None data_pedido: Optional[datetime] = None
mensalista_livrocaixa_id: Optional[int] = None mensalista_livrocaixa_id: Optional[Decimal] = None
observacao: Optional[str] = None observacao: Optional[str] = None
escrevente_id: Optional[int] = None escrevente_id: Optional[Decimal] = None
situacao: Optional[str] = None situacao: Optional[str] = None
estornado: Optional[str] = None estornado: Optional[str] = None
apresentante: Optional[str] = None apresentante: Optional[str] = None
nfse_id: Optional[int] = None nfse_id: Optional[Decimal] = None
chave_importacao: Optional[int] = None chave_importacao: Optional[Decimal] = None
cpfcnpj_apresentante: Optional[str] = None cpfcnpj_apresentante: Optional[str] = None
class Config: class Config:

View file

@ -1,3 +1,4 @@
from datetime import datetime
from packages.v1.servicos.balcao.actions.t_servico_pedido.t_servico_pedido_save_action import ( from packages.v1.servicos.balcao.actions.t_servico_pedido.t_servico_pedido_save_action import (
TServicoPedidoSaveAction, TServicoPedidoSaveAction,
) )
@ -8,6 +9,9 @@ from packages.v1.servicos.balcao.schemas.t_servico_pedido_schema import (
from packages.v1.sequencia.services.g_sequencia.generate_service import ( from packages.v1.sequencia.services.g_sequencia.generate_service import (
GenerateService, GenerateService,
) )
from packages.v1.servicos.balcao.services.t_servico_itempedido.go.t_servico_itempedido_save_service import (
TServicoItemPedidoSaveService,
)
class TServicoPedidoSaveService: class TServicoPedidoSaveService:
@ -43,8 +47,35 @@ class TServicoPedidoSaveService:
# Atualiza o ID no schema # Atualiza o ID no schema
t_servico_pedido_save_schema.servico_pedido_id = sequencia.sequencia t_servico_pedido_save_schema.servico_pedido_id = sequencia.sequencia
# Verifica se tem a data do pedido
if not t_servico_pedido_save_schema.data_pedido:
t_servico_pedido_save_schema.data_pedido = datetime.now()
# ---------------------------------------------------- # ----------------------------------------------------
# Instanciamento e execução da Action de salvamento # Instanciamento e execução da Action de salvamento
# ---------------------------------------------------- # ----------------------------------------------------
t_servico_pedido_save_action = TServicoPedidoSaveAction() t_servico_pedido_save_action = TServicoPedidoSaveAction()
return t_servico_pedido_save_action.execute(t_servico_pedido_save_schema)
# Obtenho a resposta da operação
response = t_servico_pedido_save_action.execute(t_servico_pedido_save_schema)
# Verifica se o pedido foi salvo
if (
response.servico_pedido_id > 0
and len(t_servico_pedido_save_schema.itens) > 0
):
# Import a classe de salvar os intes
t_servico_itempedido_service = TServicoItemPedidoSaveService()
# Percorre todos os itens salvos
for item in t_servico_pedido_save_schema.itens:
# Define o id do item do serviço
item.servico_pedido_id = response.servico_pedido_id
# Salva o item do pedido
t_servico_itempedido_service.execute(item)
return response