Привет, Хабр! На связи Игорь Батулин — руководитель группы разработки виртуального хостинга в Рунити. Недавно в другой статье я рассказывал, как написал приложение для поиска маршрута в рогейне — делал его для себя, чтобы ориентироваться на дистанции. Опыт оказался удачным, и я продолжил собственную разработку — решил разобраться с личными финансами. 

В статье — мой опыт создания бота для учета личных расходов. Проект был остановлен, когда выполнил свою задачу, — дальше развивать его просто не было смысла. Зато в процессе стало ясно, что принципы, знакомые мне по командной разработке, отлично работают и в личных проектах. Итерации, декомпозиция и готовность к изменениям оказались полезны и здесь. Об этом я тоже расскажу — без методологий и фреймворков, зато на личном примере.

Навигация по тексту:

Как неожиданные открытия заставили задуматься о финансовой грамотности 

Каждый год мы с семьей участвуем в соревнованиях по спортивному ориентированию — рогейне. Помимо самих стартов там обычно проходят и образ��вательные мероприятия. На одном из таких событий я попал на лекцию по финансовой грамотности, где прозвучала мысль, которая мне запомнилась: люди, которые начинают фиксировать свои расходы, в среднем сокращают траты на 5–10 % без каких-либо ограничений в повседневной жизни.

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

Эволюция решений: от базовой таблицы до первой итерации приложения

Начали с самого простого — обычной электронной таблицы. Собирали чеки и вручную заносили туда расходы. Параллельно я изучал готовые приложения для учета: их оказалось много, но ни одно не подходило нам на 100%. 

Сначала таблицы хватало. Но довольно быстро стало ясно, что вручную записывать все траты неудобно. Часть покупок хотелось фиксировать сразу, часть — добавлять позже, а со временем появилась идея как-то упростить этот процесс. Из-за этого данные начали попадать в таблицу разными способами и в разное время. Но в какой-то момент стало очевидно: без понятного формата записей и простых правил изменений даже обычная таблица начинает ломаться — данные перезаписываются, появляются ошибки. Тогда мы перешли к совместной таблице с более жесткой структурой. Форму записей пришлось пересмотреть так, чтобы позже можно было подключить автоматический или полуавтоматический ввод данных.

Уже на первых шагах стало понятно, что крупные категории расходов неудобно автоматизировать. Их приходилось дробить, потому что данные быстро становились неточными. Чтобы не переделывать всё каждый раз, мы заранее договорились о едином формате записей. Это позволило добавлять новые способы ввода и менять логику обработки расходов, не трогая уже внесенные данные.

В итоге мы привели все записи к одному виду и вынесли «сырые» данные на отдельный лист. Оттуда они попадали на лист с классификацией. Все расходы стали вестись единым списком в общем формате. Для этого добавили одинаковые категории («Подарки», «Хозтовары», «Еда», «Платежные системы») и подкатегории с детализацией, а также поле с датой расхода, чтобы точно фиксировать момент покупки.

Скриншот нашей таблицы с расходами за декабрь 2023 года
Скриншот нашей таблицы с расходами за декабрь 2023 года

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

Поэтому на этом этапе в архитектуре было важно несколько вещей:

  • фиксированная схема обмена данными (единый формат строк в таблице);

  • воз��ожность расширять структуру без пересборки всего решения (добавлением столбцов);

  • независимость способа ввода данных (вручную, через бота, позже — через код);

  • возможность обрабатывать данные разными инструментами — формулами, скриптами или внешним кодом;

  • несколько вариантов представления результатов — от таблиц до графиков.

Благодаря этому мы могли спокойно менять категории, добавлять новые способы записи расходов и не бояться потерять или исказить внесенные ранее данные.

Примерно через месяц ведения записей стало понятно, что первоначальная схема категорий не работает. Часть категорий оказалась лишней, а другие, наоборот, требовали большей детализации. Из-за этого пришлось пересмотреть структуру и перенести уже внесенные данные на новую схему. Заодно выяснилось, что для части расходов изначально не хватало нужной информации, и ее пришлось добавлять задним числом.

При необходимости можно было просто добавить новый столбец и начать заполнять его для новых записей. А старые данные, при желании, дополнить позже. Это позволяло менять схему без переделки всей таблицы.

