[2026-06-28] eagle: personal/projects/budget-app/index.md

This commit is contained in:
Alexey Martemyanov
2026-06-28 12:21:09 +06:00
parent 93622ebf7e
commit 665e1e2365
+28 -10
View File
@@ -455,30 +455,48 @@ API возвращает `t.date.isoformat()` → `2026-05-29T17:00:00`.
Файлы: `frontend/src/pages/Transactions.vue`, `Accounts.vue`, `TaxRecords.vue` — каждая содержит `CURRENCY_SYMBOLS` маппинг и функцию `getCurrencySymbol`/`currencySymbol`.
### Страница быстрого ввода наличных
### БД: исправление типа кредиток
Четыре кредитных счета были ошибочно импортированы как `type='debit'` вместо `type='credit'`. Исправлено вручную:
```sql
UPDATE account SET type = 'credit' WHERE name ILIKE '%кредитка%';
```
Затронуты: Альфа Кредитка, Сбер Кредитка, ВТБ Кредитка, Тинькофф Кредитка.
Модель `AccountType` поддерживает `credit` с самого начала — это была неточность импорта из Excel.
### Страница быстрого ввода наличных — CashInput (2026-06-23)
**Файл:** `frontend/src/pages/CashInput.vue`
**Маршрут:** `/cash`
**Хедер:** скрыт на этой странице (App.vue проверяет `route.name === 'CashInput'`)
Одна страница с двумя режимами, переключаемыми сегмент-кнопкой:
Одна страница с двумя режимами, переключаемыми сегмент-кнопкой.
**Режим «Расход» (по умолчанию):**
- Выбор наличного счёта (type=cash) — чипами, последний сохраняется в localStorage
- Поле суммы (крупное, центрированное)
- Чипы с топ-категориями наличных расходов (Grocery, Рестораны, Стройка, Быт/Техника, Дети, Отдых, Медицина, Авто, Транспорт/АЗС, Жена, Одежда, Кредиты, Квартплата, Аренда, Прочее)
- Кнопка «Другое» → раскрывающийся список всех остальных категорий по группам
- Выбор наличного счёта (type=cash) — чипами, последний сохраняется в `localStorage` под ключом `cash_last_account_id`
- Поле суммы (крупное, центрированное, автофокус)
- Чипы с топ-категориями наличных расходов (15 штук, по частоте из БД):
🛒 Grocery, 🍣 Рестораны, 🛠️ Быт/Техника, 🧱 Стройка, 🧸 Дети, 🏖️ Отдых, 💊 Медицина, 🚙 Авто, ⛽️ Транспорт/АЗС, 👰‍♀️ Жена, 👚 Одежда, 💷 Кредиты, 📟 Квартплата/Связь, 🏢 Аренда, Прочее
- Без кнопки «Другое» — все уникальные категории уже в списке, других нет в БД
- Опциональный комментарий
- POST /api/transactions (source_account → NULL)
**Режим «Обмен валюты»:**
- Селекты счёт-источник / счёт-получатель (фильтр: другая валюта)
- Сумма (отдаю), Курс, Получу — три поля с двусторонним пересчётом:
- меняешь сумму → получу = сумма * курс
- меняешь курс → получу = сумма * курс
- меняешь получу → курс = получу / сумма
- Сумма (отдаю), Курс, Получу — три поля с двусторонним пересчётом (через `_updating` флаг для защиты от циклов):
- меняешь сумму → `получу = сумма * курс`
- меняешь курс → `получу = сумма * курс`
- меняешь получу → `курс = получу / сумма`
- Комментарий (предзаполнен «Обмен валюты»)
- POST /api/transactions (source → dest с cross_rate)
**Технические детали и исправления, которые были сделаны:**
1. **Дата** — `new Date()` форматируется как `YYYY-MM-DDTHH:mm` (локальное время без TZ и миллисекунд). Через `localNow()` helper. Это критично: `new Date().toISOString()` даёт UTC c `Z`, что падает на бэкенде (`can't subtract offset-naive and offset-aware datetimes` — Pydantic парсит как offset-aware, а SQLAlchemy вставляет в `TIMESTAMP WITHOUT TIME ZONE`).
2. **Чипы — `type="button"`** — все `<button>` внутри `<form>` явно имеют `type="button"`, иначе клик по чипу триггерит `submit` формы из-за дефолтного `type="submit"`.
3. **Очистка error** — `error.value` обнуляется при выборе категории, счёта, переключении режима.
4. **Дубликаты категорий** — в БД 34 строки на 17 уникальных категорий (видимо импорт задвоил). `topCats` использует дедупликацию по id через `Set`.
5. **Хедер скрыт** — навигация не показывается на странице `/cash` (App.vue: `<header v-if="!hideHeader">`).
### Пароль
- `admin123` — совпадает с `ADMIN_PASSWORD` в `.env`