# Как работает обработка отчетов из 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 → таблица лицевых счетов (колонки: Лицевой счёт, Сальдо на начало, Обороты дебет/кредит, Сальдо на конец). При наличии маппинга можно добавить фильтр по дому.
