Руководство по миграции из QuickBooks в Beancount
Этап 1: Экспорт данных из QuickBooks
Миграция данных за пять лет начинается с выгрузки всех записей из QuickBooks в удобном для использования формате. QuickBooks Desktop и QuickBooks Online имеют разные опции экспорта:
1.1 QuickBooks Desktop – Варианты экспорта
IIF (Intuit Interchange Format): QuickBooks Desktop может экспортировать списки (такие как план счетов, клиенты, поставщики) в текстовые файлы формата .IIF
. В QuickBooks Desktop перейдите в Файл → Утилиты → Экспорт → Списки в IIF (File → Utilities → Export → Lists to IIF), затем выберите нужные списки (например, План счетов, Клиенты, Поставщики). В результате вы получите текстовый файл, содержащий названия счетов, их типы и данные из списков. IIF — это проприетарный, но текстовый формат, который относительно легко разобрать. Используйте его, чтобы получить ваш План счетов и списки контактов для дальнейшего использования в Beancount.
Главная книга/Журнал через CSV: Для экспорта транзакций QuickBooks Desktop не предоставляет полного экспорта в один клик, но можно использовать отчёты. Рекомендуемый метод — экспорт Главного журнала (всех транзакций) за желаемый период. В QuickBooks Desktop откройте Отчёты → Бухгалтер и налоги → Журнал (Reports → Accountant & Taxes → Journal), установите Даты с самой ранней транзакции до сегодняшнего дня и нажмите Экспорт → Excel. Сохраните результат как CSV, предварительно удалив все заголовки/подвалы отчёта и пустые столбцы. Убедитесь, что числовые данные чистые: содержат центы (например, 3.00
, а не 3
), без лишних кавычек, символов валют или двойных минусов в CSV. CSV-файл должен иметь столбцы, такие как Дата, № тр анз., Имя, Счёт, Заметка, Дебет, Кредит, Остаток (или один столбец "Сумма" в зависимости от формата отчёта).
Совет: QuickBooks Desktop 2015+ также может экспортировать транзакции через диалоговое окно Найти (Find). Используйте Правка → Найти → Расширенный поиск (Edit → Find → Advanced), установите диапазон дат на пять лет, а затем экспортируйте результаты в CSV. Предупреждение: Некоторые версии ограничивают экспорт 32 768 строками. Если у вас очень большой объём данных, экспортируйте по годам (или меньшими частями), чтобы избежать усечения, а затем объедините их. Убедитесь, что диапазоны дат не пересекаются, чтобы избежать дубликатов.
Другие форматы (QBO/QFX/QIF): QuickBooks Desktop может импортировать банковские транзакции через файлы .QBO
(Web Connect) или .QFX/.OFX
, но для экспорта из QuickBooks они обычно не используются. Если ваша цель — извлечь только банковские транзакции, они у вас уже могут быть в формате QBO/OFX от вашего банка. Однако для полного экспорта главной книги придерживайтесь IIF и CSV. QuickBooks Desktop не может напрямую экспортировать в QIF (Quicken Interchange Format) без сторонних инструментов. Если вы найдёте способ получить QIF, учтите, что некоторые инструменты для учёта (старые версии Ledger 2.x) могли читать QIF, но в нашем процессе лучше работать с CSV.
1.2 QuickBooks Online – Варианты экспорта
Встроенный экспорт в Excel/CSV: QuickBooks Online (QBO) предоставляет инструмент Экспорт данных. Перейдите в Настройки ⚙ → Инструменты → Экспорт данных (Settings ⚙ → Tools → Export Data). В диалоговом окне экспорта используйте вкладку Отчёты для выбора данных (например, Главная книга или Список транзакций) и вкладку Списки для списков (план счетов и т.д.), выберите Все даты и экспортируйте в Excel. QuickBooks Online загрузит ZIP-архив, содержащий несколько файлов Excel для выбранных отчётов и списков (например, Отчёт о прибылях и убытках, Балансовый отчёт, Главная книга, Клиенты, Поставщики, План счетов и т.д.). Затем вы можете преобразовать эти файлы Excel в CSV для обработки.
Отчёт о детализации транзакций: Если стандартный экспорт QBO не включает единый файл Главной книги, вы можете вручную создать детализированный отчёт:
- Перейдите в Отчёты и найдите Детализация транзакций по счетам (Transaction Detail by Account) или Главная книга (General Ledger) в некоторых версиях QBO.
- Установите Отчётный период на полный пятилетний диапазон.
- В опциях отчёта установите Группировать по = Нет (чтобы отобразить отдельные транзакции без промежуточных итогов).
- Настройте столбцы, чтобы включить как минимум: Дату, Тип транзакции, Номер, Имя (Получатель/Клиент), Заметка/Описание, Счёт, Дебет, Кредит (или один столбец "Сумма") и Остаток. Включите класс или местоположение, если они используются.
- Сформируйте отчёт, а затем Экспортируйте в Excel.
Это даст детализированную главную книгу всех транзакций. Сохраните её как CSV. Каждая строка будет представлять одну проводку транзакции. Позже вам нужно будет сгруппировать строки по транзакциям для конвертации.
План счетов и другие с писки: QuickBooks Online может экспортировать план счетов через Учёт → План счетов → Пакетные действия → Экспорт в Excel (Accounting → Chart of Accounts → Batch Actions → Export to Excel). Сделайте это, чтобы получить названия и типы счетов. Аналогично, экспортируйте Клиентов, Поставщиков и т.д., если хотите перенести имена для метаданных.
QuickBooks Online API (Необязательно): Для программного подхода Intuit предоставляет REST API для данных QBO. Продвинутые пользователи могут создать приложение QuickBooks Online (требуется аккаунт разработчика) и использовать API для получения данных в формате JSON. Например, вы можете запросить эндпоинт Account
для плана счетов и эндпоинты отчётов JournalEntry
или GeneralLedger
для транзакций. Существуют Python SDK, такие как python-quickbooks
, которые являются обёртками над API. Однако использование API включает в себя аутентификацию по OAuth и является излишним для одноразовой миграции, если вы не предпочитаете автоматизацию. В большинстве случаев ручной экспорт в CSV/Excel проще и менее подвержен ошибкам.
Этап 2: Трансформация и очистка данных
Когда у вас есть данные из QuickBooks в формате CSV (и/или IIF), следующий шаг — преобразовать их в текстовый формат главной книги Beancount. Это включает разбор экспортированных файлов, сопоставление счетов QuickBooks с планом счетов Beancount и форматирование транзакций в синтаксисе Beancount.
2.1 Разбор экспортов из QuickBooks с помощью Python
Использование Python обеспечит точность и воспроизводимость трансформации. Мы наметим скрипты для двух ключевых задач: импорт плана счетов и конвертация транзакций.
Импорт и сопоставление счетов: Крайне важно настроить ваши счета в Beancount перед добавлением транзакций. Счета QuickBooks имеют типы (Банк, Дебиторская задолженность, Расходы и т.д.), которые мы сопоставим с иерархией Beancount (Активы, Обязательства, Доходы, Расходы и т.д.). Например, мы можем использовать такое сопоставление:
# Сопоставление типа счёта QuickBooks с корневой категорией Beancount
AccountTypeMap = {
'BANK': 'Assets',
'CCARD': 'Liabilities',
'AR': 'Assets', # Дебиторская задолженность как актив
'AP': 'Liabilities', # Кредиторская задолженность как обязательство
'FIXASSET': 'Assets',
'OASSET': 'Assets', # Прочие активы
'OCASSET': 'Assets', # Прочие оборотные активы
'LTLIAB': 'Liabilities', # Долгосрочные обязательства
'OCLIAB': 'Liabilities', # Прочие текущие обязательства
'EQUITY': 'Equity',
'INC': 'Income',
'EXP': 'Expenses',
'EXINC': 'Income', # Прочие доходы
'EXEXP': 'Expenses', # Прочие расходы
}
Используя экспорт IIF из QuickBooks Desktop или CSV-файл со списком счетов из QBO, мы получаем имя и тип каждого счёта. Затем:
-
Создайте имена счетов Beancount: QuickBooks иногда использует двоеточия (
:
) в именах счетов для обозначения субсчетов (например, "Current Assets:Checking"). Beancount использует ту же нотацию с двоеточием для иерархии. Часто можно использовать имя напрямую. Если имена счетов QuickBooks не начинаются с категории, добавьте сопоставленную категорию в начало. Например, счёт QuickBooks типаBANK
с названием "Checking" станетAssets:Checking
в Beancount. СчётEXP
(расход) "Meals" станетExpenses:Meals
и т.д. -
Обеспечьте корректность именования: Удалите или замените любые символы, которые могут сбить Beancount с толку. QuickBooks допускает символы вроде
&
или/
в именах. Разумно вырезать или заменить специальные символы (например, заменить&
наand
, удалить слэши или пробелы). Также убедитесь, что все имена счетов уникальны после трансформации – QuickBooks мог позволять одинаковые имена субсчетов у разных родительских счетов, что нормально, но в Beancount полное имя (с родителями) должно быть уникальным. При необходимости переименуйте или добавьте квалификатор для их различения. -
Выведите открыти я счетов: В Beancount каждый используемый счёт должен быть открыт с помощью директивы
open
. Вы можете выбрать дату до вашей первой транзакции (например, если вы мигрируете данные за 2019–2023 годы, используйте2018-12-31
или даже более раннюю дату для всех открытий). Скрипт запишет строки вида:2018-12-31 open Assets:Checking USD
2018-12-31 open Expenses:Meals USD
для каждого счёта (предполагая, что основная валюта — USD). Используйте соответствующую валюту для каждого счёта (см. заметки о мультивалютности ниже).
Конвертация транзакций: Основная задача — преобразовать экспорт транзакций QuickBooks (CSV) в записи Beancount. Каждая транзакция QuickBooks (счёт-фактура, счёт, чек, журнальная запись и т.д.) может иметь несколько проводок (строк), которые необходимо собрать в одну транзакцию Beancount.
Мы будем использовать CSV-ридер Python для итерации по экспортированным строкам и накопления проводок:
import csv
from collections import defaultdict
# Чтение всех строк из CSV-файла журнала QuickBooks
rows = []
with open('quickbooks_exported_journal.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for line in reader:
rows.append(line)
# Группировка строк по транзакциям (предполагая, что 'Trans #' идентифицирует транзакции)
transactions = defaultdict(list)
for line in rows:
trans_id = line.get('Trans #') or line.get('Transaction ID') or line.get('Num')
transactions[trans_id].append(line)
Теперь transactions
— это словарь, где каждый ключ — это ID/номер транзакции, а значение — список проводок для этой транзакции. Далее мы конвертируем каждую группу в формат Beancount:
def format_date(qb_date):
# Даты в QuickBooks могут быть в формате "12/31/2019"
m, d, y = qb_date.split('/')
return f"{y}-{int(m):02d}-{int(d):02d}"
output_lines = []
for trans_id, splits in transactions.items():
# Сортировка проводок по порядку строк, если необходимо (обычно они уже уп орядочены)
splits = sorted(splits, key=lambda x: x.get('Line') or 0)
first = splits[0]
date = format_date(first['Date'])
payee = first.get('Name', "").strip()
memo = first.get('Memo', "").strip()
# Заголовок транзакции
output_lines.append(f"{date} * \"{payee}\" \"{memo}\"")
if first.get('Num'): # включаем номер ссылки, если доступен
output_lines.append(f" number: \"{first['Num']}\"")
# Цикл по каждой проводке/постингу
for split in splits:
acct_name = split['Account'].strip()
# Сопоставляем имя счёта QuickBooks со счётом Beancount (используя предыдущее сопоставление)
beancount_acct = account_map.get(acct_name, acct_name)
# Определяем сумму со знаком:
amount = split.get('Amount') or ""
debit = split.get('Debit') or ""
credit = split.get('Credit') or ""
if amount:
# Некоторые экспорты имеют один столбец Amount (отрицательный для кредитов)
amt_str = amount
else:
# Если отдельные столбцы Debit/Credit
amt_str = debit if debit else f"-{credit}"
# Для безопасности удаляем все запятые в числах
amt_str = amt_str.replace(",", "")
# Добавляем валюту
currency = split.get('Currency') or "USD"
amt_str = f"{amt_str} {currency}"
# Заметка/описание для проводки
line_memo = split.get('Memo', "").strip()
comment = f" ; {line_memo}" if line_memo else ""
output_lines.append(f" {beancount_acct:<40} {amt_str}{comment}")
# Конец транзакции – пустая строка
output_lines.append("")
Эта логика скрипта выполняет следующее:
-
Форматирует дату в YYYY-MM-DD для Beancount.
-
Использует получателя (Name) и заметку (Memo) для описания транзакции. Например:
2020-05-01 * "ACME Corp" "Оплата счёта-фактуры"
(Если получателя нет, можно использовать Тип транзакции из QuickBooks или оставить кавычки пустыми). -
Добавляет метаданные
number
, если есть номер ссылки (№ чека, № счёта-фактуры и т.д.). -
Итерирует по каждой строке проводки:
- Сопоставляет имя счёта QuickBooks со счётом Beancount, используя словарь
account_map
(заполненный на шаге с планом счетов). - Определяет сумму. В зависимости от вашего экспорта, у вас может быть один столбец Сумма (с положительными/отрицательными значениями) или отдельные столбцы Дебет и Кредит. Приведённый выше код обрабатывает оба случая. Он гарантирует, что кредиты представляются как отрицательные суммы для Beancount (так как в Beancount для каждой проводки используется одно число со знаком).
- Прикрепляет валюту (предполагая USD, если не указан другой столбец с валютой).
- Записывает строку проводки Beancount со счётом, суммой и комментарием с заметкой из строки. Например:
Assets:Checking 500.00 USD ; Депозит
Income:Sales -500.00 USD ; Депозит
Это отр ажает депозит в $500 (с Доходов на Расчётный счёт).
- Сопоставляет имя счёта QuickBooks со счётом Beancount, используя словарь
-
После перечисления всех проводок пустая строка разделяет транзакции.
Обработка мультивалютности: Если ваши данные в QuickBooks включают несколько валют, указывайте код валюты в каждой проводке (как показано выше). Убедитесь, что счета в иностранных валютах открыты с этой валютой. Например, если у вас есть банковский счёт в EUR, вы должны вывести open Assets:Bank:Checking EUR
, и транзакции на этом счёте будут использовать EUR. Beancount поддерживает мультивалютные главные книги и будет отслеживать неявные конвертации, но вам может понадобиться добавить записи о ценах для курсов обмена, если вы хотите конвертировать в базовую валюту в отчётах. Также рекомендуется объявить вашу основную операционную валюту вверху файла Beancount (например, option "operating_currency" "USD"
).
Запуск конвертации: Сохраните скрипт Python (например, как qb_to_beancount.py
) и запустите его на ваших экспортированных файлах. Он должен создать файл .beancount
, содержащий все счета и транзакции.
2.2 Обработка крайних случаев и очистка данных
Во время трансформации помните об этих распространённых подводных камнях и способах их решения:
-
Несоответствия в названиях счетов: В QuickBooks могут быть имена счетов, которые конфликтуют с иерархическими именами Beancount. Например, в QuickBooks могут быть два разных родительских счёта, у каждого из которых есть субсчёт с названием "Страхование". В Beancount
Expenses:Insurance
должно быть уникальным. Решите это, переименовав один из них (например, "Страхование-Автомобиль" против "Страхование-Здоровье") перед экспортом или сопоставьте их с уникальными счетами Beancount в вашем скрипте. Последовательные соглашения об именах (без специальных символов и с использованием иерархии) сэкономят вам головную боль. При необходимости используйте подход с файлом пересопоставления: ведите CSV или словарь "старое имя → новое имя Beancount" и применяйте его во время конвертации (наш пример кода используетaccount_map
и мог бы загружать переопределения из файла). -
Даты и форматы: Убедитесь, что все даты отформатированы последовательно. Приведённый выше скрипт нормализует M/D/Y в формат ISO. Также следите за проблемами с финансовым и календарным годом, если ваш пятилетний период пересекает конец года. Beancount не волнуют границы финансового года, но позже вы можете захотеть разделить файлы по годам для удобства.
-
Числовая точность: QuickBooks обрабатывает валюту с центами, поэтому работа в центах обычно подходит. Все суммы в идеале должны иметь два десятичных знака в CSV. Если какие-то суммы превратились в целые числа (без десятичной части) или содержат запятые/скобки (для отрицательных чисел), очистите их в скрипте (удалите запятые, преобразуйте
(100.00)
в-100.00
и т.д.). Экспорт в CSV, если он выполнен правильно (согласно инструкциям), должен был уже избежать этих проблем с форматированием. -
Отрицательные суммы и знаки: Отчёты QuickBooks иногда показывают отрицательные числа как
-100.00
,(100.00)
или даже--100.00
в некоторых экспортах в Excel. Шаг очистки должен справиться с этим. Убедитесь, что дебеты и кредиты каждой транзакции в сумме дают ноль. Beancount будет это проверять (если не сбалансировано, он выдаст ошибку при импорте). -
Дубликаты транзакций: Если вам пришлось экспортировать транзакции частями (например, по годам или по счетам), будьте осторожны при их объединении, чтобы избежать пересечений. Проверьте, что первая транзакция года не является также последней из предыдущей партии и т.д. Легко случайно продублировать несколько транзакций на границах. Если вы подозреваете дубликаты, вы можете отсортировать итоговые записи Beancount по дате и поискать идентичные записи, или использовать уникальные теги транзакций Beancount для их отлова. Одна из стратегий — включить номера транзакций QuickBooks в метаданные (например, использовать
Trans #
или номер счёта-фактуры как тегtxn
или метаданныеquickbooks_id
), а затем убедиться в отсутствии дубликатов этих ID. -
Несбалансированные проводки / Временные счета: В QuickBooks могут быть странные случаи, наприм ер, транзакция с дисбалансом, который QuickBooks автоматически скорректировал на счёт "Начальный капитал" или "Нераспределённая прибыль". Например, при настройке начальных остатков счетов QuickBooks часто проводит разницы на счёт Капитала. Они появятся в экспортированных транзакциях. Beancount потребует явной балансировки. Вам может понадобиться ввести счёт Капитала для начальных остатков (обычно
Equity:Opening-Balances
), чтобы отразить логику QuickBooks. Хорошей практикой является создание записи о начальных остатках в первый день вашей главной книги, которая устанавливает стартовые балансы всех счетов (см. Этап 5). -
Крайние случаи с мультивалютностью: При использовании нескольких валют экспорт из QuickBooks может перечислять все суммы в домашней валюте или в их родной валюте. В идеале, получите данные в родной валюте для каждого счёта (отчёты QuickBooks Online обычно так и делают). В Beancount каждая проводка несёт в себе валюту. Если QuickBooks предоставил курсы обмена или конвертацию в домашнюю валюту, вы можете проигнорировать их и полагаться на записи о ценах в Beancount. Если QuickBooks не экспортировал ку рсы обмена, вы можете захотеть вручную добавить записи о ценах (например, используя директиву
price
в Beancount) для ключевых дат, чтобы соответствовать оценке. Однако для базовой целостности главной книги достаточно, чтобы транзакции сходились в своих исходных валютах – нереализованные прибыли/убытки не нужно явно записывать, если вы не хотите получить те же отчёты. -
Дебиторская / Кредиторская задолженность: QuickBooks отслеживает детали счетов-фактур и счетов (сроки оплаты, статус оплаты и т.д.), которые не будут полностью перенесены в простую главную книгу. Вы получите транзакции по дебиторской и кредиторской задолженности (счета-фактуры увеличивают ДЗ, платежи уменьшают ДЗ и т.д.), но не документы счетов-фактур или балансы клиентов по счетам. В результате после миграции вы должны проверить, что балансы ваших счетов ДЗ и КЗ в Beancount равны открытым остаткам клиентов/поставщиков в QuickBooks. Если вам нужно отслеживать счета-фактуры, вы можете использовать метаданные Beancount (например, включить тег
invoice
или ссылку). Номера счетов-фактур из QuickBooks должны были перейти в поляNum
илиMemo
– наш скрипт сохраняетNum
какnumber: "..."
в метаданных транзакции. -
Неактивные или закрытые счета: Экспорт IIF может включать неактивные счета (если вы выбрали их включение). Их можно импортировать (у них просто не будет транзакций и будет нулевой баланс, если они действительно неактивны). Вы можете пометить их как закрытые в Beancount после даты последней транзакции с помощью директивы
close
. Это поддерживает порядок в вашей главной книге. Например:2023-12-31 close Expenses:OldAccount ; закрыт после миграции
Это необязательно и в основном для чистоты.
Тщательно очистив и сопоставив данные, как описано выше, вы получите файл главной книги Beancount, который структурно отражает ваши данные из QuickBooks. Следующий шаг — убедиться, что он также численно отражает QuickBooks.
Этап 3: Проверка и сверка данных
Проверка — это критически важный этап в миграции бухгалтерских данных. Нам нужно убедиться, что главная книга Beancount совпадает с книгами QuickBooks до копейки. Для этого можно использовать несколько стратегий и инструментов:
3.1 Сверка по оборотно-сальдовой ведомости
Оборотно-сальдовая ведомость — это отчёт, в котором перечислены конечные остатки по всем счетам (с указанием дебетов и кредитов или положительных/отрицательных значений), и который должен сходиться к нулю. Запуск оборотно-сальдовой ведомости в обеих системах на одну и ту же дату — самый быстрый способ подтвердить общую точность.
-
В QuickBooks: Запустите отчёт Оборотно-сальдовая ведомость (Trial Balance) на последний день последнего года (например, 31 декабря 2023 года). Этот отчёт показывает баланс каждого счёта. Экспортируйте его или запишите ключевые цифры.
-
В Beancount: Используйте отчётность Beancount для генерации оборотно-сальдовой ведомости. Один из простых способов — через командную строку:
bean-report migrated.beancount balances
Отчёт
balances
— это оборотно-сальдовая ведомость, перечисляющая все счета и их остатки. Вы также можете открыть файл в Fava (веб-интерфейс Beancount) и посмотреть раздел Balances или Balance Sheet. Каждый остаток по счёту в Beancount должен совпадать с оборотно-сальдовой ведомостью QuickBooks. Например, если QuickBooks показывает Дебиторская задолженность = $5,000, то счёт Assets:Accounts Receivable в Beancount должен иметь итоговую сумму $5,000 (дебет). Если Доход от продаж = $200,000, то счёт Income:Sales в Beancount должен показывать $200,000 (кредит, что может отображаться как -200,000, если используется оборотно-сальдовая ведомость, представляющая кредиты как отрицательные числа).
Если есть расхождения, найдите их:
- Проверьте, не отсутствует ли целый счёт или не добавлен ли лишний (мы забыли счёт или включили тот, который был закрыт до периода миграции?).
- Если остаток не сходится, углубитесь: QuickBooks может запустить Быстрый отчёт по счёту (Account QuickReport) или детализацию главной книги для этого счёта, и вы можете сравнить это с регистром Beancount для этого счёта (
bean-report migrated.beancount register -a ИмяСчёта
). Иногда различия возникают из-за пропущенной или дублирующейся транзакции.
Также проверьте, что сумма всех счетов равна нулю в оборотно-сальдовой ведомости Beancount (она выводит итог, который должен быть равен нулю или очень близок к нему). Beancount применяет двойную запись, поэтому если у вас есть ненулевой дисбаланс, это означает, что активы минус обязательства-капитал не сошлись к нулю, что указывает на проблему (которую QuickBooks обычно не допускает, но это может произойти, если некоторые данные были утеряны).
3.2 Сравнение остатков по счетам
Помимо оборотно-сальдовой ведомости, вы можете сравнить конкретные финансовые отчёты:
-
Балансовый отчёт: Запустите Балансовый отчёт в QuickBooks на конечную дату и балансовый отчёт в Beancount (
bean-report migrated.beancount balsheet
). Это похоже на оборотно-сальдовую ведомость, но организовано по Активам, Обязательствам, Капиталу. Цифры должны совпадать по категориям. Для более детальной проверки сравните итоговые суммы по основным счетам: денежные средства, ДЗ, основные средства, кредиторская задолженность, капитал и т.д. -
Отчёт о прибылях и убытках: Запустите Отчёт о прибылях и убытках за пятилетний период (или по годам) в QuickBooks и в Beancount (
bean-report migrated.beancount income
для отчёта о прибылях и убытках за весь период). Чистая прибыль из Beancount должна быть равна чистой прибыли из QuickBooks за каждый период. Если вы мигрировали все пять лет, совокупная чистая прибыль должна совпадать. Вы также можете сравнить отдельные итоговые суммы доходов и расходов, чтобы убедиться, что ни одна категория не была пропущена или продублирована. -
Выборочная проверка транзакций: Выберите несколько случайных транзакций (особенно из каждого года и каждого крупного счёта) и проверьте, что они мигрировали правильно. Например, найдите счёт-фактуру трёхлетней давности в QuickBooks, а затем найдите его сумму или заметку в файле Beancount (поскольку все транзакции текстовые, вы можете открыть файл
.beancount
в текстовом редакторе или использовать инструменты поиска). Проверьте, что дата, суммы и счета совпадают. Это помогает выявить проблемы с форматированием дат или неправильно сопоставленные счета.
3.3 Автоматизированные проверки целостности
Используйте встроенные инструменты проверки Beancount:
-
bean-check: Запустите
bean-check migrated.beancount
. Он разберёт файл и сообщит о любых ошибках в синтаксисе или балансировке. Если скрипт пропустил что-то, например, не открытый счёт или несбалансированную транзакцию,bean-check
это обнаружит. Чистый проход (без вывода) означает, что файл как минимум внутренне согласован. -
Утверждения о балансе: Вы можете добавить явные утверждения о балансе в главную книгу для ключевых счетов в качестве дополнительной проверки. Например, если вы знаете остаток на банковском счёте на определённую дату, добавьте строку:
2023-12-31 balance Assets:Bank:Checking 10000.00 USD
Тогдаbean-check
убедится, что в главной книге на эту дату баланс действительно составляет $10,000. Это необязательно, но может быть полезно для счетов высокой важности. Вы можете взять конечные остатки из QuickBooks (например, на конец каждого года) и утвердить их в файле Beancount. Если какое-либо утверждение не сработает, Beancount сообщит о разнице. -
Проверка оборотно-сальдовой ведомости по периодам: Если хотите, вы можете провести проверку по периодам. Для каждого года сравните чистое изменение. Например, чистая прибыль в QuickBooks 2020 против Beancount 2020 и т.д., чтобы убедиться, что каждый год правильно закрылся в капитал (QuickBooks автоматически переносит чистую прибыль в Нераспределённую прибыль каждый новый год; в Beancount вы просто увидите совокупный капитал). Если вы видите различия, это может указывать на проблему в данных конкретного года.
-
Количество транзакций и дубликаты: Подсчитайте количество транзакций в QuickBooks и в Beancount. QuickBooks не показывает прямое количество легко, но вы можете оценить его, подсчитав строки в CSV (каждый заголовок транзакции против проводок). В Beancount быстрый способ — посчитать вхождения
txn
или* "
в файле. Они должны быть равны или немного больше, чем в QuickBooks (если вы добавили транзакции начального остатка или корректировки). Значительное несоответствие означает, что что-то могло быть пропущено или продублировано. Использование нами уникальных ID в метаданных может помочь: если вы подозреваете дубликаты, поищ ите в файле Beancount тот же номер чека или счёта-фактуры, появляющийся дважды, когда этого быть не должно. -
Статус сверки: Мы включили метаданные
rec: "y"
или"n"
на основе статуса cleared в QuickBooks в нашем скрипте (какrec
в примере). Это не стандартная функция Beancount (Beancount не отслеживает cleared/pending так же, как Ledger), но это могут быть полезные метаданные. Вы можете проверить, что все транзакции, которые были сверены в QuickBooks, присутствуют. В конечном счёте, новая сверка банковских счетов в Beancount (с использованием ваших выписок) может стать окончательным доказательством того, что ничего не пропало.
Выполняя эти проверки, вы укрепляете уверенность в том, что миграция сохранила данные. Не торопитесь на этом этапе – легче исправить аномалии сейчас, чем через месяцы, когда на книги могут полагаться. Частые проблемы при сбое проверки: отсутствие начального остатка счёта, транзакция с датой за пределами диапазона или инверсия знака в записи. Все они исправимы после выявления.
Этап 4: Фиксаци я данных в главной книге Beancount
После очистки и проверки пришло время формализовать данные в структуре вашей главной книги Beancount. «Фиксация» здесь означает как завершение работы над файлами главной книги, так и, возможно, их внесение в систему контроля версий для аудита.
4.1 Организация файлов главной книги и конфигурации
Решите, как структурировать файлы главной книги Beancount. Для данных за пять лет вы можете хранить всё в одном файле или разделить по годам или категориям. Распространённая и понятная структура:
- Основной файл главной книги: например,
ledger.beancount
– это точка входа, которая можетinclude
другие файлы. Он может содержать глобальные опции, а затем включать годовые файлы. - Файл счетов: Определите план счетов и начальные остатки. Например,
accounts.beancount
со всеми директивамиopen
(сгенерированными скриптом). Здесь же вы можете перечислить товары (валюты). - Файлы транзакций: По одному на каждый год, например,
2019.beancount
,2020.beancount
и т.д., содержащие транзакции за этот год. Это позволяет поддерживать manageable размер каждого файла и сосредоточиться на одном годе при необходимости. Альтернативно, можно разделить по сущностям или счетам, но разделение по времени просто и понятно для финансовых данных.
Пример основного файла:
option "title" "Моя главная книга бизнеса"
option "operating_currency" "USD"
include "accounts.beancount"
include "2019.beancount"
include "2020.beancount"
...
include "2023.beancount"
Таким образом, все данные агрегируются при запуске отчётов, но вы поддерживаете порядок.
Beancount не требует нескольких файлов – у вас может быть один большой файл – но вышеуказанная структура улучшает ясность и контроль версий. Согласно лучшим практикам Beancount, хорошо использовать понятные заголовки разделов и логически группировать связанные записи.
4.2 Установка начальных остатков и капитала
Если ваша миграция не начинается с абсолютного нуля, вам нужно будет обработать начальные остатки. Два сценария:
-
Книги с нуля: Если пятилетний период начинается с момента основания бизнеса (например, вы начали использовать QuickBooks в январе 2019 года со всеми счетами, обнулёнными, кроме первоначального капитала), то вам может не понадобиться отдельная транзакция начального баланса. Первые транзакции в 2019 году (например, первоначальное финансирование на банковский счёт) естественным образом установят начальные остатки. Просто убедитесь, что любой первоначальный капитал или нераспределённая прибыль за прошлые периоды учтены через транзакции капитала.
-
Книги в середине периода (частичная история): Если вы начали использовать QuickBooks раньше, и 2019 год — это середина, то на 1 января 2019 года у каждого счёта был перенесённый остаток. В QuickBooks они были бы в виде начальных остатков или нераспределённой прибыли. В Beancount типично создать запись о начальных остатках за день до даты начала:
- Используйте счёт капитала под названием
Equity:Opening-Balances
(или аналогичный) для компенсации суммы всех начальных остатков. - Пример: если на 31.12.2018 денежные средства составляли $10,000, ДЗ $5,000 и КЗ $3,000 (кредит), вы бы записали транзакцию:
2018-12-31 * "Начальные остатки"
Assets:Cash 10000.00 USD
Assets:Accounts Receivable 5000.00 USD
Liabilities:Accounts Payable -3000.00 USD
Equity:Opening-Balances -12000.00 USD
Это оставляет на счёте Opening-Balances отрицательную сумму (–$12k), которая балансирует запись. Теперь все счета активов/обязательств начинают 2019 год с правильными остатками. Это должно отражать любые "Нераспределённые прибыли" или перенесённые остатки из QuickBooks. - В качестве альтернативы используйте директивы Beancount
pad
иbalance
: Для каждого счёта вы можетеpad
его со счёта Opening-Balances и подтвердить баланс. Это более автоматизированный способ. Например:2018-12-31 pad Assets:Cash Equity:Opening-Balances
2018-12-31 balance Assets:Cash 10000.00 USD
Это говорит Beancount вставить любую необходимую запись (на счёт Opening-Balances), чтобы остаток по счёту Cash равнялся 10000 USD на эту дату. Сделайте это для каждого счёта. Результат будет похожим, но написание явной транзакции, как в первом методе, также является простым.
- Используйте счёт капитала под названием
-
Нераспределённая прибыль: QuickBooks не экспортирует явно транзакцию "Нераспределённая прибыль" – он просто вычисляет её. После миграции вы можете заметить, что Equity:Retained Earnings равно нулю, если вы его не создали. В Beancount нераспределённая прибыль — это просто прибыль прошлых лет. Вы можете создать счёт Нераспределённой прибыли и переводить на него прибыль прошлых периодов в первый день каждого нового года, или просто позволить капиталу быть суммой всех доходов/расходов (что появляется в разделе Капитал в отчётах). Для прозрачности некоторые пользователи ежегодно делают закрывающие записи. Это необязательно и в основном для презентации. Поскольку мы мигрировали все транзакции, прибыль за каждый год будет естественным образом сворачиваться, если вы запустите отчёт по годам.
-
Сравнительные проверки: После установки начальных остатков запустите балансовый отчёт на дату начала, чтобы убедиться, что всё верно (он должен показывать эти начальные остатки против начального капитала, сводящегося к нулю).