Telegram-бот для двоих: баланс месяца, траты с автокатегориями, выписки по каждому, учёт долгов. Python 3.10+, без внешних зависимостей, база SQLite. Суммы хранятся в копейках (целые числа) — расчёты точные, без плавающей точки.
Внизу чата постоянные кнопки: 💰 Баланс · 📋 Выписка · 💳 Долги · ❓ Помощь.
ты: 450 такси
бот: ➖ 450 ₽ — такси
🚕 Транспорт · Саша
📊 За сентябрь: расходы 45 200 ₽ · остаток +104 800 ₽
[✏️ Категория] [🗑 Удалить]
Порядок неважен (такси 450 тоже работает), понимает 1 200, 210.000, 1,5к, 40 тыс, 2 млн, знак рубля после суммы (450₽, 300 руб).
Ведущие дефисы и маркеры списка (- еда) отбрасываются, так что скопированный список работает как есть.
Несколько трат в одном сообщении: каждая с новой строки или через запятую (49 самокат, 215 кофе) — на каждую своя карточка. Строки без суммы бот перечислит отдельно.
Внизу каждой карточки — семейный итог месяца на момент записи.
Категория ставится сама. Если не угадал — жмёшь «✏️ Категория», выбираешь свою, и бот запоминает: в следующий раз «вкусвилл» сам ляжет в Продукты.
Ответ (reply) на карточку словом удали удаляет запись, верни возвращает удалённую.
Второму супругу прилетает такая же карточка операции (с пометкой, кто внёс). Карточка живая: при любой правке (сумма, описание, категория, владелец, удаление) она перерисовывается у обоих, и по зеркальной карточке тоже можно ответить (reply), чтобы поправить запись.
ты: +150000 зарплата (или: аванс 40к)
бот: 💵 Доход 150 000 ₽ — зарплата
Кнопки под сообщением переключают вид: вся семья или по одному (так же, как в выписке).
💰 Сентябрь 2026 · вся семья
Доходы: 150 000 ₽
Расходы: 45 200 ₽
Остаток: +104 800 ₽
По людям:
Саша: доходы 150 000 ₽, расходы 30 000 ₽
Аня: доходы 0 ₽, расходы 15 200 ₽
💳 Открытых долгов: 2 на 340 000 ₽
[◀️ Август] [Октябрь ▶️]
Сверху переключатели Вся семья / Саша / Аня и стрелки по месяцам — одно сообщение, которое перерисовывается кнопками, чат не засоряется.
📋 Выписка · Сентябрь 2026 · вся семья
Доходы 150 000 ₽ · Расходы 45 200 ₽
Расходы по категориям
🛒 Продукты — 18 300 ₽ (40%)
🚕 Транспорт — 4 200 ₽ (9%)
...
Последние операции
01.09 · Саша · −450 ₽ · такси
ты: долг Иван 50000 за ремонт
бот: 💳 Записал долг: Иван — 50 000 ₽ (ремонт)
ты: погасил Иван 10000
бот: ✅ Погашение по «Иван»: 10 000 ₽
Осталось: 40 000 ₽ из 50 000 ₽
Кнопка «💳 Долги» показывает все открытые долги с остатком и процентом погашения, под каждым — кнопка «➖ Погасить» (спросит сумму). Когда остаток доходит до нуля — долг закрывается сам, с праздничным сообщением. Переплата невозможна: платёж больше остатка записывается ровно на остаток, бот об этом предупреждает.
- Все суммы — целые копейки, никакого float.
- Итоги (баланс, категории, по людям) считает SQL по базе при каждом запросе — нет накапливаемых счётчиков, которые могут разойтись с данными.
- Удалённая операция помечается флагом (не стирается) и исключается из всех сумм.
- Месяц операции фиксируется по Москве в момент внесения.
- Остаток долга = исходная сумма − сумма всех платежей, тоже считается по базе.
test_bot.py— ~150 проверок: разбор сумм, форматирование, категории, суммы месяца (в т.ч. «сумма по людям = общей», «сумма категорий = расходу»), долги, обучение категорий. Все проходят.
- Доступ: первые двое написавших боту привязываются, остальным отказ (лимит меняется переменной
FIN_MAX_USERS). - Имя в отчётах берётся из Telegram, меняется командой
/имя Аня. - Погашение долга — отдельная запись, не попадает в расходы месяца автоматически (иначе задвоение, если платёж уже внесён как трата). Если нужно наоборот — скажи.
- Удалять — кнопкой 🗑 на карточке или ответом
удали; вернуть — ответомвернина удалённую карточку.
finbot/
__main__.py точка входа: long polling, цикл обновлений
handlers.py обработка сообщений и кнопок
cards.py отрисовка карточек, баланса, выписки, долгов
parsing.py разбор фраз (траты, долги, правки) — чистые функции
money.py разбор сумм («1,5к» → 150 000 коп.) и форматирование
categories.py 14 категорий + словарь ключевых слов
db.py SQLite: операции, долги, платежи, журнал правок
dates.py месяцы, московское время
telegram.py обёртка над Bot API (stdlib, без зависимостей)
backup.py ночной бэкап базы (sqlite backup API)
test_bot.py проверки расчётов: python3 test_bot.py
- В BotFather:
/newbot→ получить токен. TG_TOKEN=<токен> python3 -m finbot
На сервере: systemd-сервис family-finance-bot, деплой — git push с рабочей машины,
затем на сервере git pull и systemctl restart family-finance-bot.
База finance.db и файл env с токеном лежат в корне рядом с пакетом и в git не попадают.