forked from seb_vallee/BillManager
Init project
This commit is contained in:
162
routers/auth.py
Normal file
162
routers/auth.py
Normal file
@@ -0,0 +1,162 @@
|
||||
from template_helper import render
|
||||
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 User
|
||||
from auth import (
|
||||
hasher_mot_de_passe, verifier_mot_de_passe,
|
||||
creer_session, get_current_admin, COOKIE_NAME
|
||||
)
|
||||
from config import settings
|
||||
|
||||
router = APIRouter(tags=["auth"])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
# ── Login / Logout ─────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/login", response_class=HTMLResponse)
|
||||
def login_form(request: Request):
|
||||
return render(templates, "auth/login.html", request, {
|
||||
"erreur": None
|
||||
})
|
||||
|
||||
|
||||
@router.post("/login")
|
||||
def login(
|
||||
request: Request,
|
||||
username: str = Form(...),
|
||||
password: str = Form(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
user = db.query(User).filter(
|
||||
User.username == username, User.actif == True
|
||||
).first()
|
||||
|
||||
if not user or not verifier_mot_de_passe(password, user.hashed_password):
|
||||
return render(templates, "auth/login.html", request, {
|
||||
"erreur": "Identifiants incorrects."
|
||||
}, status_code=401)
|
||||
|
||||
token = creer_session(user.id)
|
||||
response = RedirectResponse("/factures/", status_code=303)
|
||||
response.set_cookie(
|
||||
key=COOKIE_NAME,
|
||||
value=token,
|
||||
max_age=settings.session_max_age,
|
||||
httponly=True,
|
||||
samesite="lax",
|
||||
secure=False # Passer à True si HTTPS (recommandé en prod)
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
@router.post("/logout")
|
||||
def logout():
|
||||
response = RedirectResponse("/login", status_code=303)
|
||||
response.delete_cookie(COOKIE_NAME)
|
||||
return response
|
||||
|
||||
|
||||
# ── Gestion utilisateurs (admin) ───────────────────────────────────────────────
|
||||
|
||||
@router.get("/admin/utilisateurs", response_class=HTMLResponse)
|
||||
def liste_utilisateurs(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_user=Depends(get_current_admin)
|
||||
):
|
||||
users = db.query(User).order_by(User.username).all()
|
||||
return render(templates, "auth/utilisateurs.html", request, {
|
||||
"users": users, "current_user": current_user
|
||||
})
|
||||
|
||||
|
||||
@router.get("/admin/utilisateurs/nouveau", response_class=HTMLResponse)
|
||||
def nouveau_user_form(request: Request, current_user=Depends(get_current_admin)):
|
||||
return render(templates, "auth/user_form.html", request, {
|
||||
"user": None,
|
||||
"titre": "Nouvel utilisateur", "current_user": current_user
|
||||
})
|
||||
|
||||
|
||||
@router.post("/admin/utilisateurs/nouveau")
|
||||
def creer_user(
|
||||
username: str = Form(...),
|
||||
email: str = Form(""),
|
||||
password: str = Form(...),
|
||||
is_admin: bool = Form(False),
|
||||
db: Session = Depends(get_db),
|
||||
current_user=Depends(get_current_admin)
|
||||
):
|
||||
if db.query(User).filter(User.username == username).first():
|
||||
raise HTTPException(status_code=400, detail="Ce nom d'utilisateur existe déjà.")
|
||||
user = User(
|
||||
username=username,
|
||||
email=email,
|
||||
hashed_password=hasher_mot_de_passe(password),
|
||||
is_admin=is_admin
|
||||
)
|
||||
db.add(user)
|
||||
db.commit()
|
||||
return RedirectResponse("/admin/utilisateurs", status_code=303)
|
||||
|
||||
|
||||
@router.get("/admin/utilisateurs/{user_id}/modifier", response_class=HTMLResponse)
|
||||
def modifier_user_form(
|
||||
request: Request,
|
||||
user_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user=Depends(get_current_admin)
|
||||
):
|
||||
user = db.query(User).get(user_id)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404)
|
||||
return render(templates, "auth/user_form.html", request, {
|
||||
"user": user,
|
||||
"titre": "Modifier l'utilisateur", "current_user": current_user
|
||||
})
|
||||
|
||||
|
||||
@router.post("/admin/utilisateurs/{user_id}/modifier")
|
||||
def modifier_user(
|
||||
user_id: int,
|
||||
username: str = Form(...),
|
||||
email: str = Form(""),
|
||||
password: str = Form(""),
|
||||
is_admin: bool = Form(False),
|
||||
db: Session = Depends(get_db),
|
||||
current_user=Depends(get_current_admin)
|
||||
):
|
||||
user = db.query(User).get(user_id)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404)
|
||||
# Empêcher de se retirer les droits admin à soi-même
|
||||
if user.id == current_user.id and not is_admin:
|
||||
raise HTTPException(status_code=400, detail="Vous ne pouvez pas retirer vos propres droits admin.")
|
||||
user.username = username
|
||||
user.email = email
|
||||
user.is_admin = is_admin
|
||||
if password:
|
||||
user.hashed_password = hasher_mot_de_passe(password)
|
||||
db.commit()
|
||||
return RedirectResponse("/admin/utilisateurs", status_code=303)
|
||||
|
||||
|
||||
@router.post("/admin/utilisateurs/{user_id}/desactiver")
|
||||
def desactiver_user(
|
||||
user_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user=Depends(get_current_admin)
|
||||
):
|
||||
user = db.query(User).get(user_id)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404)
|
||||
if user.id == current_user.id:
|
||||
raise HTTPException(status_code=400, detail="Impossible de se désactiver soi-même.")
|
||||
user.actif = not user.actif
|
||||
db.commit()
|
||||
return RedirectResponse("/admin/utilisateurs", status_code=303)
|
||||
95
routers/clients.py
Normal file
95
routers/clients.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from fastapi import APIRouter, Depends, Request, Form, HTTPException
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from database import get_db
|
||||
from models import Client
|
||||
from auth import get_current_user
|
||||
from template_helper import render
|
||||
|
||||
router = APIRouter(prefix="/clients", tags=["clients"],
|
||||
dependencies=[Depends(get_current_user)])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
def liste_clients(request: Request, db: Session = Depends(get_db)):
|
||||
clients = db.query(Client).filter(Client.actif == True).order_by(Client.nom).all()
|
||||
return render(templates, "clients/liste.html", request, {
|
||||
"clients": clients
|
||||
})
|
||||
|
||||
|
||||
@router.get("/nouveau", response_class=HTMLResponse)
|
||||
def nouveau_client_form(request: Request):
|
||||
return render(templates, "clients/form.html", request, {
|
||||
"client": None, "titre": "Nouveau client"
|
||||
})
|
||||
|
||||
|
||||
@router.post("/nouveau")
|
||||
def creer_client(
|
||||
request: Request,
|
||||
nom: str = Form(...),
|
||||
adresse: str = Form(...),
|
||||
code_postal: str = Form(...),
|
||||
ville: str = Form(...),
|
||||
email: str = Form(""),
|
||||
telephone: str = Form(""),
|
||||
siret: str = Form(""),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
client = Client(
|
||||
nom=nom, adresse=adresse, code_postal=code_postal,
|
||||
ville=ville, email=email, telephone=telephone, siret=siret
|
||||
)
|
||||
db.add(client)
|
||||
db.commit()
|
||||
return RedirectResponse("/clients/", status_code=303)
|
||||
|
||||
|
||||
@router.get("/{client_id}/modifier", response_class=HTMLResponse)
|
||||
def modifier_client_form(request: Request, client_id: int, db: Session = Depends(get_db)):
|
||||
client = db.query(Client).get(client_id)
|
||||
if not client:
|
||||
raise HTTPException(status_code=404)
|
||||
return render(templates, "clients/form.html", request, {
|
||||
"client": client, "titre": "Modifier le client"
|
||||
})
|
||||
|
||||
|
||||
@router.post("/{client_id}/modifier")
|
||||
def modifier_client(
|
||||
client_id: int,
|
||||
nom: str = Form(...),
|
||||
adresse: str = Form(...),
|
||||
code_postal: str = Form(...),
|
||||
ville: str = Form(...),
|
||||
email: str = Form(""),
|
||||
telephone: str = Form(""),
|
||||
siret: str = Form(""),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
client = db.query(Client).get(client_id)
|
||||
if not client:
|
||||
raise HTTPException(status_code=404)
|
||||
client.nom = nom
|
||||
client.adresse = adresse
|
||||
client.code_postal = code_postal
|
||||
client.ville = ville
|
||||
client.email = email
|
||||
client.telephone = telephone
|
||||
client.siret = siret
|
||||
db.commit()
|
||||
return RedirectResponse("/clients/", status_code=303)
|
||||
|
||||
|
||||
@router.post("/{client_id}/supprimer")
|
||||
def supprimer_client(client_id: int, db: Session = Depends(get_db)):
|
||||
client = db.query(Client).get(client_id)
|
||||
if not client:
|
||||
raise HTTPException(status_code=404)
|
||||
client.actif = False
|
||||
db.commit()
|
||||
return RedirectResponse("/clients/", status_code=303)
|
||||
186
routers/devis.py
Normal file
186
routers/devis.py
Normal file
@@ -0,0 +1,186 @@
|
||||
import json
|
||||
from datetime import date, timedelta
|
||||
from fastapi import APIRouter, Depends, Request, Form, HTTPException
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from database import get_db
|
||||
from models import Devis, LigneDevis, Client, StatutDevis
|
||||
from numerotation import generer_numero_devis
|
||||
from auth import get_current_user
|
||||
from template_helper import render
|
||||
|
||||
router = APIRouter(prefix="/devis", tags=["devis"], dependencies=[Depends(get_current_user)])
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
def liste_devis(request: Request, db: Session = Depends(get_db)):
|
||||
devis = db.query(Devis).order_by(Devis.date_emission.desc()).all()
|
||||
return render(templates, "devis/liste.html", request, {
|
||||
"devis": devis
|
||||
})
|
||||
|
||||
|
||||
@router.get("/nouveau", response_class=HTMLResponse)
|
||||
def nouveau_devis_form(request: Request, db: Session = Depends(get_db)):
|
||||
clients = db.query(Client).filter(Client.actif == True).order_by(Client.nom).all()
|
||||
return render(templates, "devis/form.html", request, {
|
||||
"devis": None,
|
||||
"clients": clients,
|
||||
"titre": "Nouveau devis",
|
||||
"date_aujourd_hui": date.today().isoformat(),
|
||||
"date_validite_defaut": (date.today() + timedelta(days=30)).isoformat(),
|
||||
})
|
||||
|
||||
|
||||
@router.post("/nouveau")
|
||||
def creer_devis(
|
||||
request: Request,
|
||||
client_id: int = Form(...),
|
||||
date_emission: str = Form(...),
|
||||
date_validite: str = Form(...),
|
||||
notes: str = Form(""),
|
||||
conditions: str = Form(""),
|
||||
lignes_json: str = Form(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
numero = generer_numero_devis(db)
|
||||
devis = Devis(
|
||||
numero=numero,
|
||||
client_id=client_id,
|
||||
date_emission=date.fromisoformat(date_emission),
|
||||
date_validite=date.fromisoformat(date_validite),
|
||||
notes=notes,
|
||||
conditions=conditions,
|
||||
)
|
||||
db.add(devis)
|
||||
db.flush()
|
||||
|
||||
lignes = json.loads(lignes_json)
|
||||
for i, l in enumerate(lignes):
|
||||
ligne = LigneDevis(
|
||||
devis_id=devis.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"/devis/{devis.id}", status_code=303)
|
||||
|
||||
|
||||
@router.get("/{devis_id}", response_class=HTMLResponse)
|
||||
def voir_devis(request: Request, devis_id: int, db: Session = Depends(get_db)):
|
||||
devis = db.query(Devis).get(devis_id)
|
||||
if not devis:
|
||||
raise HTTPException(status_code=404)
|
||||
return render(templates, "devis/detail.html", request, {
|
||||
"devis": devis, "StatutDevis": StatutDevis
|
||||
})
|
||||
|
||||
|
||||
@router.get("/{devis_id}/modifier", response_class=HTMLResponse)
|
||||
def modifier_devis_form(request: Request, devis_id: int, db: Session = Depends(get_db)):
|
||||
devis = db.query(Devis).get(devis_id)
|
||||
if not devis:
|
||||
raise HTTPException(status_code=404)
|
||||
clients = db.query(Client).filter(Client.actif == True).order_by(Client.nom).all()
|
||||
return render(templates, "devis/form.html", request, {
|
||||
"devis": devis,
|
||||
"clients": clients,
|
||||
"titre": "Modifier le devis",
|
||||
"date_aujourd_hui": date.today().isoformat(),
|
||||
"date_validite_defaut": devis.date_validite.isoformat(),
|
||||
})
|
||||
|
||||
|
||||
@router.post("/{devis_id}/modifier")
|
||||
def modifier_devis(
|
||||
devis_id: int,
|
||||
client_id: int = Form(...),
|
||||
date_emission: str = Form(...),
|
||||
date_validite: str = Form(...),
|
||||
notes: str = Form(""),
|
||||
conditions: str = Form(""),
|
||||
lignes_json: str = Form(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
devis = db.query(Devis).get(devis_id)
|
||||
if not devis:
|
||||
raise HTTPException(status_code=404)
|
||||
devis.client_id = client_id
|
||||
devis.date_emission = date.fromisoformat(date_emission)
|
||||
devis.date_validite = date.fromisoformat(date_validite)
|
||||
devis.notes = notes
|
||||
devis.conditions = conditions
|
||||
|
||||
for ligne in devis.lignes:
|
||||
db.delete(ligne)
|
||||
db.flush()
|
||||
|
||||
lignes = json.loads(lignes_json)
|
||||
for i, l in enumerate(lignes):
|
||||
ligne = LigneDevis(
|
||||
devis_id=devis.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"/devis/{devis_id}", status_code=303)
|
||||
|
||||
|
||||
@router.post("/{devis_id}/statut")
|
||||
def changer_statut_devis(
|
||||
devis_id: int,
|
||||
statut: str = Form(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
devis = db.query(Devis).get(devis_id)
|
||||
if not devis:
|
||||
raise HTTPException(status_code=404)
|
||||
devis.statut = StatutDevis(statut)
|
||||
db.commit()
|
||||
return RedirectResponse(f"/devis/{devis_id}", status_code=303)
|
||||
|
||||
|
||||
@router.post("/{devis_id}/convertir")
|
||||
def convertir_en_facture(devis_id: int, db: Session = Depends(get_db)):
|
||||
from models import Facture, LigneFacture
|
||||
from numerotation import generer_numero_facture
|
||||
devis = db.query(Devis).get(devis_id)
|
||||
if not devis:
|
||||
raise HTTPException(status_code=404)
|
||||
|
||||
numero = generer_numero_facture(db)
|
||||
facture = Facture(
|
||||
numero=numero,
|
||||
client_id=devis.client_id,
|
||||
devis_id=devis.id,
|
||||
date_emission=date.today(),
|
||||
date_echeance=date.today() + timedelta(days=30),
|
||||
notes=devis.notes,
|
||||
)
|
||||
db.add(facture)
|
||||
db.flush()
|
||||
|
||||
for i, l in enumerate(devis.lignes):
|
||||
ligne = LigneFacture(
|
||||
facture_id=facture.id,
|
||||
description=l.description,
|
||||
quantite=l.quantite,
|
||||
prix_unitaire_ht=l.prix_unitaire_ht,
|
||||
ordre=i
|
||||
)
|
||||
db.add(ligne)
|
||||
|
||||
devis.statut = StatutDevis.accepte
|
||||
db.commit()
|
||||
return RedirectResponse(f"/factures/{facture.id}", status_code=303)
|
||||
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