Бот: начало и первые шаги к автоматизации

Параллельно с переработкой структуры я начал думать об автоматизации. Иногда чек просто невозможно получить, и такие покупки мы сначала записывали в отдельный общий канал в Telegram, а потом вручную переносили в таблицу.

В какой-то момент стало очевидно, что этот промежуточный шаг лишний. Проще сразу вносить все расходы через Telegram — в одном месте, в удобном формате. Так появилась идея бота: он принимал записи, а дальше данные можно было обрабатывать и добавлять в таблицу. Уже на этом этапе было понятно, как такой подход можно постепенно развивать и дополнять.

Представил все варианты возможного развития продукта, с учетом гибкости и универсальности:

1. Любой способ внесения исходных данных:

  • ввод вручную, текстом в файл;

  • сообщением в Telegram-боте или Telegram-канале;

  • со своего мобильного приложения (если его со временем сделаю);

  • с компьютера (через веб-сайт);

  • голосом через навык голосового помощника (если такой навык сделаю);

  • фотографией чека;

  • e-mail с чеком;

  • со стороннего сервиса или приложения (если там будет экспорт).

2. Возможность обрабатывать и подготавливать эти «сырые» данные:

  • отделяя товар и сумму в сообщении;

  • расшифровывая сокращения;

  • конвертируя валюту;

  • классифицируя товар по категориям;

  • дополняя/обогащая тегами;

  • поиск таких же товаров дешевле, в соседних магазинах для вычисления «потенциальной переплаты»;

  • анализ при помощи LLM.

3. Разные варианты хранения/экспорта журнала:

  • стандартная база данных внутри;

  • либо доступное хранилище в облаке (с возможностью доступа из других приложений);

  • удобный экспорт данных в любой стандартный формат;

  • в идеале доступ по API для перспектив расширения.

4. Гибкое/настраиваемое отображение:

  • просмотр через MS Excel и электронные документы;

  • удобный интерфейс для построения отчетов;

  • либо просто набор готовых отчетов, в котором есть все нужные;

  • озвучивание отчета через навык голосового помощника (если его сделаю);

  • отправка в Telegram с картинками и пояснениями.

Самой важной «болью» было внесение и классификация данных. И, если последнее еще можно сделать автоматически, то внесение информации требовало регулярных действий. В идеале представлял продукт в виде мобильного приложения с тремя кнопками в интерфейсе для ввода данных:

  • сделать фото чека;

  • внести голосовую заметку;

  • ввести текстом с клавиатуры: поле ввода + кнопка.

Изначально хотелось, чтобы голосовой ввод работал привычно: после диктовки текст отображался для проверки и правок, а затем сохранялся. Такой сценарий проще всего реализовать в отдельном приложении. Но на практике стало ясно, что для первых шагов этого не требуется. Telegram уже дает нужный набор возможностей: ввод текста, голосовые сообщения и отправку фотографий. Работать с этими данными по API несложно — голос легко расшифровывается, а изображения чеков поддаются распознаванию.

Это решение менее удобно, чем отдельное приложение, зато его можно было реализовать быстрее и с минимальными затратами. Поэтому на этом этапе я остановился на Telegram-боте.

Бот: реализация и инженерные принципы, которые всплыли в процессе

На этапе автоматизации я сразу смотрел в сторону Telegram-бота — не как идеального интерфейса, а как самого дешевого и быстрого способа проверить гипотезу. В одном месте уже есть ввод текста, голосовые сообщения и отправка изображений, а API позволяет без лишней инфраструктуры принимать и обрабатывать данные.

Аналогично и с инфраструктурой: код бота работал на shared-хостинге. Это было осознанное упрощение — не как рекомендация для продакшена, а как способ минимизировать накладные расходы и сосредоточиться на логике обработки данных, а не на развертывании окружения. Такое решение накладывает ограничения, но для задачи прототипирования и первых итераций они оказались приемлемыми.

Для работы с Telegram я сознательно не использовал сторонние библиотеки. Bot API позволяет напрямую отправлять и принимать сообщения через HTTP-запросы, без дополнительного слоя абстракций, а для прототипа этого оказалось достаточно. Отправка сообщений сводится к обычному HTTP-запросу, а входящие данные Telegram передаёт на webhook в формате JSON.

