Init project
This commit is contained in:
189
routers/factures.py
Normal file
189
routers/factures.py
Normal file
@@ -0,0 +1,189 @@
|
||||
import json
|
||||
from datetime import date, timedelta
|
||||
from fastapi import APIRouter, Depends, Request, Form, HTTPException
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse, Response
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from database import get_db
|
||||
from models import Facture, LigneFacture, Client, StatutFacture
|
||||
from numerotation import generer_numero_facture
|
||||
from config import settings
|
||||
from auth import get_current_user
|
||||
from template_helper import render
|
||||
|
||||
router = APIRouter(prefix="/factures", tags=["factures"], dependencies=[Depends(get_current_user)])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
def liste_factures(request: Request, db: Session = Depends(get_db)):
|
||||
factures = db.query(Facture).order_by(Facture.date_emission.desc()).all()
|
||||
return render(templates, "factures/liste.html", request, {
|
||||
"factures": factures
|
||||
})
|
||||
|
||||
|
||||
@router.get("/nouvelle", response_class=HTMLResponse)
|
||||
def nouvelle_facture_form(request: Request, db: Session = Depends(get_db)):
|
||||
clients = db.query(Client).filter(Client.actif == True).order_by(Client.nom).all()
|
||||
return render(templates, "factures/form.html", request, {
|
||||
"facture": None,
|
||||
"clients": clients,
|
||||
"titre": "Nouvelle facture",
|
||||
"date_aujourd_hui": date.today().isoformat(),
|
||||
"date_echeance_defaut": (date.today() + timedelta(days=30)).isoformat(),
|
||||
})
|
||||
|
||||
|
||||
@router.post("/nouvelle")
|
||||
def creer_facture(
|
||||
client_id: int = Form(...),
|
||||
date_emission: str = Form(...),
|
||||
date_echeance: str = Form(...),
|
||||
notes: str = Form(""),
|
||||
conditions_reglement: str = Form("Paiement à réception de facture."),
|
||||
lignes_json: str = Form(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
numero = generer_numero_facture(db)
|
||||
facture = Facture(
|
||||
numero=numero,
|
||||
client_id=client_id,
|
||||
date_emission=date.fromisoformat(date_emission),
|
||||
date_echeance=date.fromisoformat(date_echeance),
|
||||
notes=notes,
|
||||
conditions_reglement=conditions_reglement,
|
||||
)
|
||||
db.add(facture)
|
||||
db.flush()
|
||||
|
||||
lignes = json.loads(lignes_json)
|
||||
for i, l in enumerate(lignes):
|
||||
ligne = LigneFacture(
|
||||
facture_id=facture.id,
|
||||
description=l["description"],
|
||||
quantite=float(l["quantite"]),
|
||||
prix_unitaire_ht=float(l["prix_unitaire_ht"]),
|
||||
ordre=i
|
||||
)
|
||||
db.add(ligne)
|
||||
|
||||
db.commit()
|
||||
return RedirectResponse(f"/factures/{facture.id}", status_code=303)
|
||||
|
||||
|
||||
@router.get("/{facture_id}", response_class=HTMLResponse)
|
||||
def voir_facture(request: Request, facture_id: int, db: Session = Depends(get_db)):
|
||||
facture = db.query(Facture).get(facture_id)
|
||||
if not facture:
|
||||
raise HTTPException(status_code=404)
|
||||
return render(templates, "factures/detail.html", request, {
|
||||
"facture": facture, "StatutFacture": StatutFacture
|
||||
})
|
||||
|
||||
|
||||
@router.get("/{facture_id}/modifier", response_class=HTMLResponse)
|
||||
def modifier_facture_form(request: Request, facture_id: int, db: Session = Depends(get_db)):
|
||||
facture = db.query(Facture).get(facture_id)
|
||||
if not facture:
|
||||
raise HTTPException(status_code=404)
|
||||
if facture.statut != StatutFacture.emise:
|
||||
raise HTTPException(status_code=400, detail="Seules les factures émises peuvent être modifiées.")
|
||||
clients = db.query(Client).filter(Client.actif == True).order_by(Client.nom).all()
|
||||
return render(templates, "factures/form.html", request, {
|
||||
"facture": facture,
|
||||
"clients": clients,
|
||||
"titre": "Modifier la facture",
|
||||
"date_aujourd_hui": facture.date_emission.isoformat(),
|
||||
"date_echeance_defaut": facture.date_echeance.isoformat(),
|
||||
})
|
||||
|
||||
|
||||
@router.post("/{facture_id}/modifier")
|
||||
def modifier_facture(
|
||||
facture_id: int,
|
||||
client_id: int = Form(...),
|
||||
date_emission: str = Form(...),
|
||||
date_echeance: str = Form(...),
|
||||
notes: str = Form(""),
|
||||
conditions_reglement: str = Form(""),
|
||||
lignes_json: str = Form(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
facture = db.query(Facture).get(facture_id)
|
||||
if not facture:
|
||||
raise HTTPException(status_code=404)
|
||||
facture.client_id = client_id
|
||||
facture.date_emission = date.fromisoformat(date_emission)
|
||||
facture.date_echeance = date.fromisoformat(date_echeance)
|
||||
facture.notes = notes
|
||||
facture.conditions_reglement = conditions_reglement
|
||||
|
||||
for ligne in facture.lignes:
|
||||
db.delete(ligne)
|
||||
db.flush()
|
||||
|
||||
lignes = json.loads(lignes_json)
|
||||
for i, l in enumerate(lignes):
|
||||
ligne = LigneFacture(
|
||||
facture_id=facture.id,
|
||||
description=l["description"],
|
||||
quantite=float(l["quantite"]),
|
||||
prix_unitaire_ht=float(l["prix_unitaire_ht"]),
|
||||
ordre=i
|
||||
)
|
||||
db.add(ligne)
|
||||
|
||||
db.commit()
|
||||
return RedirectResponse(f"/factures/{facture_id}", status_code=303)
|
||||
|
||||
|
||||
@router.post("/{facture_id}/statut")
|
||||
def changer_statut_facture(
|
||||
facture_id: int,
|
||||
statut: str = Form(...),
|
||||
date_paiement: str = Form(""),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
facture = db.query(Facture).get(facture_id)
|
||||
if not facture:
|
||||
raise HTTPException(status_code=404)
|
||||
facture.statut = StatutFacture(statut)
|
||||
if statut == "payee" and date_paiement:
|
||||
facture.date_paiement = date.fromisoformat(date_paiement)
|
||||
db.commit()
|
||||
return RedirectResponse(f"/factures/{facture_id}", status_code=303)
|
||||
|
||||
|
||||
@router.get("/{facture_id}/pdf")
|
||||
def telecharger_pdf(facture_id: int, db: Session = Depends(get_db)):
|
||||
from weasyprint import HTML
|
||||
facture = db.query(Facture).get(facture_id)
|
||||
if not facture:
|
||||
raise HTTPException(status_code=404)
|
||||
|
||||
html_content = templates.get_template("pdf/facture.html").render({
|
||||
"facture": facture,
|
||||
"settings": settings,
|
||||
})
|
||||
|
||||
pdf_bytes = HTML(string=html_content, base_url=".").write_pdf()
|
||||
|
||||
filename = f"facture-{facture.numero}.pdf"
|
||||
return Response(
|
||||
content=pdf_bytes,
|
||||
media_type="application/pdf",
|
||||
headers={"Content-Disposition": f'attachment; filename="{filename}"'}
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{facture_id}/apercu-pdf", response_class=HTMLResponse)
|
||||
def apercu_pdf(request: Request, facture_id: int, db: Session = Depends(get_db)):
|
||||
facture = db.query(Facture).get(facture_id)
|
||||
if not facture:
|
||||
raise HTTPException(status_code=404)
|
||||
return render(templates, "pdf/facture.html", request, {
|
||||
"facture": facture,
|
||||
"settings": settings,
|
||||
})
|
||||
Reference in New Issue
Block a user