Initial commit MKD fixes
This commit is contained in:
135
backend/HOW_REPORTS_WORK.md
Executable file
135
backend/HOW_REPORTS_WORK.md
Executable file
@@ -0,0 +1,135 @@
|
||||
# Как работает обработка отчетов из 1С
|
||||
|
||||
## Оборотно-сальдовая ведомость по счету 20
|
||||
|
||||
### Распознавание файла
|
||||
|
||||
Файл `Оборотно_сальдовая_ведомость_по_счету_20_за_2025_г_ООО_Дружба.csv` **автоматически распознается** как `balance_sheet` по ключевым словам в названии:
|
||||
- "оборотн"
|
||||
- "сальд"
|
||||
- "ведомост"
|
||||
|
||||
### Формат CSV (схема колонок и чисел)
|
||||
|
||||
- **Разделитель**: точка с запятой (`;`).
|
||||
- **Кодировка**: UTF-8 (при наличии BOM он автоматически убирается).
|
||||
- **Строки 1–9**: метаданные и заголовки (организация, «Счет, Наименование счета», «Обороты за период», «Статьи затрат» и т.д.). Строка начала данных определяется автоматически (по подстроке «Обороты за период» / «Счет, Наименование» или по первой строке, где в колонке 0 есть текст, а в колонке 3 или 4 — число).
|
||||
|
||||
**Колонки (индексы 0–6):**
|
||||
|
||||
| Индекс | Содержимое |
|
||||
|--------|------------|
|
||||
| 0 | Наименование (адрес дома / номенклатурная группа / статья затрат) |
|
||||
| 1, 2 | Сальдо на начало периода (Дебет, Кредит), часто пусто |
|
||||
| **3** | **Обороты за период — Дебет** (источник расходов по счёту 20) |
|
||||
| 4 | Обороты за период — Кредит |
|
||||
| 5, 6 | Сальдо на конец периода (Дебет, Кредит) |
|
||||
|
||||
**Формат чисел**: пробел — разделитель тысяч, запятая — десятичный знак (например, `2 229,20`). Парсер удаляет пробелы и заменяет запятую на точку.
|
||||
|
||||
**Пример строки данных:**
|
||||
`Булата Имашева 6/1;;;2 229,20;;2 229,20;` — адрес в колонке 0, оборот по дебету (расход) в колонке 3: 2 229,20.
|
||||
|
||||
### Куда сохраняются данные
|
||||
|
||||
1. **Таблица `financial_reports`**:
|
||||
- Запись о загруженном файле
|
||||
- Поля: `id`, `filename`, `file_type`, `uploaded_by`, `status`, `report_type`, `uploaded_at`
|
||||
- Статус: `processing` → `completed` / `partial` / `failed`
|
||||
|
||||
2. **Таблица `building_financial_data`**:
|
||||
- Финансовые данные по каждому дому
|
||||
- Поля:
|
||||
- `building_id` - ID дома из таблицы `buildings`
|
||||
- `report_id` - ID отчета из `financial_reports`
|
||||
- `period_start`, `period_end`, `period_type` - период (извлекается из названия файла)
|
||||
- `total_income` - общий доход
|
||||
- `total_expenses` - общие расходы
|
||||
- `expenses_by_items` - JSONB с разбивкой по статьям: `{"Группа > Статья": сумма}`
|
||||
- `balance` - баланс
|
||||
- `metadata` - JSONB с полной структурой групп и статей
|
||||
|
||||
### Как извлекаются адреса
|
||||
|
||||
Функция `isBuildingAddress()` определяет адрес дома по следующим признакам:
|
||||
- Содержит буквы (название улицы) И цифры (номер дома)
|
||||
- Паттерны: `"6/1"`, `"Булата Имашева 6/1"`, `"Авроры 5/12"`
|
||||
- НЕ является счетом (20, 20.01)
|
||||
- НЕ является статьей затрат
|
||||
|
||||
**Важно**: Чтобы данные по адресу попали в отчёт, адрес из файла должен быть найден в системе. Поиск выполняется в таком порядке:
|
||||
1. Таблица **`doma_address_mappings`** — по нормализованному адресу (LOWER, TRIM) ищется `building_id`. Это позволяет явно связать адрес из 1С/ОСВ (например, «Авроры 5/12», «Булата Имашева 6/1») с домом в системе.
|
||||
2. Таблица **`buildings`** — по полному совпадению `data->'passport'->>'address'`, затем без учёта регистра и пробелов, затем по нормализованному адресу (без «ул.», «д.», запятых), затем по основной части адреса (ILIKE).
|
||||
|
||||
Если дом не найден ни одним способом, данные по этому адресу пропускаются и адрес добавляется в `error_log` отчета.
|
||||
|
||||
### Примеры адресов из файла
|
||||
|
||||
- ✅ **"Булата Имашева 6/1"** - распознается (есть цифры и буквы)
|
||||
- ✅ **"Авроры 5/12"** - распознается (есть цифры и буквы)
|
||||
- ⚠️ **"Зеленая Роща"** - НЕ распознается как адрес дома (нет цифр в первой колонке)
|
||||
- Это может быть участок или комплекс, но не отдельный дом
|
||||
- Если это участок, данные по нему не сохранятся в `building_financial_data`
|
||||
|
||||
### Структура данных в `expenses_by_items`
|
||||
|
||||
```json
|
||||
{
|
||||
"Административно-управленческие расходы > Набор персонала": 805.84,
|
||||
"Административно-управленческие расходы > Налоги": 4416.06,
|
||||
"Текущее обслуживание общедомового имущества > Ремонт кровли": 34000.00,
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Где посмотреть загруженные данные
|
||||
|
||||
1. **Список отчетов**: Вкладка "Отчеты" → "Загруженные отчеты"
|
||||
2. **Детали отчета**: Клик на отчет → показывает дома, участки, детальную разбивку
|
||||
3. **Данные по дому**: В паспорте дома → раздел "Финансы" → данные из `building_financial_data`
|
||||
|
||||
### Проблемы и решения
|
||||
|
||||
**Проблема**: "Дом не найден в базе"
|
||||
- **Причина**: Адрес из файла не найден ни в `doma_address_mappings`, ни в таблице `buildings` (с учётом нормализации).
|
||||
- **Решение**: Добавить запись в `doma_address_mappings` (адрес из ОСВ → `building_id`), либо привести адрес дома в паспорте к формату из файла, либо добавить дом вручную.
|
||||
|
||||
**Проблема**: "Зеленая Роща" не распознается
|
||||
- **Причина**: Нет цифр в первой колонке (это участок, а не дом)
|
||||
- **Решение**: Если это участок, данные должны быть привязаны к конкретным домам внутри участка
|
||||
|
||||
---
|
||||
|
||||
## Оборотно-сальдовая ведомость по счёту 76.06 (лицевые счета жителей)
|
||||
|
||||
### Назначение
|
||||
|
||||
ОСВ по счёту 76.06 содержит **лицевые счета** (жители/собственники): в 1С колонка может называться «Контрагенты», по смыслу это лицевые счета с суммами (обороты, сальдо).
|
||||
|
||||
### Распознавание файла
|
||||
|
||||
- По названию файла: подстроки `"76"`, `"76.06"`, `"счету 76"` (без учёта регистра) — тип `balance_sheet_76`.
|
||||
- По фронту: при выборе типа «ОСВ по счёту 76» передаётся `detailedReportType: 'balance_sheet_76'`.
|
||||
|
||||
### Формат CSV (схема колонок)
|
||||
|
||||
- Разделитель `;`, кодировка UTF-8, BOM убирается.
|
||||
- Строки 1–8: метаданные, заголовки «Счет», «Контрагенты», «Дебет», «Кредит». Начало данных определяется автоматически (по «Обороты за период» / «Контрагенты» или по первой строке с числом в колонке 3/4).
|
||||
- Колонки те же, что у ОСВ 20: 0 — наименование (лицевой счёт: код + ФИО (л/с) или просто ФИО/ИП/юрлицо); 1, 3, 4, 5, 6 — сальдо на начало, обороты дебет/кредит, сальдо на конец. Пропускаются строки с колонкой 0 = `76.06` или `Итого`.
|
||||
|
||||
### Куда сохраняются данные
|
||||
|
||||
1. **Таблица `financial_reports`**: запись с `report_type = 'balance_sheet_76'`.
|
||||
2. **Таблица `report_76_rows`**: по одной строке на каждый лицевой счёт (report_id, row_index, account_label, account_ls, saldo_start_debet, turnover_debet, turnover_credit, saldo_end_debet, saldo_end_credit).
|
||||
3. **Таблица `building_personal_account_mappings`** (сопоставление домов и лицевых счетов): привязка лицевого счёта к дому (building_id, account_ls, account_label, apartment). Используется для фильтра «ОСВ 76 по дому» и отображения данных 76 в карточке дома. Заполняется вручную или импортом.
|
||||
|
||||
### API
|
||||
|
||||
- `GET /api/finance/reports/:reportId/balance-sheet-76-rows` — строки отчёта (лицевые счета). Опциональный параметр `buildingId`: при указании возвращаются только строки, чей лицевой счёт привязан к этому дому в `building_personal_account_mappings`.
|
||||
- `GET /api/finance/buildings/:buildingId/personal-accounts` — лицевые счета, привязанные к дому.
|
||||
- `POST /api/finance/building-personal-account-mappings` — добавить/обновить привязку (body: building_id, account_ls, опционально account_label, apartment).
|
||||
|
||||
### Где посмотреть
|
||||
|
||||
1. **Список отчетов**: Финансы → Отчеты; фильтр «Лицевые счета (ОСВ 76)».
|
||||
2. **Детали отчёта**: Клик на отчёт ОСВ 76 → таблица лицевых счетов (колонки: Лицевой счёт, Сальдо на начало, Обороты дебет/кредит, Сальдо на конец). При наличии маппинга можно добавить фильтр по дому.
|
||||
Reference in New Issue
Block a user