Telegram Bot API достаточно простой и прозрачный: для отправки сообщения не требуется ни SDK, ни дополнительной инфраструктуры — достаточно обычного HTTP-запроса. Например, сообщение от бота можно отправить прямо из браузера, сформировав URL вида:

https://api.telegram.org/bot1234567:SoMe-ToKen-Ku909d/sendMessage?chat_id=1234567&text=Текст+вашего+сообщения

На первом этапе я ограничился самым простым вариантом: бот принимал сообщения и сохранял их в лог-файл. Этого было достаточно, чтобы проверить прием и обработку данных, но такой подход не решал основную задачу — учет и анализ расходов. Поэтому следующим шагом стало добавление записей напрямую в таблицу. Для тестирования я сделал копию рабочей таблицы и подключил ее к скрипту. Здесь сразу проявились организационные ограничения: при одновременном внесении данных вручную и через бота возникали конфликты записи, а также потребовалось явно помечать источник каждой записи. Маркировка решалась добавлением отдельной колонки, а вот с синхронизацией параллельных записей пришлось повозиться.

Отдельным этапом стала автоматическая классификация расходов. Сначала она работала на простом словаре ключевых слов, затем добавили эвристики с учетом их веса, и только после этого подключили ИИ по API. На тот момент возможностей открытых моделей хватало лишь для классификации, а дальнейшее развитие упиралось в ограничения и стоимость использования API. 

Итоговые сводки и отчеты продолжали строиться в Google Таблицах. Я рассматривал вариант вынести визуализацию в отдельный интерфейс с графиками и последующей интеграцией в мобильное приложение, но на этом этапе практической необходимости в этом не возникло. Также появлялись идеи расширения функциональности — например, список покупок или привязка цен к магазинам. Однако их ценность для основной задачи оказалась невысокой. Кроме того, подобные решения уже существуют в готовом виде. 

Пример сводки повседневных расходов по категориям
Пример сводки повседневных расходов по категориям

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

Выводы и итоги

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

По результатам работы для меня оказались важны несколько простых принципов:

  • разделение логики на независимые части;

  • минимальные связи между этими частями;

  • простые и устойчивые форматы данных;

  • хранение данных в максимально «сыром» виде с возможностью дальнейшей обработки;

  • построчный текстовый формат как долгоживущая модель хранения;

  • ручная реализация части логики на ранних этапах для проверки идей;

  • развитие решения небольшими шагами с понятным результатом.

Эти принципы не привязаны к конкретным фреймворкам или методологиям, но именно они позволили проекту спокойно развиваться и адаптироваться к изменениям без жестких переделок.

Когда минимально необходимый функционал был готов, я остановил развитие проекта. Задача, ради которой он начинался, была решена, а дальнейшие доработки не давали новых инженерных или продуктовых наблюдений. Со временем появились готовые приложения с тем же набором возможностей, а на практике оказалось, что самостоятельная фиксация расходов работает эффективнее полностью автоматизированных решений.

Отдельно стало понятно, что сегодня подобный прототип можно собрать значительно быстрее. Современные ИИ-модели позволяют получить базовый рабочий код за несколько итераций, поэтому ценность дальнейшего развития проекта в его исходном виде снизилась.

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

  • экономия на повседневных расходах на еду почти не дает эффекта;

  • расходы на обслуживание автомобиля допускают разумную оптимизацию;

  • строительные и ремонтные работы требуют постоянного контроля, так как незаметно формируют значительную долю бюджета;

  • ручная фиксация и последующий анализ данных остаются самым надежным способом контроля расходов.

Что дальше?

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

Есть и более прикладные идеи. Например, автоматизация части рутинных операций при продаже вещей на Авито — от оценки и публикации объявлений до ответов на типовые вопросы покупателей. Если такой сценарий даст новые инженерные наблюдения, его имеет смысл развивать дальше. ИИ в этих экспериментах рассматривается как вспомогательный инструмент, чтобы упростить отдельные этапы работы. Остальные идеи остаются в бэклоге и будут развиваться только при наличии практической пользы.

А вы используете собственные решения, чтобы упростить рутинные задачи? Поделитесь в комментах успешными и не очень кейсами!