Skip to main content

django-accounting-fr

Application Django de comptabilité en partie double, conforme aux usages français : plan comptable général (PCG), journaux VT/BQ/AC/OD/AN, numérotation chronologique à la validation, écritures validées intangibles (correction par contre-passation), TVA collectée par taux, lettrage des comptes de tiers, rapprochement bancaire, clôture d'exercice et à-nouveaux, export FEC (art. A47 A-1 du LPF), journal d'audit.

Elle ne dépend d'aucun autre module : le projet hôte lui décrit ses pièces (ventes, encaissements, avoirs, remboursements) via une API Python.

Ce module produit une comptabilité tenue selon les règles du PCG et un FEC au format attendu ; il ne remplace pas l'expert-comptable ni un logiciel certifié lorsque la loi l'impose (caisse, facturation électronique).

Installation

pip install django-accounting-fr      # ou depuis un dépôt Git / un index privé
INSTALLED_APPS = [..., "accounting_fr"]  # libellé d'application : « accounting »
urlpatterns = [..., path("comptabilite/", include("accounting_fr.urls"))]
python manage.py migrate        # installe le plan comptable, les journaux et les taux de TVA
python manage.py init_accounts  # (ré)installe le plan par défaut, sans doublon

Les pages sont réservées aux utilisateurs ayant les permissions accounting.* (view_transaction, add_transaction, change_fiscalperiod…).

API

from accounting_fr import api

customer = api.Party("C042", "Dupont SARL")
api.post_sale("invoice:F-001", day, "F-001", "Facture F-001", customer,
              [api.SaleLine(Decimal("120.00"), Decimal("0.20")),
               api.SaleLine(Decimal("6.00"), Decimal("0.20"), kind="shipping")],
              prices_include_tax=True, document=("invoice", "F-001"))
api.post_payment("invoice:F-001:payment", day, "VIR-1", "Règlement F-001",
                 Decimal("126.00"), "transfer", customer, document=("invoice", "F-001"))
api.post_credit_note("invoice:F-001:refund", "invoice:F-001", day, "AV-1", "Avoir F-001")
api.post_refund("invoice:F-001:refund_payment", day, "AV-1", "Remboursement", Decimal("126.00"), "transfer", customer)
api.post_fee("invoice:F-001:fee", day, "ch_123", "Frais Stripe F-001", Decimal("2.14"), "stripe")   # 627 / 467
api.post_transfer("stripe:payout:po_1", day, "po_1", "Virement Stripe", Decimal("123.86"), "stripe")  # ST 580/467, BQ 512/580

api.is_posted("invoice:F-001")          # True
api.entries_for("invoice", "F-001")     # écritures liées à la pièce
  • Chaque appel porte une clé unique : le rejouer ne crée jamais de doublon.
  • kind d'une ligne : goods et services (compte de ventes paramétré, 707 par défaut) ou shipping (7085).
  • Le journal d'encaissement dépend du moyen (method) : table Journaux des moyens de paiement, à défaut le journal de la banque ; le compte est le compte de trésorerie du journal.
  • Une erreur de paramétrage (taux de TVA sans compte, exercice clôturé…) lève api.AccountingError.

Pour les écritures libres : accounting_fr.posting.post_entry(journal_code, day, description, lines, ...). posting.with_treasury_counterpart(journal, lines) complète une saisie dans un journal de banque par sa contrepartie sur le compte du journal.

Intégration au projet hôte

Tout est facultatif ; sans réglage, l'application fonctionne seule avec son propre gabarit.

ACCOUNTING = {
    "BASE_TEMPLATE": "monprojet/base.html",               # doit définir un bloc « content »
    "DOCUMENT_URL": "monprojet.accounting.document_url",  # f(type, id) -> URL de la pièce ou None
    "COMPANY": "monprojet.accounting.company",            # f() -> {"name": ..., "siren": ...}
    "DASHBOARD_PANELS": ["monprojet.accounting.panels"],  # f(request) -> [{"label", "value", "url", "alert"}]
}

La raison sociale et le SIREN saisis dans les paramètres comptables priment sur COMPANY.

Journaux

Édition de chaque journal et du livre-journal (/journaux/<code>/, /journaux/livre-journal/), journal centralisateur (/journaux/), création de journaux.

Chaque journal de banque a un compte de trésorerie (Journal.account) : BQ 512000, ST (Stripe) 467100, PP (PayPal) 467200, CA (caisse) 530000 par défaut. Ce compte est la contrepartie de toutes les écritures du journal et ne se mouvemente que dans ce journal (à-nouveaux et contre-passations exceptés) ; un virement entre deux trésoreries passe par le compte de virements internes (580). PaymentAccount.journal dirige les encaissements, frais et virements d'un moyen de paiement vers son journal. Un journal mixte hérité d'une version précédente est signalé au tableau de bord.

TVA et bilan

