mirror of
https://github.com/Fare-spec/get_ovh_bills.git
synced 2025-12-07 10:20:36 +00:00
145 lines
4.5 KiB
Python
145 lines
4.5 KiB
Python
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 l’API 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 l’API OVH, les informations détaillées d’une 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 d’une 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))
|