fin.issuer_settings guarda la identidad fiscal con la que la empresa emite CFDI: razón social, RFC, régimen fiscal y CP del lugar de expedición. Una sola configuración vigente por empresa, garantizada con índice único parcial; el guardado es un upsert (GET + PUT, sin DELETE). El RFC se valida con la expresión oficial y se normaliza a mayúsculas sin espacios antes de aplicar la restricción de longitud. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
59 lines
1.9 KiB
Python
59 lines
1.9 KiB
Python
"""Lógica de los datos fiscales del emisor.
|
|
|
|
Una empresa tiene, a lo más, una configuración vigente: el guardado es un upsert, no
|
|
un alta que pueda duplicar filas.
|
|
"""
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ..catalogs.models import TaxRegime
|
|
from .dto import IssuerSettingsInput
|
|
from .models import IssuerSettings
|
|
|
|
|
|
def _find(db: Session, tenant_id: int, company_id: int) -> IssuerSettings | None:
|
|
return db.query(IssuerSettings).filter(
|
|
IssuerSettings.tenant_id == tenant_id,
|
|
IssuerSettings.company_id == company_id,
|
|
IssuerSettings.deleted_at.is_(None),
|
|
).first()
|
|
|
|
|
|
def get_issuer_settings(db: Session, tenant_id: int, company_id: int) -> IssuerSettings:
|
|
obj = _find(db, tenant_id, company_id)
|
|
if not obj:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="La empresa aún no tiene datos fiscales del emisor configurados",
|
|
)
|
|
return obj
|
|
|
|
|
|
def save_issuer_settings(
|
|
db: Session,
|
|
payload: IssuerSettingsInput,
|
|
tenant_id: int,
|
|
company_id: int,
|
|
user_id: str | None = None,
|
|
) -> IssuerSettings:
|
|
"""Crea la configuración la primera vez y la actualiza en adelante."""
|
|
if db.query(TaxRegime.id).filter(TaxRegime.id == payload.tax_regime_id).first() is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="El régimen fiscal indicado no existe en el catálogo del SAT",
|
|
)
|
|
|
|
obj = _find(db, tenant_id, company_id)
|
|
data = payload.model_dump()
|
|
if obj is None:
|
|
obj = IssuerSettings(**data, tenant_id=tenant_id, company_id=company_id, updated_by=user_id)
|
|
db.add(obj)
|
|
else:
|
|
for field, value in data.items():
|
|
setattr(obj, field, value)
|
|
obj.updated_by = user_id
|
|
db.commit()
|
|
db.refresh(obj)
|
|
return obj
|