Линукс, Vim, LaTeX, полезные скрипты, визуализация данных, численные расчёты, немного ФП

20090515

Ledger — бухучёт в командной строке

Решил, что надо наводить порядок в своей жизни и деньги считать. В общем, вести домашнюю бухгалтерию. Познания в бухучёте у меня очень скромные (хотя когда-то и прослушал вводный курс), помню только, что такое двойная запись, и дебет/кредит. Когда-то, правда, пользовался GNUcash.

Кроме GNUcash в линуксе есть ещё несколько программ для учёта личных финансов: KMyMoney и Grisbi. Программы красивые, удобные, наглядные. Однако меня впечалил и заинтересовал ledger. Это бухучёт в стиле unix. В общем, для фанатов.

Идея проста: записываем все расходы/доходы в текстовый файл (файл редактируем сами, программа его не трогает), а программа всегда поможет проверить баланс и составить отчёт о текущем состоянии или по периоду. Что может быть естественней, проще, надёжней? Полный простор в организации учёта.

Отмечу, что вначале я нашёл не сам ledger, а его клон hledger, написанный на Haskell. Есть ещё и вариант написанный на Python — beancount. Какую программу выбрать — дело вкуса. Формат файла, к счастью, у них (почти) одинаковый. «Старший» ledger уже есть в репозиториях Ubuntu и Debian, но мне пока больше понравился вариант на Haskell (исходники короче и понятнее), про него и буду рассказывать.

Хотя сложного в использовании ledger вроде ничего нет, трудно начать, потому что все примеры в сети на английском и используют английскую бухгалтерскую терминологию. Для меня, чтобы разобраться, было важно понять формат в котором вести записи. Итак, файл состоит из записей, формат каждой записи
ДАТА[=ФАКТИЧЕСКАЯ ДАТА] [*|!] [(КОД)] [ОПИСАНИЕ] [ ; КОММЕНТАРИЙ ]
отступ НАЗВАНИЕ СЧЕТА хотя бы два пробела СУММА [ ; КОММЕНТАРИЙ ]
отступ НАЗВАНИЕ ДРУГОГО СЧЕТА [ хотя бы два пробела СУММА ] [ ; КОММЕНТАРИЙ ]
[другие счета, если необходимо]
Каждая запись начинается с цифры, то есть даты. Даты пишем в формате ISO, ГГГГ-ММ-ДД. Для краткости можем указать в файле
Y2009
и все последующие записи без указания года будут относится к 2009-му году.

Описание проводки может быть любым. Номера квитанций, счетов и тому подобные коды можно вписывать в поле (КОД) (указывать перед описанием в скобках).

СУММЫ можно писать так, как удобно, «13», «$42», «17 EUR», «121 Kb», «9 L». Ledger понимает, что разные единицы измерения нужно считать отдельно. Единицы можно указывать любые, те, которые нужно учитывать. В том числе и неденежные (и программа умеет их правильно пересчитывать, если ей дать файл с историей цен).

В каждой записи обычно два или три счета, но указывать сумму для одного из них необязательно, понятно, что изменение будет равно сумме всех других, но с противоположенным знаком:
2009-05-14
расходы:обед 123 RUB
актив:наличные ; понятно, что здесь должно быть -123 RUB
Счета можно называть как угодно. В том числе и по-русски. Можно делать подсчета, используя двоеточие в названии счёта, например, «расходы:услуги:интернет». Видимо, необходимо иметь счета как минимум пяти категорий: актив, долги, доходы, расходы и какой-то счёт для уравнивания балансов. Я назвал его «собственные», в англоязычных примерах его обычно называют «equity».

Дело в том, что двойная запись подразумевает, что всегда выполняется закон сохранения денег. Всегда, когда к какому-то счёту мы их приписываем, точно такую же сумму мы должны с какого-то счёта списать. Поэтому уже в начале, чтобы указать сумму денег в кошельке и на счету в банке, нужно ввести некий счёт, с которого они «пришли».

Составим такой файл со счетами, для начала. Пусть у нас есть текущий счёт в банке, на котором лежит 1001 рубль (единицы не будем указывать для краткости), есть что-то в кошельке, скажем 150 рублей. Пишем файл:
Y2009

05-14 начальное состояние счета в банке
актив:банк 1001
собственные:начало

