"""Routes S3 — Vente de littérature.""" from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, desc from app.core.database import get_db from app.core.security import get_current_membre from app.models.litterature import Litterature from app.models.vente_litterature import VenteLitterature from app.models.membre import Membre from app.models.affectation import Affectation from app.models.poste import Poste from app.schemas.phase6 import VenteCreate, VenteOut router = APIRouter(prefix="/ventes-litterature", tags=["S3 — Vente littérature"]) async def require_resp_litterature(membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db)): """Vérifie que le membre est responsable de la littérature.""" result = await db.execute( select(Affectation).join(Poste).where( Affectation.membre_id == membre.id, Affectation.statut == "actif", Poste.nom.ilike("%littérature%"), ) ) if not result.scalars().first(): raise HTTPException(status_code=403, detail="Réservé au responsable de la littérature") return membre @router.post("/", response_model=VenteOut) async def enregistrer_vente( req: VenteCreate, membre=Depends(require_resp_litterature), db: AsyncSession = Depends(get_db), ): """S3 — Enregistrer une vente de littérature. Le stock est décrémenté automatiquement.""" # Vérifier le titre result = await db.execute( select(Litterature).where( Litterature.id == req.litterature_id, Litterature.groupe_id == membre.groupe_id, ) ) item = result.scalar_one_or_none() if not item: raise HTTPException(status_code=404, detail="Titre introuvable") if req.quantite <= 0: raise HTTPException(status_code=400, detail="La quantité doit être positive") if item.quantite_stock < req.quantite: raise HTTPException( status_code=400, detail=f"Stock insuffisant ({item.quantite_stock} disponible, {req.quantite} demandé)" ) # Décrémenter le stock item.quantite_stock -= req.quantite # Créer la vente vente = VenteLitterature( litterature_id=req.litterature_id, groupe_id=membre.groupe_id, quantite=req.quantite, montant=req.montant, date_vente=req.date_vente, vendu_par=membre.id, ) db.add(vente) await db.flush() return VenteOut( id=vente.id, litterature_titre=item.titre, quantite=vente.quantite, montant=float(vente.montant), date_vente=vente.date_vente, vendu_par_prenom=membre.prenom, cree_le=vente.cree_le, ) @router.get("/", response_model=list[VenteOut]) async def liste_ventes( limite: int = 20, membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """Lister les ventes récentes.""" result = await db.execute( select(VenteLitterature) .where(VenteLitterature.groupe_id == membre.groupe_id) .order_by(desc(VenteLitterature.date_vente)) .limit(limite) ) ventes = result.scalars().all() out = [] for v in ventes: item = await db.get(Litterature, v.litterature_id) vendeur = await db.get(Membre, v.vendu_par) if v.vendu_par else None out.append(VenteOut( id=v.id, litterature_titre=item.titre if item else "?", quantite=v.quantite, montant=float(v.montant), date_vente=v.date_vente, vendu_par_prenom=vendeur.prenom if vendeur else None, remis_tresorier=v.remis_tresorier, cree_le=v.cree_le, )) return out @router.get("/a-recevoir") async def ventes_a_recevoir( membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """Ventes dont le montant n'a pas encore été remis au trésorier.""" result = await db.execute( select(VenteLitterature) .where( VenteLitterature.groupe_id == membre.groupe_id, VenteLitterature.remis_tresorier == False, ) .order_by(desc(VenteLitterature.date_vente)) ) ventes = result.scalars().all() out = [] for v in ventes: item = await db.get(Litterature, v.litterature_id) vendeur = await db.get(Membre, v.vendu_par) if v.vendu_par else None out.append({ "id": str(v.id), "litterature_titre": item.titre if item else "?", "quantite": v.quantite, "montant": float(v.montant), "date_vente": str(v.date_vente), "vendu_par_prenom": vendeur.prenom if vendeur else None, }) return out @router.post("/{vente_id}/recevoir") async def confirmer_reception_vente( vente_id: str, membre=Depends(get_current_membre), db: AsyncSession = Depends(get_db), ): """Le trésorier confirme la réception du montant de la vente.""" # Vérifier que c'est le trésorier ou exécutif result = await db.execute( select(Affectation).join(Poste).where( Affectation.membre_id == membre.id, Affectation.statut == "actif", (Poste.nom.ilike("%trésorier%") | (Poste.categorie == "executif")), ) ) if not result.scalars().first(): raise HTTPException(status_code=403, detail="Réservé au trésorier ou à l'exécutif") result = await db.execute( select(VenteLitterature).where( VenteLitterature.id == vente_id, VenteLitterature.groupe_id == membre.groupe_id, ) ) vente = result.scalar_one_or_none() if not vente: raise HTTPException(status_code=404, detail="Vente introuvable") if vente.remis_tresorier: raise HTTPException(status_code=400, detail="Déjà reçue") from datetime import date as date_type vente.remis_tresorier = True vente.recu_par = membre.id vente.date_remise = date_type.today() await db.flush() return {"message": "Réception confirmée"}