/tva/ : récapitulatif de la période (bases et TVA collectée par taux, TVA déductible) et liquidation : vat.settle(début, fin) passe et valide, au dernier jour de la période, l'écriture de déclaration (journal OD, type vat) qui solde les 4457 et 4456 (écritures validées jusqu'à cette date), impute le crédit de TVA reporté (44567) et porte le solde en TVA à décaisser (44551) ou en nouveau crédit à reporter. Elle est refusée s'il reste des brouillons touchant la TVA ou si une période postérieure est déjà liquidée ; vat.preview montre ce qu'elle passerait. Le paiement (44551 / 512) se saisit dans le journal de banque. Comptes : paramètres comptables.

/bilan/?as_of= (reports.balance_sheet) : actif et passif par rubrique simplifiée du PCG ; comptes de tiers et de trésorerie selon le sens de leur solde, amortissements en déduction, résultat de l'exercice en capitaux propres ; depuis les à-nouveaux de l'exercice s'ils existent, sinon depuis l'origine (résultats antérieurs non reportés à part). Export CSV. Document de pilotage, pas les comptes annuels.

TVA : encaissements, autoliquidation, CA3

  • Prestations de services : sauf option pour les débits (AccountingSettings.vat_on_debits), leur TVA reste en attente (445800) jusqu'au paiement ; chaque encaissement (post_payment) en fait passer la part correspondante en TVA collectée, un remboursement l'inverse. Les lignes de TVA portent leur base HT (vat_base).
  • Autoliquidation : post_purchase(..., reverse_charge="eu_goods" | "eu_services" | "foreign"), facture hors taxe, TVA au taux de chaque ligne due en 445200 et déductible en 445662 ; TVA sur immobilisations en 445620.
  • CA3 : reports.ca3(début, fin) et la page TVA donnent les lignes 01, 03, 2A, 3B, 05, la TVA brute par taux, 16, 17, 19, 20, 22, 23 et 25 ou 28 (CSV). Aide à la déclaration, à contrôler avant télédéclaration.

Devises et analytique

  • Une ligne peut porter un montant d'origine en devise (Line(currency="USD", currency_amount=...), currency=("USD", montant) dans l'API) : la comptabilité reste en euros, le FEC renseigne Montantdevise / Idevise. Au lettrage, l'écart de change se solde en 666 / 766 (reconciliation.write_off(..., exchange=True)).
  • Sections analytiques (AnalyticSection) sur les lignes de charges et de produits : à la saisie, par l'API (SaleLine(analytic="WEB"), PurchaseLine(analytic=...)) ou après validation depuis l'écriture (hors empreinte). /analytique/ : produits, charges et résultat par section.

Comptes annuels

/comptes-annuels/ (annual.annual_accounts) : bilan détaillé (brut, amortissements et dépréciations, net) et compte de résultat (exploitation, financier, exceptionnel, impôt) selon la présentation du PCG, avec l'exercice précédent ; CSV. Document de travail : la liasse fiscale et sa transmission EDI-TDFC restent du ressort de l'expert-comptable.

Inaltérabilité : empreinte chaînée

À sa validation, chaque écriture reçoit un rang (seal_index) et une empreinte SHA-256 (seal) de son contenu (numéro, journal, dates, pièce, libellé, montant, lignes) et de l'empreinte précédente (accounting_fr.seal). Une écriture validée modifiée, supprimée ou insérée après coup, même directement en base, casse la chaîne. La clôture d'un exercice enregistre le dernier maillon comme sceau de l'exercice (FiscalPeriod.closing_seal, affiché et journalisé) : conservé hors du logiciel, il prouve que rien n'a été réécrit, même par quelqu'un qui recalculerait toute la chaîne. Lettrage, pointage bancaire et lien de contre-passation ne sont pas scellés.

python manage.py verifier_integrite   # code de sortie 1 en cas d'altération ; aussi page /integrite/
python manage.py ancrer_sceau         # sceau du jour par e-mail (destinataires des sceaux) et dans SEAL_ARCHIVE_DIR

Le sceau part aussi à chaque clôture. Conservé hors du logiciel, il se contrôle sur la page Intégrité (maillon et empreinte) ; la vérification compare la chaîne à chaque envoi enregistré.

La migration scelle les écritures déjà validées, dans l'ordre de validation.

Immobilisations