05-14 начальное содержимое кошелька
актив:наличные 150
собственные:начало
Сохраняем в файл, например ~/.ledger (там его по-умолчанию ищет hledger). Смотрим, что получилось:
~$ hledger
1151 актив
1001 банк
150 наличные
-1151 собственные:начало
Программа сама догадалась подсчитать баланс виртуального счёта «актив». Всё сходится: всё, что было списано со счёта «собственные:начало» оказалось в «активе». Если что-то не сходится, программа будет страшно ругаться.

Как записывать расход-приход — см пример записи выше. Допустим, мы что-то купили и что-то получили в подарок:
05-15 * подарок
актив:наличные 100
доходы:подарки
05-15 * яблоко
расходы:покупки 9
актив:наличные
Я добавил звёздочку перед описнием проводок. Как её интерпретировать — дело хозяйское. Я помечаю ей те операции, которые уже завершены (а восклицательным знаком — те, которые запланированы). Программа потом позволяет легко отбирать проводки со звёздочкой и без.

Предположим, например, что на завтра я запланировал ответный подарок, но ещё его не сделал:
05-16 ! ответный подарок
расходы:подарки 90
актив:наличные
Теперь, если посмотреть баланс с ключиком -C, увидим только то, что завершено:
$ hledger -C bal
91 актив:наличные
-100 доходы:подарки
9 расходы:покупки
Чтобы посмотреть не баланс, а список проводок, есть команда register:
~$ hledger reg
2009/05/14 начальное состояни.. актив:банк 1001 1001
собственные:начало -1001 0
2009/05/14 начальное содержим.. актив:наличные 150 150
собственные:начало -150 0
2009/05/15 подарок актив:наличные 100 100
доходы:подарки -100 0
2009/05/15 яблоко расходы:покупки 9 9
актив:наличные -9 0
2009/05/16 ! ответный подарок расходы:подарки 90 90
актив:наличные -90 0
Отмечу, что в «сишной» версии ledger колонки здесь разъедутся. А вот в hledger-0.5 уже всё в порядке (и для 0.4 я тоже сделал патчик).

В общем, баланс (balance) и проводки (register) — два главных отчёта. Можно ограничивать отчёты по диапазону дат или периодам. Или по названиям счетов. Так, чтобы выбрать все счета со словом «подарки» в названии, используем регулярное выражение:
$ hledger reg .*подарки.*
2009/05/15 подарок доходы:подарки -100 -100
2009/05/16 ! ответный подарок расходы:подарки 90 -10
Чтобы выбрать записи по описанию, поступаем так:
$ hledger reg desc:яблоко
2009/05/15 яблоко расходы:покупки 9 9
актив:наличные -9 0
В общем, идея понятна. Для отчётов по неделям и по месяцам есть ключики -W и -M.

Бывают ещё периодические записи, но только в ledger, в hledger их пока нет. Они не означают, что со счёта что-то автоматически списывается. Проводку нужно всё равно вносить вручную, но периодические записи позволяют рассчитывать прогноз бюджета. В ledger также можно делать виртуальные записи, ими можно автоматически учитывать разные комиссии или проценты.

Вот такая программка. Думаю, не одному мне понравится. Вижу большое достоинство программы в том, что формат данных очень простой и естественный. Посмотрю теперь, будет ли её хватать для моих нужд.

Вот пример ledger-файла.

