Spaces:
Running
Running
| from sqlalchemy.orm import Session | |
| from fastapi import HTTPException | |
| from datetime import datetime | |
| from app.models.user import User, CreditTransaction | |
| def deduct_credits(db: Session, user: User, amount: int, concept: str, reference_id: str = None) -> int: | |
| """ | |
| Deduce `amount` de créditos del usuario y registra la transacción. | |
| Si no tiene suficientes créditos, lanza HTTPException 402 (Payment Required). | |
| Retorna la cantidad de créditos restantes. | |
| """ | |
| if user.credits < amount: | |
| raise HTTPException( | |
| status_code=402, | |
| detail=f"Créditos insuficientes. Se requieren {amount} créditos para esta operación (tienes {user.credits})." | |
| ) | |
| # Restar créditos del usuario | |
| user.credits -= amount | |
| # Crear transacción de deducción (monto negativo) | |
| tx = CreditTransaction( | |
| user_id=user.id, | |
| amount=-amount, | |
| concept=concept, | |
| reference_id=str(reference_id) if reference_id is not None else None, | |
| created_at=datetime.utcnow() | |
| ) | |
| db.add(tx) | |
| db.commit() | |
| db.refresh(user) | |
| # Notificar al usuario por WebSocket en tiempo real de su deducción de créditos | |
| try: | |
| from app.websocket_manager import send_sync_message | |
| send_sync_message({ | |
| "type": "user_credits_updated", | |
| "credits": user.credits | |
| }, user.id) | |
| except Exception: | |
| # Silenciamos cualquier error de WebSocket para no arruinar la transacción principal | |
| pass | |
| return user.credits | |