/immobilisations/ : registre (valeur d'origine, mise en service, durée, comptes), plan d'amortissement linéaire prorata temporis en jours, sur une année de 360 jours (assets.schedule), et écarts entre le registre et les comptes de la classe 2 (assets.register_gaps).

from accounting_fr import assets

assets.post_depreciations(exercice)        # dotations au dernier jour : 6811 / 28, ce qui reste dû (rattrapage compris)
assets.dispose(immo, date, prix=None)      # dotation complémentaire, puis sortie : 28 + 675 / 2 ; prix en 462 / 775

Comptes d'amortissement et de dotation déduits du compte d'immobilisation (218300 → 281830, 6811x), modifiables. L'acquisition se comptabilise par la facture du fournisseur. Amortissement linéaire ou dégressif fiscal (coefficients 1,25 / 1,75 / 2,25, bascule en linéaire), dépréciations (assets.impair, 6816 / 29, reprises en 7816), TVA sur le prix de cession. Non traités : amortissement dérogatoire, révision du plan après dépréciation, régularisations de TVA.

Lettrage

Comptes de tiers (préfixes ACCOUNTING["RECONCILABLE_PREFIXES"], 40 et 41 par défaut), par compte auxiliaire : /lettrage/ (soldes par tiers), /lettrage/<compte>/ (lettrage manuel), /lettrage/balance-agee/.

from accounting_fr import reconciliation

reconciliation.auto_reconcile()               # même pièce, même référence, montant unique, tiers soldé
code = reconciliation.reconcile([id1, id2])   # lignes équilibrées d'un même tiers -> "A", "B"… "AA"
reconciliation.write_off([id1, id2])          # solde un écart ≤ 5 € en OD (658 / 758), puis lettre
reconciliation.unreconcile(account, "A")
reconciliation.aged_balance(account, as_of)   # 0–30, 31–60, 61–90, plus de 90 jours
python manage.py lettrage_auto   # à planifier (par exemple chaque heure)

Seules les lignes validées des exercices ouverts se lettrent ; le code et la date de lettrage alimentent EcritureLet et DateLet du FEC. Permission : accounting.reconcile_entries (solder un écart demande aussi validate_transaction). Dans la saisie manuelle, la colonne « Tiers » renseigne le compte auxiliaire d'une ligne.

Rapprochement bancaire

Par journal de banque : /banque/ (journaux, import, relevés), /banque/<journal>/ (pointage), /banque/<journal>/etat/ (état de rapprochement). Les fonctions travaillent sur le compte de trésorerie du journal (journal.account, et bank.journal_of(compte) en sens inverse).

from accounting_fr import bank

result = bank.import_statement(account, contenu, "releve.ofx")  # CSV, OFX, CAMT.053, CFONB 120
bank.auto_match(account)                     # même montant à 7 jours près, sans ambiguïté
bank.match(account, [ligne_releve], [ligne_ecriture, ...])       # totaux égaux
bank.create_entry(ligne_releve, compte_627)  # écriture validée au journal de la banque, pointée
bank.mark_prior(account, date)               # écritures antérieures au premier relevé
bank.state(account, date)                    # solde comptable, en-cours, solde du relevé, écart
python manage.py rapprochement_auto   # à planifier avec lettrage_auto

Un CSV aux colonnes inconnues demande la correspondance (date, libellé, montant ou débit / crédit). Une opération déjà importée est ignorée (identifiant de la banque, sinon date, montant et libellé). Permission : accounting.reconcile_bank (passer une écriture depuis le relevé demande aussi add_transaction et validate_transaction).

Contrôle du FEC

python manage.py check_fec 123456789FEC20261231.txt   # n'importe quel FEC
python manage.py check_fec --year 2026 --output fec/  # FEC de l'exercice, généré puis contrôlé

Règles de structure de l'article A47 A-1 du LPF (zones, formats, couples de zones, équilibre, numérotation continue et chronologique, exercice, nom de fichier) ; aussi depuis la page des exports. accounting_fr.fec_check.check_fec(contenu, nom) renvoie erreurs, avertissements et statistiques.

Tests

python manage.py test accounting

Licence

AGPL-3.0-or-later : voir LICENSE. Une licence commerciale (sans l'obligation de publier les modifications) peut être accordée par l'auteur : ouvrez une issue.

Metadata

Release files for django-accounting-fr 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-accounting-fr 0.3.0
File Size Uploaded
django_accounting_fr-0.3.0.tar.gz 169.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-accounting-fr 0.3.0
File Interpreter ABI Platform
django_accounting_fr-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 383.9 kB

Release files / django_accounting_fr-0.3.0.tar.gz

Download URL django_accounting_fr-0.3.0.tar.gz
Size 169.2 kB
Tags Source
SHA-256 checksum
How to use checksums
571c051966021bc5c3a6c265c32497bddee94af9584c7fa1f9b227408de478d1
BLAKE2b-256 checksum
How to use checksums
313e8d5377041d826373c82b41d2f68492ae1453ec7494b663777cf1b5d1c92d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / django_accounting_fr-0.3.0-py3-none-any.whl

Download URL django_accounting_fr-0.3.0-py3-none-any.whl
Size 214.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
61ce88d7fd0d2a07f6783d8a3505b63111d0fb90f391c87e7ba1338447f3cd82
BLAKE2b-256 checksum
How to use checksums
b0e57ab3b99a419775139ceb2b6399a452fdd605e21408afaa9e8589d04ef5be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page