22 коммент.:

  1. Попахивает маньячеством :)

    Для меня, одно из самых главных достоинств программ бухучета - возможность предсказывать финансовое будущее и проверять сценарии "что, если". Уже пару месяцев пользуюсь KMyMoney (после нескольких лет использования MS Money) и полностью доволен этой программой.

    ОтветитьУдалить
  2. Мда... точно попахивает.

    Потеря времени всё это.

    ОтветитьУдалить
  3. Не могу сказать про эту программу, но ради одной бухгалтерии я держу Windows... Всё никак не найду ничего под Linux простого. И понятного. Но это НЕ трата времени, просто вы не умеете пользоаться этим, я уже использую такого рода программу порядка 3-х лет. Результаты впечатляют!

    ОтветитьУдалить
  4. Любопытно, что же программа дает взамен, какие отчеты/прогнозы/графики/подсказки? Данные вводить не проще, чем в любую другую программу, в чем же тогда "фишка"?;)

    ОтветитьУдалить
  5. Занятно. Название интригующее, хотя внутри не совсем то, что ожидаешь (я аж к стулу примёрз: думал, что 1С в консоли сделали :-))

    Примерный объём личных финансов можно помнить, даже при наличии двух депозитов и трёх текущих счетов. Или банкомат терзать время от времени.

    ОтветитьУдалить
  6. Программа, конечно, на любителей. Однако и программа, и учёт расходов могут быть весьма полезны (не всем).

    Поясню, чем мне интересна эта программа. Дело не в том, что она «предоставляет» по сравнению с комбайнами. Дело в том, что она легко уживается с другими повседневными инструментами: текстовым редактором, командной оболочкой (shell) и множеством её утилиток, системой контроля версий... То есть здесь интересен инструментальный, модульный подход к задаче, а не конкретные возможности.

    Также, пользователь ledger использует простой и человекочитаемый формат данных, полностью им контроллируемый. Благо, сложность задачи и объём вычислений позволяют таким форматом пользоваться. Следствие: конкретные инструменты взаимозаменяемы (ledger/hledger/beancount), а в случае чего написать скрипт для какой-то особенной задачи — нетрудно. О преимуществах такого подхода — см. пятую главу The Art of Unix Programming или The UNIX Philosophy. Альтернатива — увязанные воедино графический интерфейс, непрозрачный формат (в запущенных случаях проприетарный, в менее запущенных бинарно-xml-ный) и обработчики данных (легко ли их изменить или разнообразить?).

    Наконец, о необходимости вести учёт. Дело хозяйское, конечно, но учёт позволяет не только посчитать «сколько есть», но и наглядно увидеть структуру расходов.

    P.S. Мне было бы интересно услышать от людей, ведущих такой учёт давно, что с их точки зрения в ledger не хватает.

    ОтветитьУдалить
  7. Пока ребят всё руки не дойдут. Учёт как писал выше уже не первый год веду. Постараюсь уйти с пропиретарного кода.

    Постараюсь написать чего и как получилось.

    ОтветитьУдалить
  8. Этот комментарий был удален администратором блога.

    ОтветитьУдалить
  9. Прошу помощи в запуске bin версии hledger. Выгружаю, делаю исполняемым, запускаю... А оно мне syntax error... Из исходных кодов нету желания собирать - слишком много тянуть надо.

    ОтветитьУдалить
  10. Пока запускаю под wine... :-) Работает вроде. Но блин, за это ж мне надо глаза выколоть... Но собрать из исходных текстов я не смог за сорок минут, попробовал под wine. Прошу подскажите как всё же нативную то версию пустить под Linux бинарная, у них на сайте лежит.

    ОтветитьУдалить
  11. Готовые линуксовые бинарники сейчас есть только для x86-64 (amd64). Для i386 нет.

    Из исходных текстов оно собирается с помощью cabal, который автоматически соберёт и все зависимости. Только для сборки последней версии hledger (0.6.1) нужен и последний ghc (6.10), которого в пакетированном виде нет ни в Debian, ни в Ubuntu.

    У меня ghc 6.10.3 стоит самосборный из исходников, как и haskell platform (набор библиотек, претендующий на стандартность), hledger собирается гладко. Дистрибутивным ghc не соберётся.

    ОтветитьУдалить
  12. Ааа... Вот я кусок унылый... Я не понял, что это для amd64 - я подумал, что и для того и для того подойдёт.


    Да, со сборкой я намучался... ghc как раз. И пробовал параметр совместимой компиляции, но стало ругаться на zlib c что мол нету, я поискал, поставил, а оно всё равно ругается, я бросил и под wine запустил. Сергей, если будет возможность попросите Автора собрать под 32 bit или может есть возможность поделиться уже собранным..? Спасибо!

    ОтветитьУдалить
  13. Ну вы зря так на себя ругаетесь. Учитывая очень передовые зависимости и состояния пакетов с ghc, собрать его на рядовой машине не просто. А чтобы узнать про передовые зависимости, нужно на hackage идти (или .cabal смотреть).

    Автор (Симон Майкл) — сам недавно просил кого-нибудь собрать статический бинарник под i386 (у него amd64). Я было попробовал, но не вышло. Сейчас по вашей просьбе попробовал ещё раз, и кажется получилось.

    Попробуйте этот бинарник (вроде слинкован статически и у меня на Linux/i386 работает): hledger-0.6.1+9-linux-i386.gz. Это верия из darcs. Если заработает, дайте знать, пожалуйста.

    ОтветитьУдалить
  14. ОГРОМНОЕ спасибо. У меня на конфигурации:

    Ubutnu 8.10 32 bit заработало!

    Ну я глубоко не тестировал, но все примеры которые Вы тут привели заработали.

    Сергей, если Вас не затруднит, и я не доконца что-либо пойму (при этом буду стараться очень), я могу обратиться к Вам с вопросами по работе с программой..? В базовом варианте вроде заработало, но всё же. Как Вы правильно пишите начать трудно довольно, даже распечатал текст статьи и перечитываю на бумаге чтобы всё усвоить.

    Спасибо!

    ОтветитьУдалить
  15. Пожалуйста! Да, конечно, обращайтесь. Будем вместе разбираться.

    ОтветитьУдалить
  16. Почти разобрался. Сергей, подскажите такая ситуация: К примеру в активе есть такие счета: актив:банк, актив:ЯндексДеньги, актив:сейф. - Это к примеру, у меня их ещё больше. И основные проводки будут крутиться только вокруг этих счетов, то есть они будут пополняться, и будут расходоваться. Каким образом смотреть баланс только на нужных мне счетах..? Мне чтобы удобно планировать было, требуется общая картина. Сколько и где у меня в активе. То есть без учёта кучи остальных счетов, у меня просто всё весьма детально, то есть очень много будет транзакций расходов, интернет, обучение, проезд, пожертвование, еда и так далее... - Мне нужно делать отчёты по суммам за период на Интернет, к примеру - поэтому я детально так веду. Я правильно понимаю, что hledger без параметров это тоже самое, что и hledger -bal ..? Вот, мне надо просто отфильтровать актив, чтобы видеть чем я сейчас могу распоряжаться, как Вы это сделали бы..? grep использовать...? --depth не очень тоже подходит.--display=EXPR -не очень понял как использовать, но думаю, что это тоже не совсем то...

    СПАСИБО, если не сочтёте за труд мне подсказать!


    Также я предлагаю, всё, новые и интересные приёмы по работе с программой публиковать тут, то есть дополнять статью, лично мне да и многим я думаю, что будет весьма интересно!

    Спасибо! С Уважением Виктор.

    ОтветитьУдалить
  17. Сергей, что-то не работает параметр ui ...То есть оно работает, но что-то с кодировками похоже...

    Также параметр web не поддерживает фильтр - период не проверял. Но ругается в консоль так: hledger web
    starting web interface at http://localhost:5000/
    starting web browser
    opera: X Shared memory extension is not available. ZPixmap not supported
    opera: Activated running instance


    С кодировками нормально. - Но это уже видимо заслуга броузера.

    Также очень хочется параметра -o который есть в ledger.

    И хочется сделать так чтобы отображалось полностью проводка в reg если применять регулярное выражение к примеру:

    hledger reg -f ~/.ledger~bak .*расхо.*
    2009/04/07 приобретение перех.. Ра:Компьютер:Железо 700.0 700.0

    А без регулярного выражения будет так:
    hledger reg -f ~/.ledger~bak
    2009/04/07 приобретение перех.. Ра:Компьютер:Железо 700.0 700.0
    Актив:Кошелёк -700.0 0

    Как видно, в первой записи нету упоминания про Актив:Кошелёк

    Далее:
    При этих всех действиях описание проводки отображается не полностью... То есть:

    приобретение перех..

    Вместо:
    приобретение переходника usb to sata обрезка

    То есть всё описание, что больше 18 символов не отображается... Даже если использовать desc:

    Ну и последнее:
    Как Вы думаете, каким образом лучьше вести учёт: дал в долг, вернули долг..? Понятно, что заводить отдельные счета, и в описании, указывать обещанную дату возврата и ФИО одолжившего, или если ты берёшь, то аналогично... Но это как-то... Ну не очень... - Может есть идеи лучьше?

    В общем пользуюсь уже программой, жить можно. Но шероховатости есть.

    Также интересно услышать если Вы разобрались с виртуалными транзакциями, что это такое.


    СПАСИБО!

    ОтветитьУдалить
  18. По порядку.

    Да, ui некорректно отоброжает уникод, это баг.

    Фильтры в web у меня сейчас тоже не работают, завёл новый баг.

    Я до последнего времени ui и web практически не пользовался (даже компилировал без них). ui, по-моему, вполне заменяется hledger ... | less

    Новая версия пытается запускать по команде web браузер, мне это не очень нравится и у меня это не работает, отключается (сюрпиз!) ключом --debug. На это дело баг я тоже завёл.

    С идеей, что найденые проводки следует отображать целиком — согласен. Возможно, нужен ключик, чтобы можно было выбрать способ отображения. Как сейчас (удобно для grep), или целиком (логичней).

    Зачем ключик -o (сохранить вывод в файл) в ledger я не очень понимаю. Ведь можно просто сделать (h)ledger balance > output.txt.

    Сокращение описаний до 18 символов в печати реестра — фича, унаследованная от ledger. Так можно гарантировать, что список проводок всегда влезет по ширине в 80 символов и будет одного и того же формата у hledger, и у ledger. Я думаю, в будущем можно было бы сделать более красивое отображение в веб-интерфейсе, но кто-то должен взяться и сделать.

    Шероховатости есть. Я согласен. Поэтому сразу сознался, что программка для фанатов :-)

    С виртуальными транзакциями пока не разбирался.

    ОтветитьУдалить
  19. Отвечаю по порядку:
    Сразу оговорюсь, что: ledger я не использовал. Так-как оно есть только в репозитариях Ubuntu 9.04, у меня более старая версия этой ОС, и у меня ledger отсутствует там, про возможности ui web и другие я читал на сайте hledger. Поэтому как они работают правильно не знаю, но мне хочется этих возможностей.

    Да, ui некорректно отоброжает уникод, это баг. - Интересно, чтоже тогда корректно оно будет отображать если не уникод... :-) Ну это не более чем риторический шутливый вопрос.

    |less не заменит мне кажется, я так понимаю, что ui позволяет организовать псевдо ui, то есть ходить стрелочками и так далее.

    ui и web не самые важные функции, это конечно понятно. И тут даже спора нету - без них вполне жить можно.

    -o -тут согласен, что не догадался до использования оператора >. Может опять же я не прав, но мне почему-то хочется чтобы работать с программой не привлекая сторонних утилит вида > less grep и так далее. - Это опять же не критично, можно и так. Да и к -o можно сделать вызов печатной формы к примеру... -Ну к примеру чтобы шапочка вставлялась какая-либо. - Опять же не знаю как это работает в ledger... - Но это всё не очень надо конечно, согласен.

    Теперь про 18 символов: да, но Вы не обратили на один момент всё же внимания я снова процитирую:

    hledger reg -f ~/.ledger~bak .*расхо.*
    2009/04/07 приобретение перех.. Ра:Компьютер:Железо 700.0 700.0

    А без регулярного выражения будет так:
    hledger reg -f ~/.ledger~bak
    2009/04/07 приобретение перех.. Ра:Компьютер:Железо 700.0 700.0
    Актив:Кошелёк -700.0 0

    Как видно, в первой записи нету упоминания про Актив:Кошелёк

    Это бывает важно, когда смотришь и сразу видно из какой части актива была проведена проводка. - Согласитесь..? Это всё же мне кажется тоже баг...

    Про долги ничего не посоветуете?

    Резюмирую: Сергей, большое спасибо, что вы делаете bug reports. Я не смогу к сожалению сделать это сам, так-как уровень моего Английского Языка в данный момент не позволит внятно объяснить проблему.

    Если Вы не забросите это дело, то я думаю, что мы сможем так или иначе допилить программу.

    Также к сожалению я не смогу помочь в улучьшении web интерфейса, так-как я не программист, а скорее продвинутый пользователь, и не дизайнер, поэтому не смогу помочь даже картинками красивыми сделанными в gimp. Но всё же смогу попробовать помочь в тестировании.

    Продолжаю использовать программу. В остальном всё нравится.

    ОтветитьУдалить
  20. Про долги я бы сделал так:

    2038-01-01 взял в долг
    обязательства:долг:кто-то
    актив:наличные 42.0

    2038-01-01 дал в долг
    актив:долг:кто-то-ещё
    актив:наличные -42.0

    ОтветитьУдалить
  21. интересно, не знал, что можно в командной строке вести бухучет, н мне этои не особенно нужно, так как я использую для ведения бухгалтерии онлайн сервис «Моё дело», на нем автоматически рассчитываются налоги и взносы (на
    основании Ваших данных о сотрудниках, доходах и расходах) и платежные документы
    полностью заполнены, так что на нем очень удобно работать с финансами своего предприятия.

    ОтветитьУдалить