= Informatiser une comptabilité avec confiance :author: git://git.autogeree.net/tool/hledger :copyright: © 2014 (CC) BY Julien Moutinho <julm+hledger@autogeree.net> :icons: :iconsdir: ./icons :numbered: :toc: :slidebackground: hledgersplash :slidefontsizeadjust: -3 :incremental: :revremark: //:max-width: 45em :scriptsdir: $PWD/javascripts ifdef::backend-slidy2[:data-uri:] ifdef::backend-slidy2[:slidebackground!:] // a2x: --xsltproc-opts "--stringparam ulink.show 1" // a2x: --xsltproc-opts "--stringparam ulink.footnotes 1" // :source-highlighter: vim == Le ++.ledger++ : un format de __Grand Livre__ ouvert.. et simple [source,hledger] ---- 2014/05/01 Stand manif Don:Anonyme -42 Caisse:Grève 42 2014/05/08 Propagande Caisse:Grève -7 Achat:Impression:Tracts 7 ; Répéter ad nauseam ---- ifdef::backend-slidy2[>>>] === Les plus [horizontal] Transparent:: Visibilité de _toutes_ les informations. Pérenne:: Compréhensible sans peine. Modifiable:: Pas d’interface protectrice. Accès:: Pas de changement d’interface non-consenti. Versionnable:: Suivi et fusion simples des modifications. Écrit:: Langage pour s’exprimer clairement, par exemple pour discuter dans un courriel. Hors-ligne:: Pas besoin de réseau. Interopérable:: Pas spécifique à un éditeur logiciel particulier (sauf fonctionnalité expérimentale). * http://ledger-cli.org/[] * http://hledger.org/[] * http://furius.ca/beancount/[] * https://massysett.github.io/penny/[] * https://github.com/hrj/abandon/[] === Les moins [horizontal] Modifiable:: Mais pas moins que les autres logiciels et à nuancer si couplé à un gestionnaires de versions, et/ou avec signature cryptographiques. + [source,sh] ---- % git tag --sign v2011 -m "Clôture de la comptabilité 2011" % git tag --verify v2011 ---- + [source,sh] ---- % gpg --sign $fichier.hledger % gpg --verify-files $fichier.hledger.gpg ---- Textuel:: Préférable de bien savoir utiliser un éditeur de texte structuré. Peu contraint:: + [source,hledger] ---- 2102/03/21 Remise chq (1101804) 5.Finance:1.Etablissement:1.Valeur:2.Chèque_à_encaisser -145,00 5.Finance:1.Etablissement:2.Banque:001.Courant 145,00 ---- NOTE: KISS == ++hledger++ : un outil libre.. et convivial [source,sh] ---- % hledger balance '^6' '^7' --depth 2 -f Paris.2011.hledger 770,58€ 6.Charge 248,87€ 0.Achat 441,46€ 1.Service 55,25€ 2.Autre_service 25,00€ 5.Gestion -726,00€ 7.Produit -700,00€ 0.Vente -26,00€ 5.Autre_gestion_courante ‑------------------- 44,58€ ---- ifdef::backend-slidy2[>>>] === Les plus Utilisation:: Étude:: Modification:: Duplication:: Permises techniquement et légalement + (« logiciel libre » sous ++GNU/GPLv3++) Certification:: Programmé en http://fr.wikipedia.org/wiki/Haskell[Haskell] [horizontal] Fonctionnel pur;; Aucune mutation de données externes à une fonction (effet de bord). Typage statique;; Vérification des erreurs de type avant l’exécution du programme. Typage fort;; Aucune conversion implicite de types de données. Portable:: GNU/Linux, Apple/MacOS, Microsoft/Windows Support:: ~1 développeur à mi-temps + * Simon Michael [horizontal] Ligne de commande:: + [source,sh] ---- % hledger balance -f $fichier.hledger ---- Interface Web:: + [source,sh] ---- % hledger-web --server -f $fichier.hledger % firefox "http://localhost:5000" ---- Extensible:: + [source,sh] ---- % ghc hledger-fait-ce-que-je-veux.hs % ./hledger-fait-ce-que-je-veux -f $fichier.hledger ---- ifdef::backend-slidy2[>>>] === Les moins Ligne de commande:: + ... == Installer `hledger` * http://hledger.org/installing[] [source,sh] .Debian/jessie ---- % sudo apt-get install hledger hledger-web ---- ifdef::backend-slidy2[>>>] === Via `cabal` * http://www.haskell.org/cabal/[] [source,sh] .Debian/wheezy ---- % echo 'PATH="$HOME/.cabal/bin:$PATH"' >>~/.profile # NOTE: rajoute dans le chemins des exécutables # les exécutables installés par cabal % exit # NOTE: recharge ~/.profile % sudo apt-get install ghc cabal-install \ libncurses5-dev libtinfo-dev zlib1g-dev % cabal update % cabal install cabal # NOTE: met à jour cabal % cabal install happy # NOTE: anticipe une dépendance exécutable % cabal install hledger % cabal install alex # NOTE: anticipe une dépendance exécutable % cabal install warp-2.0.3.4 hledger-web # NOTE: aide cabal à sélectionner un warp qui fonctionne ---- [source,sh] .Mise-à-jour ---- % cabal install --reinstall hledger hledger-web ---- ifdef::backend-slidy2[>>>] ==== Version de développement [source,sh] ---- % git clone http://github.com/simonmichael/hledger.git ~/src/hledger % cd ~/src/hledger % cabal install --reinstall --force-reinstalls \ ./hledger-lib ./hledger ./hledger-web ---- == Écrire en +.ledger+ Un +.ledger+ est un fichier de texte brut respectant une syntaxe préçise qui forme une succession d’écritures comptables, ordonnées librement. ifdef::backend-slidy2[>>>] === Exemple [source,hledger] ---- ; Ceci est un exemple de livre comptable « ledger » ; NOTE: fantaisiste comptablement parlant, mais syntaxiquement correct 2014/01/01 Libellé de l’écriture ; UN_TAG:, Autre_tag:Avec_Valeur Compte:Sous-Compte -42 ; flux créditant Autre_Compte:Sous-Compte:Sous-Sous-Compte 42 ; flux débitant 2014/01/01 Deuxième écriture le même jour Vente:Âme -666 ; (tag de flux) Arnaque: Kapital 666 2014/01/02 Troisième écriture le jour suivant avec ventilation des flux Compte:Crédité:A -1 Compte:Crédité:B -2 Compte:Débité:Z 1 Compte:Débité:Y 1 Compte:Débité:X:x 1 2014/04/12 Compte:Crédité -1234,56 Compte:Débité ; 1234,56 (montant inféré) 2014/02/01 Écriture non ordonnée par date ; Ok, mais déconseillé Compte:Débité 1 Compte:Crédité -1 ; Flux non ordonné par crédit/débit ; c'est juste moins lisible... ; Répéter ad nauseam ---- === Langage [cols="a,a",options="header"] |================================== ^|Syntaxe (grammaire https://fr.wikipedia.org/wiki/Forme_de_Backus-Naur[BNF]) ^|Structure (signatures fonctionnelles) | [source,conf] ----------------------------------- livre ::= (écriture \| commentaire \| "⏎" \| "␣")* ----------------------------------- | [horizontal] :role: math **livre**:: latexmath:[$ :\>f:\textcolor{#D2691E}{\textbf{fichier}} → \lbrack\textcolor{#D2691E}{\textbf{\acute{e}criture}}\rbrack$] | [source,conf] ---- écriture ::= date "␣" "␣"* libellé commentaire "⏎" ("␣" flux "⏎")* date ::= (année "/")? mois "/" jour libellé ::= (· - (";"\|"⏎"))* ---- | [horizontal] :role: math **date**:: latexmath:[$ :\>e:\textcolor{#D2691E}{\textbf{\acute{e}criture}} → (\textcolor{#083194}{\textbf{ann\acute{e}e}}:\textcolor{#D2691E}{\textbf{ℕ}},~ \textcolor{#083194}{\textbf{mois}}:\{\textcolor{#D2691E}{\textbf{01}},...,\textcolor{#D2691E}{\textbf{12}}\},~ \textcolor{#083194}{\textbf{jour}}:\{\textcolor{#D2691E}{\textbf{01}},...,\textcolor{#D2691E}{\textbf{31}}\})$] **libellé**:: latexmath:[$ :\>e:\textcolor{#D2691E}{\textbf{\acute{e}criture}} → \textcolor{#D2691E}{\textbf{texte}}$] **commentaire**:: latexmath:[$ :\>e:\textcolor{#D2691E}{\textbf{\acute{e}criture}} → \textcolor{#D2691E}{\textbf{texte}}$] **tags**:: latexmath:[$ :\>e:\textcolor{#D2691E}{\textbf{\acute{e}criture}} → \lbrack\textcolor{#D2691E}{\textbf{tag}}\rbrack \ =\ \textbf{tags}~(\textbf{commentaire}~e)$] **flux**:: latexmath:[$ :\>e:\textcolor{#D2691E}{\textbf{\acute{e}criture}} → \lbrack\textcolor{#D2691E}{\textbf{flux}}\rbrack$] | [source,conf] ---- flux ::= compte "␣␣" "␣"* ("-" crédit \| débit) ("␣"\|"⏎")* commentaire compte ::= nom ( ":" nom )* nom ::= (· - (":"\|"⏎")) (· - (":"\|"⏎"))* crédit ::= quantité débit ::= quantité ---- | [horizontal] :role: math **compte**:: latexmath:[$ :\>f:\textcolor{#D2691E}{\textbf{flux}} → \lbrack\textcolor{#D2691E}{\textbf{nom}}\rbrack$] **montant**:: latexmath:[$ :\>f:\textcolor{#D2691E}{\textbf{flux}} → \textcolor{#D2691E}{ℚ} = \displaystyle{ \left\{\begin{array}{ll} -~(\textbf{cr\acute{e}dit}~f) & \mathit{\mbox{si défini}} \\ (\textbf{d\acute{e}bit}~f) & \mathit{\mbox{sinon}} \end{array}\right}$] **tags**:: latexmath:[$ :\>f:\textcolor{#D2691E}{\textbf{flux}} → \lbrack\textcolor{#D2691E}{\textbf{tag}}\rbrack \ =\ \textbf{tags}~(\textbf{commentaire}~f)$] | [source,conf] ---- commentaire ::= ( ";" (tag ":" valeur? \| ·)* ) ( ("⏎"\|"␣")* ";" (tag ":" valeur? \| ·)* )* ---- | [horizontal] :role: math **tags**:: latexmath:[$ :\>m:\textcolor{#D2691E}{\textbf{commentaire}} → \lbrack\textcolor{#D2691E}{\textbf{tag}}\rbrack$] **tag**:: latexmath:[$ :\>(\textcolor{#083194}{\textbf{tag}}:\textcolor{#D2691E}{\textbf{texte}},% ~\textcolor{#083194}{\textbf{valeur}}:\textcolor{#D2691E}{\textbf{\mbox{texte}}\>?})$] |================================== NOTE: RTFM @ http://hledger.org/manual/[]. === Calculs [horizontal] **compte_parent**:: latexmath:[$:\>c : \textcolor{#D2691E}{\textbf{compte}} → \textcolor{#D2691E}{\textbf{compte}}\>?$] + latexmath:[$=\>c_{\lbrack0,\cdots,|c|-2\rbrack}\ \mbox{si}\ |c| \ge 2$] **hiérarchie_de_compte**:: latexmath:[$:\>\mathbb c : \textcolor{#D2691E}{\textbf{compte}} → \lbrack\textcolor{#D2691E}{\textbf{compte}}\rbrack$] + latexmath:[$=\>\lbrack{\ c\ :\ \lbrack{\ c\ |\ c ← (\mathbf{compte\mbox{_}parent}\>{c})}\ \rbrack}\ \rbrack$] **comptes**:: latexmath:[$:\>\mathbb E : \lbrack\textcolor{#D2691E}{\textbf{\acute{e}criture}}\rbrack → \{\textcolor{#D2691E}{\textbf{compte}}\}$] + latexmath:[$\{\ (\textbf{compte}\>f)\ |\ f ← (\textbf{flux}\>e)\ |\ e ← \mathbb E\ \}$] **balance**:: latexmath:[$:\>\mathbb F : \lbrack\textcolor{#D2691E}{\textbf{flux}}\rbrack → ℚ$] + latexmath:[$=\>{(\ m\ |\ m ← m + (\textbf{montant}\>f)\ |\ f ← \mathbb F\ |\ m ← 0\ )$] + **solde_de_compte**:: latexmath:[$:\>\mathbb E : \lbrack\textcolor{#D2691E}{\textbf{\acute{e}criture}}\rbrack → c : \textcolor{#D2691E}{\textbf{compte}} → ℚ$] + latexmath:[$=\>{\textbf{balance}\>\lbrack{\ f\ |\ f ← (\textbf{flux}\>e),\ c\>≼\>(\textbf{compte}\>f)\ |\ e ← \mathbb E\ }\rbrack$] + // latexmath:[$=\>{\displaystyle{\sum_{e ← \mathbb E}}\left(\sum_{\stackrel{f ← (\textbf{flux}\>e),}{c\ ≼\ (\textbf{compte}\>f)}}(\textbf{montant}\>f})\right)$] **solde**:: latexmath:[$:\>\mathbb E : \lbrack\textcolor{#D2691E}{\textbf{\acute{e}criture}}\rbrack → \lbrack\textcolor{#D2691E}{\textbf{flux}}\rbrack$] + latexmath:[$=\>\displaystyle{\left\lbrack \begin{array}{l} (\textcolor{#083194}{\textbf{compte}}=c´, \textcolor{#083194}{\textbf{montant}}=m) \\ |\ m ← (\mathbf{\mbox{solde_de_compte}}\,\mathbb E\,c´) \\ |\ c´ ← (\mathbf{hi\acute{e}rarchie\mbox{_}de\mbox{_}compte}\,c) \\ |\ c ← (\mathbf{comptes}\,\mathbb E) \end{array}}\right\rbrack$] === Utiliser un éditeur de texte structuré (`vim`) Coloration syntaxique sur mesure:: * ++hledger.vim++ + [source,vim] .~/.vimrc ---- autocmd BufNewFile,BufRead *.hledger,*.ledger setfiletype hledger ---- Complètement automatique des comptes (``):: + * https://github.com/Shougo/neocomplete.vim[] * https://github.com/Shougo/neocomplcache.vim[] + [source,vim] .~/.vimrc ---- autocmd Filetype hledger set iskeyword+=.,38,39,40,41,44,45,58 " ---- Alignement automatique des montants:: + * https://github.com/junegunn/vim-easy-align[] + [source,vim] .~/.vimrc ---- let g:easy_align_ignore_groups = ['Comment', 'String', 'hledgerTransaction'] ---- ifdef::backend-slidy2[>>>] ==== Suivre les modifications à plusieurs et/ou à distance (`git`) TODO == Commandes `hledger` ifdef::backend-slidy2[>>>] === Calculer des soldes (`balance`) [source,sh] ---- % hledger balance -f $fichier.ledger $filtre ---- [source,sh] .Suivi des comptes ---- % hledger balance -b 2012/02/01 -e 2012/04/30 --monthly -f $fichier.ledger >/tmp/bal.flow % hledger balance -b 2012/02/01 -e 2012/04/30 --cumulative --monthly -f $fichier.ledger >/tmp/bal.cumulative % hledger balance -b 2012/02/01 -e 2012/04/30 --historical --monthly -f $fichier.ledger >/tmp/bal.historical % gvimdiff -o /tmp/bal.{cumulative,historical} ---- image::data/gvimdiff-cumulative-historical.png[] ifdef::backend-slidy2[>>>] === Filtrer des écritures (`print`) TODO ifdef::backend-slidy2[>>>] === Suivre un compte (`register`) TODO ifdef::backend-slidy2[>>>] === Observer des statistiques (`stats`, `activity`) TODO == Exercice comptable ifdef::backend-slidy2[>>>] === Plan comptable d’une association * DOC : https://wiki.cyclocoop.org/Comptabilité/Document/Plan_comptable/[] [source,hledger] ---- #include::data/Cyclofficine.Plan_comptable.hledger[] ---- === Comptabiliser en partie double Solde nul de toute écriture:: + Pour toute écriture;; Tout ce qui est _débité_ (+++++) dans ses comptes + est forcément _crédité_ (++-++) dans ses autres comptes. + * latexmath:[$\forall e : \textcolor{#D2691E}{\textbf{\acute{e}criture}}, \ \textbf{balance}\>(\textbf{flux}\>{e}) = 0$] Relation de Chasles par écritures d’engagement et de paiement:: + [source,hledger] ---- 01/01 Écriture d’engagement 7.Produit:0.Vente:1.Produit_fini:1.Vélo -80 5.Finance:1.Etablissement:1.Valeur:2.Chèque_à_encaisser 80 01/02 Écriture de paiement 5.Finance:1.Etablissement:1.Valeur:2.Chèque_à_encaisser -80 5.Finance:1.Etablissement:2.Banque:001.Courant 80 ---- + NOTE: pour des espèces, transiter par : ++5.Finance:3.Caisse:1.Siège++ ==== Soldes nuls souhaitables - Écritures des recettes + 1. latexmath:[$\sum{\mbox{ventes}} + \sum{\mbox{dons}} = \sum{\mbox{espèces entrées en caisse}} + \sum{\mbox{Chèques à encaisser}}$] + (Total des ventes + dons == Total d’espèces entrée en caisse + Chèques à encaisser (5112)) 2. Total chèques à encaisser (5112) == Total remises de chèques à la banque (512) (+/- argent non déposé en banque) 3. Solde du compte caisse (531) == Total entrées espèces en caisse - Total des sorties (remises d’espèces en banque - sorties d’achats - erreur de caisse) 4. Solde compte caisse (531) == Total entrées en caisse - Dépôt espèce en banque - Achat en espèce - Écritures de paye + TODO === Journaux (filtres) [horizontal] **Banque**:: + [source,sh] ---- hledger print -f $fichier.ledger '^5.Finance:1.Etablissement:2.Banque:' ---- **Achats**:: + [source,sh] ---- hledger print -f $fichier.ledger '^(2.Immobilisation:1.Corporelle:|6.Charge:(0.Achat|1.Service|2.Autre_service):)' ---- **Vente**:: + [source,sh] ---- hledger print -f $fichier.ledger '^7.Produit:0.Vente:' ---- **Caisse**:: + [source,sh] ---- hledger print -f $fichier.ledger '^5.Finance:3.Caisse:' ---- **Paye**:: + [source,sh] ---- hledger print -f $fichier.ledger '6.Charge:(3.Impôt:(1.|3.):|4.Personnel:)' ---- **À NouVeaux**:: + [source,sh] ---- hledger print -f $fichier.ledger tag:ANV ---- **Opération_Diverses**:: + [source,sh] ---- hledger print -f $fichier.ledger tag:OD ---- === Clôture / Ouverture (`equity`) ++hledger-equity++ calcule une balance de comptes et en fait deux écritures, respectivement : [horizontal] de clôture:: pour les solder à zéro en fin d’exercice ; d’ouverture:: pour les réinitialiser à leur solde du précédent exercice. [source,sh] ---- % hledger-equity -f $fichier.ledger $filtre ---- [source,hledger] .Solde des compte de gestion ---- % hledger-equity '^6' '^7' -f Paris.2011.hledger 2014/07/29 6.Charge:0.Achat:6.Non_stocké:8.Autre_Matière,Fourniture:1.Atelier -248,87€ 6.Charge:1.Service:3.Location:2.Immobilière -441,46€ 6.Charge:2.Autre_service:3.Communication:6.Catalogue,Imprimé -24,00€ 6.Charge:2.Autre_service:7.Service_bancaire -31,25€ 6.Charge:5.Gestion:8.Divers:6.Cotisation_(vie_statutaire) -25,00€ 7.Produit:0.Vente:6.Prest'action 700,00€ 7.Produit:5.Autre_gestion_courante:6.Cotisation 20,00€ 7.Produit:5.Autre_gestion_courante:8.Divers 6,00€ equity:closing balances 44,58€ 2014/07/29 6.Charge:0.Achat:6.Non_stocké:8.Autre_Matière,Fourniture:1.Atelier 248,87€ 6.Charge:1.Service:3.Location:2.Immobilière 441,46€ 6.Charge:2.Autre_service:3.Communication:6.Catalogue,Imprimé 24,00€ 6.Charge:2.Autre_service:7.Service_bancaire 31,25€ 6.Charge:5.Gestion:8.Divers:6.Cotisation_(vie_statutaire) 25,00€ 7.Produit:0.Vente:6.Prest'action -700,00€ 7.Produit:5.Autre_gestion_courante:6.Cotisation -20,00€ 7.Produit:5.Autre_gestion_courante:8.Divers -6,00€ equity:opening balances -44,58€ ---- == Import et export avec `hledger` * https://github.com/eval/total_recall[] * https://github.com/quentinsf/icsv2ledger[] === Feuilles de calculs des documents comptables ifdef::backend-slidy2[>>>] ==== Bilan financier TODO ifdef::backend-slidy2[>>>] ==== Comptes de résultats TODO == `hledger-web` TODO == (bonus) Scripter ++hledger++ TODO ifdef::backend-slidy2[>>>] === Installer un script ++hledger++ [source,sh] ---- % echo 'PATH="$HOME/src/hledger/extra:$PATH"' >>~/.profile % exit # NOTE: recharge ~/.profile % ghc ~/src/hledger/extra/hledger-SCRIPT.hs ---- == Communauté [horizontal] Chat:: Liste:: ifdef::backend-slidy2[] [hledgersplash,position: absolute; left: 50%; top: 10%;] &&&& image::data/hledger.splash.png[hledgersplash] &&&& endif::backend-slidy2[]