Subir archivos a "/"
This commit is contained in:
253
subclientes.py
Normal file
253
subclientes.py
Normal file
@@ -0,0 +1,253 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
from app.database import get_db
|
||||
from app.models import Cliente, SubCliente, MovimientoTimbre, Usuario
|
||||
from app.models.enums import TipoMovimiento, EstadoCliente
|
||||
from app.schemas import (
|
||||
SubClienteCreate, SubClienteUpdate, SubClienteResponse,
|
||||
ConsumoTimbreCreate, MessageResponse
|
||||
)
|
||||
from app.dependencies import get_current_user
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/", response_model=SubClienteResponse, status_code=status.HTTP_201_CREATED)
|
||||
def crear_subcliente(
|
||||
subcliente: SubClienteCreate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Usuario = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Crear un nuevo subcliente asociado a un cliente
|
||||
"""
|
||||
# Verificar que el cliente existe
|
||||
cliente = db.query(Cliente).filter(Cliente.id == subcliente.cliente_id).first()
|
||||
|
||||
if not cliente:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Cliente no encontrado"
|
||||
)
|
||||
|
||||
# Verificar que el cliente permite subclientes
|
||||
if not cliente.permite_subclientes:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Este cliente no permite crear subclientes"
|
||||
)
|
||||
|
||||
# Verificar si el email ya existe
|
||||
if db.query(SubCliente).filter(SubCliente.email == subcliente.email).first():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="El email ya está registrado"
|
||||
)
|
||||
|
||||
# Verificar si el RFC ya existe (si se proporciona)
|
||||
if subcliente.rfc and db.query(SubCliente).filter(SubCliente.rfc == subcliente.rfc).first():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="El RFC ya está registrado"
|
||||
)
|
||||
|
||||
db_subcliente = SubCliente(**subcliente.model_dump())
|
||||
|
||||
db.add(db_subcliente)
|
||||
db.commit()
|
||||
db.refresh(db_subcliente)
|
||||
|
||||
return db_subcliente
|
||||
|
||||
|
||||
@router.get("/", response_model=List[SubClienteResponse])
|
||||
def listar_subclientes(
|
||||
cliente_id: int = None,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Usuario = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Listar subclientes, opcionalmente filtrados por cliente_id
|
||||
"""
|
||||
query = db.query(SubCliente)
|
||||
|
||||
if cliente_id:
|
||||
query = query.filter(SubCliente.cliente_id == cliente_id)
|
||||
|
||||
subclientes = query.offset(skip).limit(limit).all()
|
||||
return subclientes
|
||||
|
||||
|
||||
@router.get("/{subcliente_id}", response_model=SubClienteResponse)
|
||||
def obtener_subcliente(
|
||||
subcliente_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Usuario = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Obtener un subcliente por ID
|
||||
"""
|
||||
subcliente = db.query(SubCliente).filter(SubCliente.id == subcliente_id).first()
|
||||
|
||||
if not subcliente:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="SubCliente no encontrado"
|
||||
)
|
||||
|
||||
return subcliente
|
||||
|
||||
|
||||
@router.put("/{subcliente_id}", response_model=SubClienteResponse)
|
||||
def actualizar_subcliente(
|
||||
subcliente_id: int,
|
||||
subcliente_update: SubClienteUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Usuario = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Actualizar información de un subcliente
|
||||
"""
|
||||
db_subcliente = db.query(SubCliente).filter(SubCliente.id == subcliente_id).first()
|
||||
|
||||
if not db_subcliente:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="SubCliente no encontrado"
|
||||
)
|
||||
|
||||
update_data = subcliente_update.model_dump(exclude_unset=True)
|
||||
|
||||
# Verificar email único si se actualiza
|
||||
if "email" in update_data and update_data["email"] != db_subcliente.email:
|
||||
if db.query(SubCliente).filter(SubCliente.email == update_data["email"]).first():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="El email ya está registrado"
|
||||
)
|
||||
|
||||
# Verificar RFC único si se actualiza
|
||||
if "rfc" in update_data and update_data["rfc"] != db_subcliente.rfc:
|
||||
if db.query(SubCliente).filter(SubCliente.rfc == update_data["rfc"]).first():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="El RFC ya está registrado"
|
||||
)
|
||||
|
||||
for field, value in update_data.items():
|
||||
setattr(db_subcliente, field, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_subcliente)
|
||||
|
||||
return db_subcliente
|
||||
|
||||
|
||||
@router.delete("/{subcliente_id}", response_model=MessageResponse)
|
||||
def eliminar_subcliente(
|
||||
subcliente_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Usuario = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Eliminar un subcliente
|
||||
"""
|
||||
db_subcliente = db.query(SubCliente).filter(SubCliente.id == subcliente_id).first()
|
||||
|
||||
if not db_subcliente:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="SubCliente no encontrado"
|
||||
)
|
||||
|
||||
db.delete(db_subcliente)
|
||||
db.commit()
|
||||
|
||||
return {"message": f"SubCliente {db_subcliente.nombre} eliminado exitosamente"}
|
||||
|
||||
|
||||
@router.post("/{subcliente_id}/consumir", response_model=MessageResponse)
|
||||
def consumir_timbre(
|
||||
subcliente_id: int,
|
||||
consumo: ConsumoTimbreCreate,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: Usuario = Depends(get_current_user)
|
||||
):
|
||||
"""
|
||||
Consumir timbres para un subcliente (descuenta del cliente padre)
|
||||
"""
|
||||
subcliente = db.query(SubCliente).filter(SubCliente.id == subcliente_id).first()
|
||||
|
||||
if not subcliente:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="SubCliente no encontrado"
|
||||
)
|
||||
|
||||
# Verificar que el subcliente esté activo
|
||||
if subcliente.estado != EstadoCliente.ACTIVO:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"El subcliente está {subcliente.estado}"
|
||||
)
|
||||
|
||||
cliente = db.query(Cliente).filter(Cliente.id == subcliente.cliente_id).first()
|
||||
|
||||
# Verificar que el cliente esté activo
|
||||
if cliente.estado != EstadoCliente.ACTIVO:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"El cliente está {cliente.estado}"
|
||||
)
|
||||
|
||||
# Obtener timbres disponibles calculados
|
||||
timbres_disponibles = cliente.get_timbres_disponibles(db)
|
||||
|
||||
# Verificar que hay timbres disponibles en el cliente
|
||||
if timbres_disponibles < consumo.cantidad:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Timbres insuficientes. Disponibles: {timbres_disponibles}, Solicitados: {consumo.cantidad}"
|
||||
)
|
||||
|
||||
# Verificar límite propio del subcliente si existe
|
||||
if subcliente.limite_propio is not None:
|
||||
timbres_disponibles_subcliente = subcliente.limite_propio - subcliente.timbres_consumidos
|
||||
if timbres_disponibles_subcliente < consumo.cantidad:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Límite del subcliente excedido. Disponibles: {timbres_disponibles_subcliente}"
|
||||
)
|
||||
|
||||
# Realizar el consumo
|
||||
cliente.timbres_consumidos += consumo.cantidad
|
||||
subcliente.timbres_consumidos += consumo.cantidad
|
||||
|
||||
# Calcular nuevo balance
|
||||
nuevo_balance = cliente.get_timbres_disponibles(db)
|
||||
|
||||
# Registrar movimiento
|
||||
movimiento = MovimientoTimbre(
|
||||
cliente_id=cliente.id,
|
||||
subcliente_id=subcliente.id,
|
||||
tipo=TipoMovimiento.CONSUMO,
|
||||
cantidad=consumo.cantidad,
|
||||
descripcion=consumo.descripcion,
|
||||
referencia_externa=consumo.referencia_externa,
|
||||
balance_cliente=nuevo_balance
|
||||
)
|
||||
|
||||
db.add(movimiento)
|
||||
db.commit()
|
||||
|
||||
return {
|
||||
"message": f"Se consumieron {consumo.cantidad} timbre(s) exitosamente",
|
||||
"detail": {
|
||||
"subcliente": subcliente.nombre,
|
||||
"timbres_consumidos_subcliente": subcliente.timbres_consumidos,
|
||||
"timbres_disponibles_cliente": nuevo_balance
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user