Перейти до основного вмісту

Амортизація

Дізнайтеся, як ефективно керувати амортизацією в Beancount, розподіляючи витрати в часі для кращої фінансової ясності та управління.

Записуйте попередньо оплачені витрати як активи, а потім списуйте щомісячну частку у витрати за допомогою звичайних транзакцій Beancount. Наведений нижче скрипт створює повні, відтворювані книги для страхування, програмного забезпечення, ретейнера та амортизації обладнання. Для його роботи потрібен Python 3 і жодних сторонніх бібліотек.

Наприклад, шестимісячний поліс автострахування коштує $600 авансом. Шість щомісячних списань по $100 розділяють грошовий платіж та визнання витрат, що допомагає ефективно планувати бюджет.

Що таке амортизація?

Амортизація розподіляє вартість нематеріального активу або попередньо оплаченого об'єкта на періоди, протягом яких він приносить вигоду. Ці приклади використовують просту щомісячну умовність для управлінської звітності. Вони не визначають податкове вирахування чи нормативний метод амортизації.

Рішення Beancount: fava.plugins.amortize_over

Перевірка сумісності 2026-09-07: fava.plugins.amortize_over відсутній у каталозі плагінів стандартної Fava 1.30.16. Додавання директиви plugin для нього до стандартної інсталяції призводить до помилки імпорту. Наведені тут портативні приклади були протестовані з Beancount 3.2.3, beanquery 0.2.0 та Fava 1.30.16.

Власний вихідний код Beancount.io містить реалізацію amortize_over. Вона очікує окремий платіж та транзакцію-розклад із рівно двома записами та метаданими amortize_months. Її щомісячні дати слідують за оригінальним днем розкладу, і вона опускає майбутні копії під час завантаження. Її правило округлення розподіляє центи на решту періодів. Ці докази з вихідного коду не встановлюють, яку версію наразі запускає розміщене розгортання. Явні розклади нижче мають власні зазначені дати та правило округлення для останнього періоду.

Крок 1: Увімкнення плагіна

Для цього робочого процесу не потрібен жоден плагін. Збережіть блок Python з кроку 3 як amortize.py. Встановіть uv, щоб запускати команди перевірки та запитів із використаними тут версіями. Fava потрібна лише якщо ви бажаєте веб-звіти.

Скрипт записує звичайні транзакції у стандартний вивід. Перенаправте цей вивід у новий файл-приклад, перегляньте його та перевірте, перш ніж вносити записи у свої книги. Повторний запуск із > замінює згенерований файл-приклад; додавання із >> призведе до дублювання транзакцій.

Крок 2: Структурування рахунків

Кожен згенерований файл є самостійним прикладом книги. Приклад страхування відкриває ці рахунки та надає ілюстративний залишок $600 на банківському рахунку перед сплатою премії:

РахунокПризначення
Assets:Bank:CheckingГроші, використані для платежу
Assets:Prepaid:InsuranceПремія, що очікує на визнання витрат
Expenses:Insurance:AutoЩомісячні витрати на страхування
Equity:Opening-BalancesКонтррахунок початкових грошей прикладу

При адаптації згенерованих транзакцій до наявної книги використовуйте свої фактичні відкриття рахунків та банківський залишок. Не додавайте початкові гроші прикладу до вже профінансованого рахунку та не записуйте покупку повторно, якщо вона вже є у ваших книгах.

Крок 3: Запис амортизованої транзакції

Збережіть цю повну програму як amortize.py. Кожен сценарій визначає дату платежу, кількість щомісячних списань, рахунок активу, рахунок витрат та рахунок, який кредитується списаннями. Перше списання відбувається у дату платежу; наступні списання припадають на той самий день наступних місяців, за потреби обмежуючись кінцем місяця.

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)

Запустіть цей блок команд із каталогу, що містить amortize.py:

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

Платіж кредитує поточний рахунок на 600.00 USD і дебетує попередньо оплачене страхування на ту саму суму. Кожне списання дебетує витрати та кредитує попередньо оплачене страхування на 100.00 USD. Списань шість, від 1 червня, 1 липня, 1 серпня, 1 вересня, 1 жовтня та 1 листопада 2024 року. Залишок попередньо оплаченого страхування становить 500.00 USD після списання за червень, 400.00 USD після липневого та нуль після листопадового.

Практичні приклади

Річна ліцензія на програмне забезпечення

