Sync Indy integre dans l'interface web + anti-doublon
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
"""
|
||||
Mapping des transactions Indy -> lignes d'import JB Compta.
|
||||
|
||||
Indy ne renvoie pas un nom de catégorie mais un **numéro de compte du plan
|
||||
comptable (PCG)** dans `subdivisions[].accounting_account.number`. On mappe ce
|
||||
numéro vers nos catégories. Bien plus fiable que du texte.
|
||||
|
||||
Sortie : un dict par transaction au format attendu par l'import JB Compta :
|
||||
{date, libelle, categorie, activite, taux, regime, montant}
|
||||
"""
|
||||
from decimal import Decimal
|
||||
|
||||
# Préfixe de compte PCG -> nom de catégorie JB Compta (le préfixe le plus long gagne).
|
||||
COMPTE_CATEGORIE = [
|
||||
("701", "Vente de produits finis"),
|
||||
("707", "Vente de produits finis"),
|
||||
("706", "Prestation de services"),
|
||||
("605", "Matériel et outillage"),
|
||||
("606", "Matériel et outillage"),
|
||||
("607", "Matériel et outillage"),
|
||||
("6256", "Frais de repas hors domicile"),
|
||||
("6253", "Frais de repas hors domicile"),
|
||||
("626", "Télécom, fournitures, documentation"),
|
||||
("6181", "Télécom, fournitures, documentation"),
|
||||
("6183", "Télécom, fournitures, documentation"),
|
||||
("6136", "Abonnement logiciel"),
|
||||
("6226", "Abonnement logiciel"),
|
||||
("646", "Cotisation sociale Urssaf"),
|
||||
("44551", "TVA payée"),
|
||||
("44558", "TVA payée"),
|
||||
("44583", "Remboursement de TVA"),
|
||||
("108", "Prélèvement personnel"),
|
||||
# 471 (compte d'attente) et 6252 (déplacements) -> non mappés (à catégoriser)
|
||||
]
|
||||
|
||||
# Compte de vente -> activité (pour le multi-activité)
|
||||
COMPTE_ACTIVITE = [
|
||||
("701", "vente"), ("707", "vente"),
|
||||
("706", "service_bic"),
|
||||
]
|
||||
|
||||
|
||||
def _cat(num):
|
||||
num = str(num or "")
|
||||
best = None
|
||||
for pref, cat in COMPTE_CATEGORIE:
|
||||
if num.startswith(pref) and (best is None or len(pref) > len(best[0])):
|
||||
best = (pref, cat)
|
||||
return best[1] if best else None
|
||||
|
||||
|
||||
def _act(num):
|
||||
num = str(num or "")
|
||||
for pref, act in COMPTE_ACTIVITE:
|
||||
if num.startswith(pref):
|
||||
return act
|
||||
return ""
|
||||
|
||||
|
||||
def normaliser(tx):
|
||||
"""Transaction Indy -> ligne d'import (ou None si inexploitable)."""
|
||||
try:
|
||||
montant = (Decimal(tx["totalAmountInCents"]) / 100).quantize(Decimal("0.01"))
|
||||
except Exception:
|
||||
return None
|
||||
subs = [s for s in tx.get("subdivisions", [])
|
||||
if not str((s.get("accounting_account") or {}).get("number", "")).startswith("512")]
|
||||
if not subs:
|
||||
return None
|
||||
# Subdivision principale = plus gros montant absolu (hors compte bancaire 512).
|
||||
main = max(subs, key=lambda s: abs(s.get("amount_in_cents", 0)))
|
||||
num = str((main.get("accounting_account") or {}).get("number", ""))
|
||||
intra = main.get("tva_intracom")
|
||||
if intra and intra.get("type") == "eu":
|
||||
regime = "intracom"
|
||||
taux = (Decimal(intra.get("rate", 0)) / 100)
|
||||
else:
|
||||
regime = "nationale"
|
||||
taux = (Decimal(main.get("tva_rate", 0)) / 100)
|
||||
return {
|
||||
"date": tx.get("date", ""),
|
||||
"libelle": tx.get("description") or tx.get("raw_description") or "(sans libellé)",
|
||||
"categorie": _cat(num),
|
||||
"activite": _act(num),
|
||||
"taux": taux,
|
||||
"regime": regime,
|
||||
"montant": montant,
|
||||
"compte": num,
|
||||
}
|
||||
|
||||
|
||||
def vers_csv(transactions):
|
||||
"""Liste de transactions Indy -> CSV au format import JB Compta."""
|
||||
lignes = ["date;libelle;categorie;activite;taux_tva;regime;montant"]
|
||||
for tx in transactions:
|
||||
r = normaliser(tx)
|
||||
if not r:
|
||||
continue
|
||||
regime = "" if r["regime"] == "nationale" else r["regime"]
|
||||
taux = f"{r['taux']:.2f}".rstrip("0").rstrip(".")
|
||||
lignes.append(";".join([
|
||||
r["date"], r["libelle"], r["categorie"] or "", r["activite"],
|
||||
taux, regime, f"{r['montant']:.2f}"]))
|
||||
return "\n".join(lignes)
|
||||
Reference in New Issue
Block a user