Files
get_ovh_bills/main.py
2025-09-05 11:08:40 +02:00

145 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from datetime import datetime
import dotenv
import ovh
import fetcher as ft
from urllib.request import urlretrieve
import logging
from logging.handlers import RotatingFileHandler
# --- Configuration du logging ---
logging.addLevelName(logging.DEBUG, "DÉBOGAGE")
logging.addLevelName(logging.INFO, "INFO")
logging.addLevelName(logging.WARNING, "AVERTISSEMENT")
logging.addLevelName(logging.ERROR, "ERREUR")
logging.addLevelName(logging.CRITICAL, "CRITIQUE")
logger = logging.getLogger("ovh_factures")
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
fmt="%(asctime)s | %(levelname)s | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
# Console
ch = logging.StreamHandler()
ch.setFormatter(formatter)
logger.addHandler(ch)
# Fichier
fh = RotatingFileHandler(
"ovh_factures.log", maxBytes=5_000_000, backupCount=3, encoding="utf-8"
)
fh.setFormatter(formatter)
logger.addHandler(fh)
# Chargement des variables d'environnement (.env)
dotenv.load_dotenv()
APP_KEY = os.environ["APP_KEY"]
APP_SECRET = os.environ["APP_SECRET"]
CONSUMER_KEY = os.environ["CONSUMER_KEY"]
PATH_OVH = os.environ["OVH_PATH"]
YEAR = datetime.now().year # Année courante (int)
def indexer(ids: list[str]) -> list[str]:
"""
Parcourt le répertoire de l'année courante et compare les factures déjà présentes
avec la liste d'IDs renvoyée par OVH. Ne conserve que les factures absentes
ET datées de l'année courante.
"""
logger.info("Indexation des factures pour l'année %s", YEAR)
target_dir = f"{PATH_OVH}{YEAR}"
try:
ids_already_in = os.listdir(target_dir)
except FileNotFoundError:
logger.warning("Dossier %s inexistant, aucune facture locale", target_dir)
ids_already_in = []
missing = [x for x in ids if f"{x}.pdf" not in ids_already_in]
logger.info("%d factures absentes détectées", len(missing))
result: list[str] = []
for bill_id in missing:
try:
meta = ft.fetch_invoice_content(
bill_id,
app_key=APP_KEY,
app_secret=APP_SECRET,
consumer_key=CONSUMER_KEY,
)
except Exception as e:
logger.error("Impossible de récupérer la méta pour %s : %s", bill_id, e)
continue
bill_year = datetime.fromisoformat(meta["date"]).year
if bill_year == YEAR:
result.append(bill_id)
logger.info("%d factures retenues pour téléchargement", len(result))
return result
def get_ids() -> list[str]:
"""
Interroge lAPI OVH et renvoie la liste des IDs de toutes les factures.
"""
logger.info("Récupération de la liste des factures via API OVH")
try:
return ft.fetch_api(
app_key=APP_KEY,
app_secret=APP_SECRET,
consumer_key=CONSUMER_KEY,
)
except ovh.exceptions.APIError as e:
logger.error("Échec récupération des IDs de factures : %s", e)
raise RuntimeError(f"Échec de la récupération des IDs de factures : {e}") from e
def get_bill(bill_id: str) -> dict:
"""
Récupère, via lAPI OVH, les informations détaillées dune facture (JSON).
"""
logger.debug("Récupération de la facture %s", bill_id)
try:
return ft.fetch_invoice_content(
bill_id,
app_key=APP_KEY,
app_secret=APP_SECRET,
consumer_key=CONSUMER_KEY,
)
except ovh.exceptions.APIError as e:
logger.error("Échec récupération de la facture %s : %s", bill_id, e)
raise RuntimeError(
f"Échec de la récupération de la facture {bill_id} : {e}"
) from e
def save_pdf(bill: dict) -> None:
"""
Télécharge le PDF dune facture dans un sous-dossier par année.
Noms de fichiers : <billId>.pdf
"""
date = datetime.fromisoformat(bill["date"]).date()
path = f"{PATH_OVH}{date.year}/"
os.makedirs(path, exist_ok=True)
url = bill["pdfUrl"]
dest = f"{path}{bill['billId']}.pdf"
try:
urlretrieve(url, dest)
logger.info("Facture %s sauvegardée dans %s", bill["billId"], dest)
except Exception as e:
logger.error("Impossible de télécharger la facture %s : %s", bill["billId"], e)
raise
if __name__ == "__main__":
logger.info("Démarrage du traitement des factures OVH pour %s", YEAR)
os.makedirs(f"{PATH_OVH}{YEAR}", exist_ok=True)
ids_candidats = indexer(get_ids())
for bill_id in ids_candidats:
save_pdf(get_bill(bill_id))
logger.info("Traitement terminé : %d factures téléchargées", len(ids_candidats))