Cadastro da alíquota do ICMS correta. Inclusão da nova alíquota e comparação em todos os relatórios.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# parametros.py
|
||||
from fastapi import APIRouter, Request, Depends, Form
|
||||
from fastapi import APIRouter, Request, Depends, Form, UploadFile, File
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.database import get_session
|
||||
from app.models import AliquotaUF, ParametrosFormula, SelicMensal
|
||||
@@ -9,7 +9,7 @@ import datetime
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy.future import select
|
||||
from app.database import AsyncSessionLocal
|
||||
from fastapi.responses import RedirectResponse
|
||||
from fastapi.responses import RedirectResponse, JSONResponse
|
||||
from app.models import Fatura
|
||||
from fastapi import Body
|
||||
from app.database import engine
|
||||
@@ -21,6 +21,8 @@ import csv
|
||||
from fastapi.responses import StreamingResponse
|
||||
import pandas as pd
|
||||
from io import BytesIO
|
||||
from sqlalchemy import select
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
@@ -100,6 +102,28 @@ async def editar_parametro(param_id: int, request: Request):
|
||||
return {"success": True}
|
||||
return {"success": False, "error": "Não encontrado"}
|
||||
|
||||
@router.post("/parametros/ativar/{param_id}")
|
||||
async def ativar_parametro(param_id: int, request: Request):
|
||||
data = await request.json()
|
||||
ativo = bool(data.get("ativo", True))
|
||||
async with AsyncSessionLocal() as session:
|
||||
param = await session.get(ParametrosFormula, param_id)
|
||||
if not param:
|
||||
return JSONResponse(status_code=404, content={"error": "Parâmetro não encontrado"})
|
||||
param.ativo = ativo
|
||||
await session.commit()
|
||||
return {"success": True}
|
||||
|
||||
@router.get("/parametros/delete/{param_id}")
|
||||
async def deletar_parametro(param_id: int):
|
||||
async with AsyncSessionLocal() as session:
|
||||
param = await session.get(ParametrosFormula, param_id)
|
||||
if not param:
|
||||
return RedirectResponse("/parametros?erro=1&msg=Parâmetro não encontrado", status_code=303)
|
||||
await session.delete(param)
|
||||
await session.commit()
|
||||
return RedirectResponse("/parametros?ok=1&msg=Parâmetro removido", status_code=303)
|
||||
|
||||
@router.post("/parametros/testar")
|
||||
async def testar_formula(db: AsyncSession = Depends(get_session), data: dict = Body(...)):
|
||||
formula = data.get("formula")
|
||||
@@ -117,10 +141,18 @@ async def testar_formula(db: AsyncSession = Depends(get_session), data: dict = B
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
|
||||
@router.get("/parametros/aliquotas", response_model=List[AliquotaUFSchema])
|
||||
async def listar_aliquotas(db: AsyncSession = Depends(get_session)):
|
||||
result = await db.execute(select(AliquotaUF).order_by(AliquotaUF.uf, AliquotaUF.exercicio))
|
||||
return result.scalars().all()
|
||||
@router.get("/parametros/aliquotas")
|
||||
async def listar_aliquotas(uf: str | None = None, db: AsyncSession = Depends(get_session)):
|
||||
stmt = select(AliquotaUF).order_by(AliquotaUF.uf, AliquotaUF.exercicio.desc())
|
||||
if uf:
|
||||
stmt = stmt.where(AliquotaUF.uf == uf)
|
||||
|
||||
rows = (await db.execute(stmt)).scalars().all()
|
||||
return [
|
||||
{"uf": r.uf, "exercicio": int(r.exercicio), "aliquota": float(r.aliq_icms)}
|
||||
for r in rows
|
||||
]
|
||||
|
||||
|
||||
@router.post("/parametros/aliquotas")
|
||||
async def adicionar_aliquota(aliq: AliquotaUFSchema, db: AsyncSession = Depends(get_session)):
|
||||
@@ -227,5 +259,88 @@ def baixar_template_excel():
|
||||
headers={"Content-Disposition": "attachment; filename=template_aliquotas.xlsx"}
|
||||
)
|
||||
|
||||
@router.post("/parametros/aliquotas/salvar")
|
||||
async def salvar_aliquota(payload: dict, db: AsyncSession = Depends(get_session)):
|
||||
uf = (payload.get("uf") or "").strip().upper()
|
||||
exercicio = int(payload.get("exercicio") or 0)
|
||||
aliquota = Decimal(str(payload.get("aliquota") or "0"))
|
||||
|
||||
orig_uf = (payload.get("original_uf") or "").strip().upper() or uf
|
||||
orig_ex = int(payload.get("original_exercicio") or 0) or exercicio
|
||||
|
||||
if not uf or not exercicio or aliquota <= 0:
|
||||
return JSONResponse(status_code=400, content={"error": "UF, exercício e alíquota são obrigatórios."})
|
||||
|
||||
# busca pelo registro original (antes da edição)
|
||||
stmt = select(AliquotaUF).where(
|
||||
AliquotaUF.uf == orig_uf,
|
||||
AliquotaUF.exercicio == orig_ex
|
||||
)
|
||||
existente = (await db.execute(stmt)).scalar_one_or_none()
|
||||
|
||||
if existente:
|
||||
# atualiza (inclusive a chave, se mudou)
|
||||
existente.uf = uf
|
||||
existente.exercicio = exercicio
|
||||
existente.aliq_icms = aliquota
|
||||
else:
|
||||
# não existia o original -> upsert padrão
|
||||
db.add(AliquotaUF(uf=uf, exercicio=exercicio, aliq_icms=aliquota))
|
||||
|
||||
await db.commit()
|
||||
return {"success": True}
|
||||
|
||||
@router.post("/parametros/aliquotas/importar")
|
||||
async def importar_aliquotas_csv(arquivo: UploadFile = File(...), db: AsyncSession = Depends(get_session)):
|
||||
content = await arquivo.read()
|
||||
text = content.decode("utf-8", errors="ignore")
|
||||
|
||||
# tenta ; depois ,
|
||||
sniffer = csv.Sniffer()
|
||||
dialect = sniffer.sniff(text.splitlines()[0] if text else "uf;exercicio;aliquota")
|
||||
reader = csv.DictReader(io.StringIO(text), dialect=dialect)
|
||||
|
||||
count = 0
|
||||
for row in reader:
|
||||
uf = (row.get("uf") or row.get("UF") or "").strip().upper()
|
||||
exercicio_str = (row.get("exercicio") or row.get("ano") or "").strip()
|
||||
try:
|
||||
exercicio = int(exercicio_str)
|
||||
except Exception:
|
||||
continue
|
||||
aliquota_str = (row.get("aliquota") or row.get("aliq_icms") or "").replace(",", ".").strip()
|
||||
|
||||
if not uf or not exercicio or not aliquota_str:
|
||||
continue
|
||||
|
||||
try:
|
||||
aliquota = Decimal(aliquota_str)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
stmt = select(AliquotaUF).where(AliquotaUF.uf == uf, AliquotaUF.exercicio == exercicio)
|
||||
existente = (await db.execute(stmt)).scalar_one_or_none()
|
||||
|
||||
if existente:
|
||||
existente.aliq_icms = aliquota
|
||||
else:
|
||||
db.add(AliquotaUF(uf=uf, exercicio=exercicio, aliq_icms=aliquota))
|
||||
|
||||
count += 1
|
||||
|
||||
await db.commit()
|
||||
return {"success": True, "qtd": count}
|
||||
|
||||
@router.delete("/parametros/aliquotas/{uf}/{exercicio}")
|
||||
async def excluir_aliquota(uf: str, exercicio: int, db: AsyncSession = Depends(get_session)):
|
||||
stmt = select(AliquotaUF).where(
|
||||
AliquotaUF.uf == uf.upper(),
|
||||
AliquotaUF.exercicio == exercicio
|
||||
)
|
||||
row = (await db.execute(stmt)).scalar_one_or_none()
|
||||
if not row:
|
||||
return JSONResponse(status_code=404, content={"error": "Registro não encontrado."})
|
||||
|
||||
await db.delete(row)
|
||||
await db.commit()
|
||||
return {"success": True}
|
||||
|
||||
Reference in New Issue
Block a user