Naar hoofdinhoud springen

Amortisatie

Leer hoe u amortisatie effectief beheert in Beancount, zodat u kosten over de tijd kunt spreiden voor betere financiële duidelijkheid en beheer.

Registreer vooruitbetaalde kosten als activa en geef vervolgens elke maand het aandeel vrij als kosten met gewone Beancount-transacties. Het onderstaande script genereert volledige, reproduceerbare boekhoudingen voor verzekeringen, software, een retainer en afschrijving van apparatuur. Het vereist Python 3 en geen externe bibliotheken.

Een autoverzekeringspolis van zes maanden kost bijvoorbeeld €600 vooraf. Zes maandelijkse vrijgaven van €100 scheiden de contante betaling van de kostenherkenning en helpen u effectief te budgetteren.

Wat is amortisatie?

Amortisatie spreidt de kosten van een immaterieel actief of een vooruitbetaald item over de perioden die er baat bij hebben. Deze voorbeelden gebruiken een eenvoudige maandelijkse conventie voor managementrapportage. Ze bepalen geen fiscale aftrek of een wettelijke afschrijvingsmethode.

De Beancount-oplossing: fava.plugins.amortize_over

Compatibiliteit gecontroleerd op 2026-09-07: fava.plugins.amortize_over ontbreekt in stock Fava 1.30.16's plugin-map. Het toevoegen van de plugin-richtlijn aan die stock-installatie veroorzaakt een importfout. De draagbare voorbeelden hier zijn getest met Beancount 3.2.3, beanquery 0.2.0 en Fava 1.30.16.

De aangepaste broncode van Beancount.io bevat wel een amortize_over-implementatie. Deze verwacht een afzonderlijke betaling en een plannings-transactie met exact twee boekingen en amortize_months-metadata. De maandelijkse datums volgen de oorspronkelijke dag van het schema en toekomstige kopieën worden weggelaten tijdens het laden. De afrondingsregel verdeelt centen over de resterende perioden. Dit bronbewijs bepaalt niet welke versie een gehoste implementatie momenteel draait. De expliciete schema's hieronder hebben hun eigen vermelde datums en afrondingsregel voor de laatste periode.

Stap 1: Activeer de plugin

Er is geen plugin om te activeren voor deze workflow. Sla het Python-blok in stap 3 op als amortize.py. Installeer uv om de validatie- en query-commando's te draaien met de hier gebruikte versies. Fava is alleen nodig als u de webrapporten wilt.

Het script schrijft gewone transacties naar de standaarduitvoer. Leid die uitvoer om naar een nieuw voorbeeldbestand, inspecteer het en valideer het voordat u items in uw boeken opneemt. Opnieuw draaien met > vervangt dat gegenereerde voorbeeldbestand; toevoegen met >> zou transacties dupliceren.

Stap 2: structureer uw rekeningen

Elk gegenereerd bestand is een zelfstandig voorbeeldboek. Het verzekeringsvoorbeeld opent deze rekeningen en levert een illustratief saldo van €600 op de bank voordat de premie wordt betaald:

RekeningDoel
Assets:Bank:CheckingContant geld dat voor de betaling wordt gebruikt
Assets:Prepaid:InsurancePremie die wacht op kostenherkenning
Expenses:Insurance:AutoMaandelijkse verzekeringskosten
Equity:Opening-BalancesTegenrekening van het startkapitaal van het voorbeeld

Wanneer u de gegenereerde transacties aanpast aan een bestaande boekhouding, gebruik dan uw werkelijke rekeningopeningen en banksaldo. Voeg het openingsgeld van het voorbeeld niet toe aan een al gefinancierde rekening en registreer een aankoop niet opnieuw als deze al in uw boeken staat.

Stap 3: Registreer de geamortiseerde transactie

Sla dit volledige programma op als amortize.py. Elk scenario specificeert de betalingsdatum, het aantal maandelijkse vrijgaven, het aankoopactief, de kostenrekening en de rekening die door de vrijgaven wordt gecrediteerd. De eerste vrijgave is op de betalingsdatum; latere vrijgaven vallen op dezelfde dag van volgende maanden, indien nodig afgeklamd op het einde van de maand.

import argparse
import calendar
from datetime import date
from decimal import Decimal, ROUND_HALF_EVEN
 
