Files
obsidian-vault/personal/projects/budget-app/excel-balances.md
T

71 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Остатки счетов из Excel (Budget.xlsx)
Файл: `~/Downloads/Budget.xlsx`
Лист: `транзакции`
Балансы **совпадают** с API после фиксов (2026-06-23).
| Счёт | Баланс | Валюта | Последняя операция |
|---|---|---|---|
| Нал RUB | 815 555.70 | RUB | 2025-05-16 (R6029, 60 000 deb) |
| Нал KGS | 1 794.00 | KGS | 2025-06-17 (R6042, deb) |
| Нал KZT | -22 820.00 | KZT | 2024-12-15 (R5505, deb) |
| Нал USD | 1.00 | USD | 2025-02-04 (R5976, deb) |
| Нал AED | 0.00 | AED | 2023-11-16 (R2335, deb) |
| Нал EUR | — | EUR | нет операций |
| Нал UZS | 18 000.35 | UZS | 2024-03-31 (R3337, deb) |
| Demir ИП | 192 308.54 | KGS | 2025-01-31 (R5943, deb) |
| Demir ИП USD | 284 842.96 | USD | 2026-05-29 (R6053, cred) |
| Demir KGS | 96 013.12 | KGS | 2025-01-31 (R5947, deb) |
| Demir USD | 3 394.29 | USD | 2025-01-31 (R5950, cred) |
| Тинькофф Black | 521 263.65 | RUB | 2025-01-31 (R5959, deb) |
| Тинькофф Кредитка | 7 170.17 | RUB | 2025-01-28 (R5901, deb) |
| Сбер | 266 905.98 | RUB | 2025-01-28 (R5898, deb) |
| Сбер Кредитка | 3 059.00 | RUB | 2025-01-31 (R5946, deb) |
| Альфа | 78 030.00 | RUB | 2025-01-28 (R5925, cred) |
| Альфа Кредитка | 0.50 | RUB | 2025-01-28 (R5924, deb) |
| ВТБ | 265 178.95 | RUB | 2025-01-27 (R5887, deb) |
| ВТБ Кредитка | 297 189.00 | RUB | 2025-01-31 (R5952, deb) |
| Райффайзен | — | RUB | нет операций |
## Формула API
`balance = incoming_transfer + incoming_income - outgoing + initial_balance`
Где:
- `incoming_transfer``SUM(cross_rate * amount)` где source IS NOT NULL (cross_rate конвертирует валюту source в валюту dest)
- `incoming_income``SUM(amount)` где source IS NULL (amount уже в валюте счёта, cross_rate — только для отчёта)
- `outgoing``SUM(amount)` (всегда в валюте счёта-источника)
## Фиксы (2026-06-23)
### 1. incoming для income и transfer — разный расчёт
Было: `incoming = SUM(COALESCE(cross_rate, 1.0) * amount)` — cross_rate применялся ко всем включая income (где amount уже в валюте счёта). Для KGS-счетов с income-пополнениями (например "Конвертация USD по курсу 87") incoming умножался на 87, давая баланс ×87.
Стало: incoming разделён на две части:
- `incoming_transfer (source IS NOT NULL)`: cross_rate применяется (конвертирует валюту source→dest)
- `incoming_income (source IS NULL)`: просто amount (cross_rate — только для отчётной валюты)
### 2. import_hash и on_conflict_do_nothing — удалены
Было: дедупликация по `import_hash = SHA256(date|amount|source|dest|comment)`. В Excel есть 141 дублирующаяся строка с одинаковыми этими полями (реальные повторные списания). `on_conflict_do_nothing` молча пропускал их, но `tx_count` врал что импортировал.
Стало: обычный `session.add(tx)`. Колонка `import_hash` и уникальный индекс дропнуты из таблицы. Функция `_make_import_hash` удалена.
### 3. Accounts — идемпотентность
Было: каждый запуск импорта создавал 20 новых аккаунтов (session.add). После нескольких запусков — 40+ аккаунтов с разными UUID, транзакции привязаны к разным наборам.
Стало: UPSERT — ищет существующий account по `name + user_id`, переиспользует.
### 4. UserSettings — UPSERT
Было: `session.add(UserSettings(...))` — падало с UniqueViolation при повторном запуске.
Стало: `pg_insert(...).on_conflict_do_update(...)`.
### 5. Нюанс Excel col I/L
Для некоторых строк Excel не кеширует вычисленные значения col I (остаток деб) — показывает None. Это не баг, а особенность data_only=True — если Excel не пересчитал формулы перед сохранением, кеш пуст. В таких случаях последний корректный баланс берётся из предыдущей строки минус amount.