Files
FamilyHUB/docs/finance_module_specification.md
T

370 lines
8.9 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.
# 📘 Финансовый модуль
## 1. Общее описание
Финансовый модуль предназначен для учёта:
- доходов
- расходов
- категорий
Поддерживает три способа ввода расходов:
1. Ручной ввод
2. Ввод номера и даты чека
3. Загрузка фото чека
---
## 2. Глоссарий
**Доход (Income)**
Денежное поступление (зарплата, перевод, подарок и т.д.)
**Расход (Expense)**
Факт траты денег
**Категория (Category)**
Классификация доходов и расходов (например: еда, транспорт, зарплата)
**Чек (Receipt)**
Документ, содержащий информацию о покупке (дата, позиции, сумма)
**Позиция (Position)**
Отдельная строка в чеке (товар или услуга)
---
## 3. Доменная модель
### 3.1 Positions
```
positions (
id,
receipt_number,
operation_date,
gtin_code,
product_name,
product_count,
amount,
discount,
name_spd,
category_id,
family_id,
family_member_id,
created_at,
updated_at
)
```
**Описание полей:**
- `receipt_number` — номер чека (nullable для ручного ввода)
- `operation_date` — дата операции
- `gtin_code` — код товара
- `product_name` — название товара
- `product_count` — количество
- `amount` — сумма позиции
- `discount` — скидка
- `name_spd` — продавец
- `category_id` — категория
- `family_id` — семья
- `family_member_id` — участник
---
### 3.2 Receipts
```
receipts (
id,
receipt_number,
ui,
status,
issued_at,
total_amount,
payment_amount,
cash_amount,
another_amount,
clearing_amount,
margin,
currency,
payment_type,
cashbox_number,
cashier,
name_spd,
name_to,
name_np,
type_np,
street_to,
house_to,
kod_soato,
oblast_soato,
rayon_soato,
selsovet_soato,
doc_num,
skno_number,
unp,
success,
family_id,
family_member_id,
created_at
)
```
**Описание:**
- хранит агрегированную информацию о чеке
- используется при сканировании QR
- связывается с positions через `receipt_number`
---
### 3.3 Categories
```
categories (
id,
name,
type,
family_id,
family_member_id,
created_at
)
```
**Описание полей:**
- `type` — income | expense
- категория принадлежит семье
---
## 4. Бизнес-логика
### 4.1 Добавление расхода вручную
- пользователь вводит:
- сумму
- описание
- категорию
- создаётся запись в `positions`
- `receipt_number = NULL`
---
### 4.2 Добавление дохода
- аналогично расходу
- используется категория типа `income`
---
### 4.3 Добавление расхода по номеру и дате чека
#### Поток:
1. Пользователь вводит номер и дату чека
2. Backend получает данные чека через внешний сервис
3. Создаётся запись в `receipts`
4. Создаётся связанная транзакция в `transactions`
5. Для каждой позиции создаётся запись в `positions`
---
### 4.4 Добавление расхода по фото чека
#### Поток:
1. Пользователь загружает фото чека
2. Backend извлекает текст через OCR
3. Backend извлекает из текста номер и дату чека
4. Backend получает данные чека через внешний сервис
5. Создаётся запись в `receipts`
6. Создаётся связанная транзакция в `transactions`
7. Для каждой позиции создаётся запись в `positions`
---
## 5. Потоки
### Ручной ввод
```text
User → API POST /transactions → transactions
```
### Доход
```text
User → API POST /transactions → transactions
```
### Чек по номеру и дате
```text
User → API POST /transactions → receipt provider → receipts + positions + transactions
```
### Чек по фото
```text
User → API POST /transactions multipart/form-data → OCR → receipt provider → receipts + positions + transactions
```
---
## 6. API (черновик)
### Создание транзакции вручную
```http
POST /api/v1/transactions
Content-Type: application/json
```
```json
{
"family_id": 1,
"created_by": 2,
"type": "expense",
"category": "groceries",
"amount": 1000,
"description": "Продукты",
"datetime": "2026-01-21T10:11:12Z"
}
```
---
### Создание транзакции по номеру и дате чека
```http
POST /api/v1/transactions
Content-Type: application/json
```
```json
{
"family_id": 1,
"created_by": 2,
"receipt_number": "0123456789ABCDEFGHIJKLMN",
"receipt_date": "21.01.2026"
}
```
---
### Создание транзакции по фото чека
```http
POST /api/v1/transactions
Content-Type: multipart/form-data
```
Поля формы:
- `photo` — файл изображения чека, обязательно
- `family_id` — ID семьи, обязательно
- `created_by` — ID пользователя, обязательно
- `type` — тип транзакции, опционально, по умолчанию `expense`
- `category` — категория, опционально, по умолчанию `receipt`
- `description` — описание транзакции, опционально
---
### Получение транзакций
```http
GET /api/v1/transactions
```
Фильтры:
- дата
- категория
- тип
- family_id
---
### Правила для `POST /api/v1/transactions`
Используется ровно один сценарий создания:
1. Ручная транзакция:
обязательны `family_id`, `created_by`, `type`, `category`, `amount`, `datetime`
2. Транзакция по чеку:
обязательны `family_id`, `created_by`, `receipt_number`, `receipt_date`
3. Транзакция по фото:
обязательны `photo`, `family_id`, `created_by`
Нельзя смешивать ручные поля транзакции (`amount`, `datetime`, `receipt_id`) с полями чека (`receipt_number`, `receipt_date`) в одном JSON-запросе.
---
## 7. Задачи для разработки
### Этап 1 — База
- [ ] Переписать SQL-миграции (positions, receipts, categories)
---
### Этап 2 — Категории
- [ ] CRUD категорий
- [ ] Валидация типа (income/expense)
---
### Этап 3 — Транзакции
- [x] Endpoint создания транзакции
- [x] Endpoint получения списка
- [ ] Фильтрация
---
### Этап 4 — Доходы/расходы
- [ ] Определение типа через категорию
- [ ] Валидация соответствия
---
### Этап 5 — Чеки
- [x] Endpoint загрузки фото чека через `POST /transactions`
- [ ] Интеграция с сервисом чеков
- [x] Создание receipts
- [x] Создание транзакции по номеру и дате чека
- [x] Создание транзакции по фото чека
- [ ] Создание positions
---
### Этап 6 — Telegram интеграция
- [ ] Команды добавления дохода/расхода
- [ ] Обработка QR
---
### Этап 7 — Дополнительно
- [ ] Автокатегоризация
- [ ] Статистика
- [ ] Лимиты
---
## 8. Архитектурные решения
- Transaction — основная сущность финансов
- Receipt — дополняет транзакцию
- Position - позиции из чека
- Категории определяют тип операции
- Поддержка multi-tenant через family_id
---
## 9. Открытые вопросы
- [ ] Нужна ли мультивалютность?
- [ ] Можно ли редактировать чек?
- [ ] Как обрабатывать ошибки OCR?
- [ ] Нужен ли отдельный endpoint для повторной привязки чека к существующей транзакции?
- [ ] Нужны ли роли внутри семьи?