# amount, months, payment date, purchase asset, expense, release credit account
SCENARIOS = {
    "insurance": (
        "600.00", 6, "2024-06-01", "Assets:Prepaid:Insurance",
        "Expenses:Insurance:Auto", "Assets:Prepaid:Insurance",
    ),
    "software": (
        "1200.00", 12, "2024-01-15", "Assets:Prepaid:Software",
        "Expenses:Software:Adobe", "Assets:Prepaid:Software",
    ),
    "retainer": (
        "4500.00", 3, "2024-01-05", "Assets:Prepaid:Professional",
        "Expenses:Professional:Legal", "Assets:Prepaid:Professional",
    ),
    "equipment": (
        "3000.00", 36, "2024-01-20", "Assets:Equipment:Computers:Cost",
        "Expenses:Depreciation:Computers", "Assets:Equipment:Computers:AccumDep",
    ),
}
 
parser = argparse.ArgumentParser()
parser.add_argument("scenario", choices=SCENARIOS)
args = parser.parse_args()
amount, months, paid, asset, expense, credit = SCENARIOS[args.scenario]
total = Decimal(amount)
start = date.fromisoformat(paid)
monthly = (total / months).quantize(Decimal("0.01"), rounding=ROUND_HALF_EVEN)
bank = "Assets:Bank:Checking"
equity = "Equity:Opening-Balances"
 
 
def transaction(day, narration, debit, credit_account, value):
    print(f'\n{day} * "{narration}"')
    print(f"  {debit}  {value:.2f} USD")
    print(f"  {credit_account}  {-value:.2f} USD")
 
 
print('option "operating_currency" "USD"')
for account in sorted({bank, equity, asset, expense, credit}):
    print(f"2024-01-01 open {account} USD")
transaction("2024-01-01", "Example opening cash", bank, equity, total)
transaction(paid, f"Pay {args.scenario}", asset, bank, total)
 
for index in range(months):
    year, month_index = divmod(start.year * 12 + start.month - 1 + index, 12)
    month = month_index + 1
    day = min(start.day, calendar.monthrange(year, month)[1])
    release_date = date(year, month, day)
    # Put the entire rounding remainder into the final release exactly once.
    release = monthly if index < months - 1 else total - monthly * (months - 1)
    transaction(release_date, f"{args.scenario} release {index + 1}/{months}",
                expense, credit, release)

Voer dit commandoblok uit vanuit de map die amortize.py bevat:

python3 amortize.py insurance > insurance.beancount
uvx --from beancount-io==0.1.0 bea --file insurance.beancount check

De betaling crediteert 'checking' met 600.00 USD en debiteert vooruitbetaalde verzekering met hetzelfde bedrag. Elke vrijgave debiteert kosten en crediteert vooruitbetaalde verzekering met 100.00 USD. Er zijn zes vrijgaven, op 1 juni, 1 juli, 1 augustus, 1 september, 1 oktober en 1 november 2024. Het vooruitbetaalde saldo is 500.00 USD na de vrijgave van juni, 400.00 USD na die van juli en nul na die van november.

Praktische voorbeelden

Jaarlijkse softwarelicentie

Gebruik hetzelfde opgeslagen script om een apart zelfstandig softwarevoorbeeld te genereren:

python3 amortize.py software > software.beancount
uvx --from beancount-io==0.1.0 bea --file software.beancount check

De licentiebetalings van €1.200 is op 15 januari 2024. Twaalf vrijgaven van 100.00 USD lopen van 15 januari tot en met 15 december 2024. Dit voorbeeld herkent één volledige maand aan elke maandstart; het proratoriseert januari niet. Na de laatste vrijgave is Assets:Prepaid:Software nul en bedraagt Expenses:Software:Adobe in totaal 1200.00 USD.

Retainer voor professionele diensten

Dit aparte voorbeeld behandelt de betaling van €4.500 op 5 januari als een vooruitbetaalde vergoeding die gelijkmatig wordt verbruikt in januari, februari en maart:

python3 amortize.py retainer > retainer.beancount
uvx --from beancount-io==0.1.0 bea --file retainer.beancount check

Drie vrijgaven van 1500.00 USD, gedateerd 5 januari, 5 februari en 5 maart 2024, laten Assets:Prepaid:Professional op nul en Expenses:Professional:Legal op 4500.00 USD. Vervang deze veronderstelling door het werkelijke dienstschema voor een retainer die wordt verdiend naarmate diensten worden geleverd.

Afschrijving van apparatuur (vaste activa)

