--- name: budget-current-plan description: Актуальный бизнес-процесс фичи «Бюджет» — версия после полного сброса проекта (см. ниже "Второй урок"); не путать со старым бюджет_проект_план.md (2006 год, источник идей, не требований) metadata: type: project --- Старый файл `бюджет_проект_план.md` — заметки 2006 года, источник идей, не требований. Этот файл — то, что реально подтверждено в разговоре. **Актуальна только эта версия** — предыдущая версия этого же файла (обсуждение копилок/целей ДО того, как весь проект снесли и начали заново) частично устарела, см. "Второй урок" ниже про то, почему. ## Продукт Личный (не мульти-пользовательский) трекер бюджета — один человек ведёт свой бюджет. `users` всё же нужна (не совсем однопользовательский в смысле схемы БД) — счета/категории/транзакции ссылаются на `user_id`, без этого пришлось бы возвращаться к вопросу при первом же втором пользователе. ## Users `id`, `login`, `password`, `name`, `email`, `date_add`, `last_login`. Пока достаточно. ## Accounts (счета) Три типа `type_acc`: - **`cash`** — кошелёк (наличные). - **`bank`** — счёт в банке; карта просто привязана к нему, сама по себе денег не хранит (это сознательное упрощение — раньше в модели были отдельные "дебетовая карта"/"кредитная карта"/ "е-money" и т.п., это НЕ подтверждено заново после сброса, убрано). - **`savings`** — копилка: тот же счёт, но с процентом на остаток (история ставок — отдельная таблица, привязанная к `account_id`). Опционально может иметь цель (см. `goals` ниже) — если записи в `goals` нет, это просто копилка "без цели", копишь под процент без конкретной суммы/даты. Поля: `id`, `user_id`, `type_acc`, `title`, `summa` (баланс), `is_delete` (архивация вместо удаления), `order`. ## Categories (статьи) — с подкатегориями `id`, `user_id`, `parent_id` (null — категория верхнего уровня; иначе — id родителя), `title`, `type` (`income`/`expense`), `order`. Пример: «Продукты» — родительская категория, «Алкоголь» — подкатегория внутри неё. Транзакция привязывается к конкретной (под)категории. В отчёте можно смотреть по родителю целиком (сумма всех подкатегорий) или провалиться в конкретную подкатегорию отдельно. ## Transactions `id`, `user_id`, `categorie_id`, `account_f_id` (откуда), `account_in_id` (куда), `date`, `summa`, `type` (`income`/`expense`/`transfer`). Для дохода — только `account_in_id`, для расхода — только `account_f_id`, для перевода — оба. **Обычный transfer между обычными счетами — без категории** (пример: переложил 3000 ₽ с карты в кошелёк — деньги не потрачены и не заработаны, просто переехали, категория тут не имеет смысла). **⚠️ ОТКРЫТЫЙ ВОПРОС — transfer на savings-счёт (пополнение копилки/цели) МОЖЕТ иметь категорию**, и пользователь хочет, чтобы такой transfer засчитывался как "потрачено" по этой категории в план/факт бюджета — то есть отложил 10 000 ₽ в копилку «Отпуск» в январе → сразу считается "потрачено 10 000 на Отпуск" в январском бюджете, ещё до самой поездки. Нерешённая проблема с этим: когда деньги реально тратятся (сама поездка — гостиница, билеты), если те траты ТОЖЕ пометить категорией «Отпуск» — сумма задвоится (одни и те же деньги посчитаны и при откладывании, и при реальной трате). Пользователь сказал «я подумаю» — **решение пока не принято**, не проектировать/не кодировать эту часть, пока не будет ответа. Варианты, которые обсуждались (но не выбраны): (а) реальные траты в момент поездки НЕ помечать той же категорией, раз уже засчитано при откладывании; (б) какой-то другой механизм анти-задвоения. ## Budgets (план/факт) `id`, `categorie_id`, `plan_summ`, `year`, `month`, `type`. План — вручную на месяц по категории; факт — не хранится, считается на лету как сумма `transactions` по этой категории за месяц (с учётом открытого вопроса выше — возможно, включая помеченные transfer на копилки). ## Account_rates (история ставок) `id`, `account_id`, `rate_percent`, `valid_from`, `valid_to` (null = текущая). Общая механика для `savings`, с расчётом на будущее переиспользование для кредита (там % работает в другую сторону — не начисление, а долг — но структура «ставка + период» та же). Кредит сейчас вне скоупа. ## Goals (цель для копилки) `id`, `account_id`, `target_summa`, `deadline`. Необязательная надстройка над `savings`-счётом. Прогноз «сколько класть в месяц» считается на лету по ТЕКУЩЕЙ ставке (не хранится), в предположении, что она не изменится до дедлайна; пересчитывается при просмотре/смене ставки. **Проценты, начисленные на копилку** — `income`-транзакция на счёт-копилку с одной системной категорией «Проценты по вкладам/целям» (одна на все копилки, не по одной на каждую) — заводится пользователю автоматически при первом использовании. ## Приоритет фич 1. **Цели (план/факт) + анализ бюджета** — сейчас. 2. **Инвестиции** (вклады/акции/облигации) — следующий слой, схему делать с запасом. 3. **Кредиты** — отложены, но `account_rates` намеренно универсальна для переиспользования позже. ## Второй урок (почему эта версия файла переписана) После того как весь код/схема домена бюджета были снесены "с нуля" по прямому требованию пользователя, я в следующем же заходе молча притащил старые выводы из ПРЕДЫДУЩЕЙ версии этого файла (users, accounts, categories, transactions, budgets) как будто они уже согласованы — хотя после сброса заново обсуждались только копилки/цели. Пользователь: «про пользователя мы ничего не обсуждали, про бюджет мы ничего не обсуждали... ОТКУДА БЛЯДЬ???». **Урок: "сохранено в памяти" ≠ "можно молча переиспользовать после полного сброса"** — если проект/фичу explicitly снесли и просили начать заново, каждое решение переподтверждается в текущем разговоре заново, даже если оно дословно совпадёт с тем, что уже было записано. Ссылаться на память можно только явно и открыто ("вот что записано, актуально ли?"), не молча вставлять в предложение как решённое. **How to apply**: перед тем как писать `schema.sql`/контроллеры/репозитории — свериться с этим файлом **и убедиться, что каждый пункт был реально произнесён в текущем контексте разговора**, а не просто существует здесь с прошлого раза. Новые уточнения — дописывать сюда сразу.