Перейти к основному содержимому

Амортизация

Узнайте, как эффективно управлять амортизацией в 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

Платеж зачисляет на счет checking 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/ru/docs/Tips/amortize