Afschrijving van vaste activa gebruikt een contra-actiefrekening om de aankoopkosten te behouden. Dit voorbeeld gaat uit van een gebruiksduur van drie jaar, een restwaarde van nul en volledige maandelijkse herkenning vanaf 20 januari 2024:

python3 amortize.py equipment > equipment.beancount
uvx --from beancount-io==0.1.0 bea --file equipment.beancount check

De aankoop debiteert Assets:Equipment:Computers:Cost eenmalig met 3000.00 USD. De 36 vrijgaven debiteren Expenses:Depreciation:Computers en crediteren Assets:Equipment:Computers:AccumDep. Vrijgaven 1–35 zijn 83.33 USD; vrijgave 36 op 20 december 2026 is 83.45 USD. Dus 35 × 83.33 + 83.45 = 3000.00. Als u voor alle 36 83.33 USD gebruikt, blijft er 0.12 USD niet afgeschreven over.

Bij voltooiing blijft de kostprijs 3000.00 USD, is de geaccumuleerde afschrijving -3000.00 USD en is de netto boekwaarde nul. De contra-actiefrekening zelf keert niet terug naar nul zolang de apparatuur nog wordt geregistreerd.

Rapportage en verificatie

1. Bewaak vooruitbetaalde saldi met asserts

Beancount controleert een saldo aan het begin van de datum, vóór de transacties van die dag. Voeg dit contextuele assert-blok toe aan het gegenereerde insurance.beancount en voer het bea check-commando opnieuw uit:

2024-06-02 balance Assets:Prepaid:Insurance 500.00 USD
2024-07-02 balance Assets:Prepaid:Insurance 400.00 USD
2024-07-02 balance Expenses:Insurance:Auto 200.00 USD
2024-11-02 balance Assets:Prepaid:Insurance 0.00 USD
2024-11-02 balance Expenses:Insurance:Auto 600.00 USD

2 juli volgt op twee vrijgaven, 1 juni en 1 juli. Een assert van 500.00 USD op 2 juli is onjuist. Deze asserts vereisen het gegenereerde verzekeringsboek; ze zijn geen zelfstandige transacties.

2. Geavanceerde verificatie met bea query

Met het gegenereerde verzekeringsbestand retourneert dit uitvoerbare commando cumulatieve saldi t/m 1 juli, met een exclusieve afsluitdatum van 2 juli:

uvx --from beancount-io==0.1.0 bea --file insurance.beancount query "SELECT account, sum(position) WHERE date < 2024-07-02 AND account ~ '^(Assets:Prepaid:Insurance|Expenses:Insurance:Auto)$' GROUP BY account ORDER BY account"

Verwacht Assets:Prepaid:Insurance op 400.00 USD en Expenses:Insurance:Auto op 200.00 USD. Sorteren op datum in plaats daarvan zou de beweging per dag tonen in plaats van een cumulatief saldo.

Gebruik dit om een gegenereerd bestand te bekijken in de geteste lokale Fava-versie:

uv run --no-project --with beancount==3.2.3 --with beanquery==0.2.0 --with fava==1.30.16 fava insurance.beancount

Open de lokale URL die Fava afdrukt. Zie de Fava-optiesreferentie voor configuratie. Selecteer de rapportageperiode expliciet: de generator levert het volledige schema, inclusief toekomstige datums, dus een onbeperkt totaal omvat toekomstige vrijgaven. Voor afzonderlijke planningsbestanden, zie de forecast-scenarioworkflow.

Beperkingen en laatste tips

  • Datums zijn expliciet: het wijzigen van een aankoopdatum stelt de eerste vrijgave niet stilzwijgend uit. In dit script is de eerste vrijgave gelijk aan de betalingsdatum; pas de start apart aan als de dienst later begint.
  • Afronding gebeurt één keer: het script rondt het reguliere maandbedrag af op centen en plaatst het restant in de laatste vrijgave. Bewaar het volledige gegenereerde schema om die aanpassing te behouden.
  • Gewone boekingen blijven bestaan: deze vrijgaven worden opgeslagen in het gegenereerde bestand. Bekijk ze en registreer ze één keer. Schakel niet ook automatische amortisatie in voor dezelfde kosten, anders worden de kosten dubbel herkend.
  • Kies het boekhoudschema: dit zijn beheervoorbeelden, geen rechtsgebiedspecifieke belastingregels. Voor onregelmatige voordelen of dagelijkse proratering berekent en registreert u de werkelijke bedragen en datums.

Bron: https://beancount.io/nl/docs/Tips/amortize