Використайте той самий збережений скрипт для створення окремого самостійного прикладу програмного забезпечення:

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

Платіж за ліцензію у розмірі $1,200 здійснено 15 січня 2024 року. Дванадцять списань по 100.00 USD тривають з 15 січня по 15 грудня 2024 року. Цей приклад визнає один повний місяць на початку кожного місяця; він не пропорційно розподіляє січень. Після останнього списання Assets:Prepaid:Software дорівнює нулю, а Expenses:Software:Adobe загалом становить 1200.00 USD.

Ретейнер на професійні послуги

Цей окремий приклад розглядає платіж у розмірі $4,500 від 5 січня як попередньо оплачений гонорар, що рівномірно споживається протягом січня, лютого та березня:

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

Три списання по 1500.00 USD, датовані 5 січня, 5 лютого та 5 березня 2024 року, залишають Assets:Prepaid:Professional на нулі та Expenses:Professional:Legal на 4500.00 USD. Для ретейнера, що заробляється по мірі надання послуг, замініть це припущення фактичним графіком послуг.

Амортизація обладнання (основні засоби)

Амортизація основних засобів використовує контрарний рахунок для збереження вартості придбання. Цей приклад передбачає трирічний строк корисного використання, нульову ліквідаційну вартість та повне щомісячне визнання, починаючи з 20 січня 2024 року:

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

Покупка дебетує Assets:Equipment:Computers:Cost на 3000.00 USD один раз. 36 списань дебетують Expenses:Depreciation:Computers та кредитують Assets:Equipment:Computers:AccumDep. Списання 1–35 становлять 83.33 USD; списання 36 від 20 грудня 2026 року становить 83.45 USD. Отже, 35 × 83.33 + 83.45 = 3000.00. Використання 83.33 USD для всіх 36 залишило б 0.12 USD неамортизованими.

Після завершення вартість залишається 3000.00 USD, накопичена амортизація становить -3000.00 USD, а їхня чиста балансова вартість дорівнює нулю. Контрарний рахунок сам по собі не повертається до нуля, поки обладнання ще обліковується.

Звітність та перевірка

1. Моніторинг попередньо оплачених залишків за допомогою тверджень

Beancount перевіряє залишок на початок дати, до транзакцій цього дня. Додайте цей контекстний блок тверджень до згенерованого insurance.beancount, а потім повторно запустіть його команду bea check:

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 липня йде після двох списань, 1 червня та 1 липня. Твердження 500.00 USD на 2 липня є неправильним. Ці твердження потребують згенерованої книги страхування; вони не є самостійними транзакціями.

2. Розширена перевірка за допомогою bea query

Зі згенерованим файлом страхування ця виконувана команда повертає кумулятивні залишки через 1 липня, використовуючи виключний кінець 2 липня:

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"

Очікуйте Assets:Prepaid:Insurance на 400.00 USD та Expenses:Insurance:Auto на 200.00 USD. Групування за датою замість цього показувало б щоденний рух, а не кумулятивний залишок.

Щоб переглянути будь-який згенерований файл у тестованій локальній версії Fava, використовуйте:

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

Відкрийте локальну URL-адресу, яку надрукує Fava. Див. довідник параметрів Fava для налаштування. Виберіть період звітності явно: генератор створює весь розклад, включаючи майбутні дати, тому необмежений загальний підсумок включає майбутні списання. Для окремих файлів планування див. робочий процес прогнозних сценаріїв.

Обмеження та заключні поради

  • Даты є явними: Зміна дати покупки не призводить до мовчазного відтермінування першого списання. У цьому скрипті перше списання дорівнює даті платежу; адаптуйте початок окремо, якщо послуга починається пізніше.
  • Округлення виконується один раз: Скрипт округлює регулярну щомісячну суму до центів, а потім розміщує залишок в останньому списанні. Зберігайте повний згенерований розклад, щоб зберегти це коригування.
  • Звичайні записи зберігаються: Ці списання зберігаються у згенерованому файлі. Перегляньте та запишіть їх один раз. Не вмикайте також автоматичну амортизацію для тієї самої вартості, інакше витрати визнаватимуться двічі.
  • Оберіть бухгалтерський розклад: Це управлінські приклади, а не податкові правила конкретної юрисдикції. Для нерівномірних вигод або щоденної пропорційності розрахуйте та запишіть фактичні суми та дати.

Джерело: https://beancount.io/uk/docs/Tips/amortize