Загрузка данных


## Обзор схемы базы данных

На основе предоставленного кода (класс `DatabaseManager`) база данных `bot.db` (SQLite) содержит следующие таблицы, разделённые по логическим группам.

### 1. Пользователи и роли

#### `users`
| Колонка          | Тип        | Ограничения                                 | Описание                     |
|------------------|------------|---------------------------------------------|------------------------------|
| id               | INTEGER    | PRIMARY KEY AUTOINCREMENT                   | Внутренний ID                |
| vk_id            | INTEGER    | UNIQUE NOT NULL                             | ID пользователя ВКонтакте    |
| first_name       | TEXT       | NOT NULL                                    | Имя                          |
| last_name        | TEXT       | NOT NULL                                    | Фамилия                      |
| screen_name      | TEXT       |                                             | Короткое имя ВК              |
| phone            | TEXT       |                                             | Телефон                      |
| is_active        | INTEGER    | DEFAULT 1                                   | 1 – активен, 0 – деактивирован |
| deactivated_at   | DATETIME   |                                             | Дата деактивации             |
| created_at       | DATETIME   | DEFAULT CURRENT_TIMESTAMP                   | Дата регистрации             |

#### `roles`
| Колонка      | Тип        | Ограничения               | Описание           |
|--------------|------------|---------------------------|--------------------|
| id           | INTEGER    | PRIMARY KEY AUTOINCREMENT | ID роли            |
| name         | TEXT       | UNIQUE NOT NULL           | Название роли      |
| description  | TEXT       |                           | Описание           |
| is_active    | INTEGER    | DEFAULT 1                 | Активна/неактивна  |
| created_at   | DATETIME   | DEFAULT CURRENT_TIMESTAMP | Дата создания      |

#### `permissions`
| Колонка      | Тип        | Ограничения               | Описание                 |
|--------------|------------|---------------------------|--------------------------|
| id           | INTEGER    | PRIMARY KEY AUTOINCREMENT | ID разрешения            |
| name         | TEXT       | UNIQUE NOT NULL           | Кодовое имя (`create_request` и т.д.) |
| description  | TEXT       |                           | Описание                 |
| address      | TEXT       |                           | Связанный эндпоинт (опционально) |

#### `role_permissions`
| Колонка        | Тип     | Ограничения                                          |
|----------------|---------|------------------------------------------------------|
| role_id        | INTEGER | PRIMARY KEY, FOREIGN KEY → roles(id) ON DELETE CASCADE |
| permission_id  | INTEGER | PRIMARY KEY, FOREIGN KEY → permissions(id) ON DELETE CASCADE |

#### `users_roles`
| Колонка      | Тип     | Ограничения                                           |
|--------------|---------|-------------------------------------------------------|
| user_id      | INTEGER | PRIMARY KEY, FOREIGN KEY → users(id) ON DELETE CASCADE |
| role_id      | INTEGER | PRIMARY KEY, FOREIGN KEY → roles(id) ON DELETE CASCADE |
| assigned_at  | DATETIME| DEFAULT CURRENT_TIMESTAMP                             |

#### `role_subordination`
| Колонка            | Тип     | Ограничения                                           |
|--------------------|---------|-------------------------------------------------------|
| superior_role_id   | INTEGER | PRIMARY KEY, FOREIGN KEY → roles(id) ON DELETE CASCADE |
| subordinate_role_id| INTEGER | PRIMARY KEY, FOREIGN KEY → roles(id) ON DELETE CASCADE |

---

### 2. Заявки и связанные справочники

#### `request_statuses` (справочник статусов)
| Колонка     | Тип     | Ограничения          | Описание                     |
|-------------|---------|----------------------|------------------------------|
| code        | TEXT    | PRIMARY KEY NOT NULL | Код (`NEW`, `IN_WORK`, …)    |
| name        | TEXT    | NOT NULL             | Отображаемое имя             |
| sort_order  | INTEGER | NOT NULL             | Порядок сортировки           |

**Значения после миграций:** NEW, IN_WORK, DEFERRED, ON_REVIEW, REVISION, DONE.

#### `urgencies` (срочность)
| Колонка         | Тип     | Ограничения               | Описание                       |
|-----------------|---------|---------------------------|--------------------------------|
| code            | TEXT    | PRIMARY KEY NOT NULL      | `NORMAL`, `URGENT`             |
| name            | TEXT    | NOT NULL                  | Название                       |
| duration_hours  | INTEGER | NOT NULL CHECK (>0)       | Часов на выполнение            |
| emoji           | TEXT    |                           | Эмодзи для визуализации        |

#### `requests` (основная таблица заявок)
| Колонка                | Тип      | Ограничения                                                      |
|------------------------|----------|------------------------------------------------------------------|
| id                     | INTEGER  | PRIMARY KEY AUTOINCREMENT                                        |
| description            | TEXT     | NOT NULL                                                         |
| location_id            | INTEGER  | NOT NULL (внешний ключ на `locations.id`)                        |
| nomer_id               | INTEGER  | (предположительно внешний ключ, но таблица `nomers` не объявлена) |
| urgency_code           | TEXT     | NOT NULL DEFAULT 'NORMAL', FOREIGN KEY → urgencies(code)         |
| status_code            | TEXT     | NOT NULL DEFAULT 'NEW', FOREIGN KEY → request_statuses(code)     |
| user_id                | INTEGER  | NOT NULL, FOREIGN KEY → users(id) ON DELETE RESTRICT             |
| created_at             | DATETIME | DEFAULT CURRENT_TIMESTAMP                                        |
| current_deadline_at    | DATETIME | NOT NULL                                                         |
| assignee_user_id       | INTEGER  | FOREIGN KEY → users(id) ON DELETE SET NULL                       |
| assignee_role_id       | INTEGER  | FOREIGN KEY → roles(id) ON DELETE SET NULL                       |
| assigned_at            | DATETIME |                                                                  |
| started_at             | DATETIME |                                                                  |
| reviewed_at            | DATETIME |                                                                  |
| completed_at           | DATETIME |                                                                  |
| photo_count_initial    | INTEGER  | DEFAULT 0, CHECK (0–9)                                          |
| is_draft               | BOOLEAN  | DEFAULT 0                                                        |
| updated_by             | INTEGER  | FOREIGN KEY → users(id) ON DELETE SET NULL                       |

> **Примечание:** в триггере `set_request_deadline` используется столбец `initial_deadline_at`, но в определении таблицы он отсутствует – вероятно, добавлен миграцией (не показано). В финальной схеме этот столбец должен существовать.

#### `locations` (добавлено миграцией)
| Колонка   | Тип     | Ограничения                   |
|-----------|---------|-------------------------------|
| id        | INTEGER | PRIMARY KEY AUTOINCREMENT     |
| name      | TEXT    | NOT NULL UNIQUE               |
| address   | TEXT    |                               |

#### `rooms` (добавлено миграцией)
| Колонка      | Тип     | Ограничения                                            |
|--------------|---------|--------------------------------------------------------|
| id           | INTEGER | PRIMARY KEY AUTOINCREMENT                              |
| location_id  | INTEGER | NOT NULL, FOREIGN KEY → locations(id) ON DELETE CASCADE|
| name         | TEXT    | NOT NULL                                               |
| UNIQUE       | (location_id, name)                                    |

---

### 3. Изображения

#### `imgs`
| Колонка      | Тип     | Ограничения                               |
|--------------|---------|-------------------------------------------|
| id           | INTEGER | PRIMARY KEY AUTOINCREMENT                 |
| url          | TEXT    | UNIQUE NOT NULL                           |
| uploader_id  | INTEGER | NOT NULL, FOREIGN KEY → users(id) ON DELETE CASCADE |
| uploaded_at  | DATETIME| DEFAULT CURRENT_TIMESTAMP                 |
| meta         | TEXT    | JSON-метаданные                           |

#### `request_imgs` (связь заявки и изображений)
| Колонка     | Тип     | Ограничения                                           |
|-------------|---------|-------------------------------------------------------|
| request_id  | INTEGER | PRIMARY KEY, FOREIGN KEY → requests(id) ON DELETE CASCADE |
| img_id      | INTEGER | PRIMARY KEY, FOREIGN KEY → imgs(id) ON DELETE CASCADE |

> Триггер `limit_request_photos` ограничивает 9 фото на заявку.

#### `revisions` (доработки заявки)
| Колонка      | Тип     | Ограничения                                          |
|--------------|---------|------------------------------------------------------|
| id           | INTEGER | PRIMARY KEY AUTOINCREMENT                            |
| request_id   | INTEGER | NOT NULL, FOREIGN KEY → requests(id) ON DELETE CASCADE |
| reason       | TEXT    | NOT NULL                                             |
| created_by   | INTEGER | NOT NULL, FOREIGN KEY → users(id) ON DELETE CASCADE  |
| created_at   | DATETIME| DEFAULT CURRENT_TIMESTAMP                            |
| photo_count  | INTEGER | DEFAULT 0, CHECK (0–9)                              |

#### `revision_imgs`
| Колонка      | Тип     | Ограничения                                            |
|--------------|---------|--------------------------------------------------------|
| revision_id  | INTEGER | PRIMARY KEY, FOREIGN KEY → revisions(id) ON DELETE CASCADE |
| img_id       | INTEGER | PRIMARY KEY, FOREIGN KEY → imgs(id) ON DELETE CASCADE  |

#### `done_work` (завершённая работа)
| Колонка       | Тип     | Ограничения                                          |
|---------------|---------|------------------------------------------------------|
| id            | INTEGER | PRIMARY KEY AUTOINCREMENT                            |
| request_id    | INTEGER | NOT NULL UNIQUE, FOREIGN KEY → requests(id) ON DELETE CASCADE |
| completed_at  | DATETIME| NOT NULL                                             |
| submitted_by  | INTEGER | NOT NULL, FOREIGN KEY → users(id) ON DELETE CASCADE  |
| photo_count   | INTEGER | DEFAULT 0, CHECK (0–9)                              |

#### `completion_imgs`
| Колонка        | Тип     | Ограничения                                            |
|----------------|---------|--------------------------------------------------------|
| completion_id  | INTEGER | PRIMARY KEY, FOREIGN KEY → done_work(id) ON DELETE CASCADE |
| img_id         | INTEGER | PRIMARY KEY, FOREIGN KEY → imgs(id) ON DELETE CASCADE  |

---

### 4. История и аудит

#### `status_history`
| Колонка     | Тип     | Ограничения                                               |
|-------------|---------|-----------------------------------------------------------|
| id          | INTEGER | PRIMARY KEY AUTOINCREMENT                                 |
| request_id  | INTEGER | NOT NULL, FOREIGN KEY → requests(id) ON DELETE CASCADE    |
| from_code   | TEXT    | FOREIGN KEY → request_statuses(code)                      |
| to_code     | TEXT    | NOT NULL, FOREIGN KEY → request_statuses(code)            |
| changed_by  | INTEGER | NOT NULL, FOREIGN KEY → users(id) ON DELETE CASCADE       |
| changed_at  | DATETIME| DEFAULT CURRENT_TIMESTAMP                                 |
| comment     | TEXT    |                                                           |

#### `assignment_history`
| Колонка       | Тип     | Ограничения                                           |
|---------------|---------|-------------------------------------------------------|
| id            | INTEGER | PRIMARY KEY AUTOINCREMENT                             |
| request_id    | INTEGER | NOT NULL, FOREIGN KEY → requests(id) ON DELETE CASCADE|
| to_user_id    | INTEGER | FOREIGN KEY → users(id) ON DELETE SET NULL            |
| to_role_id    | INTEGER | FOREIGN KEY → roles(id) ON DELETE SET NULL            |
| from_user_id  | INTEGER | FOREIGN KEY → users(id) ON DELETE SET NULL            |
| reason        | TEXT    |                                                       |
| assigned_by   | INTEGER | NOT NULL, FOREIGN KEY → users(id) ON DELETE CASCADE   |
| assigned_at   | DATETIME| DEFAULT CURRENT_TIMESTAMP                             |

#### `deadline_extensions`
| Колонка       | Тип     | Ограничения                                           |
|---------------|---------|-------------------------------------------------------|
| id            | INTEGER | PRIMARY KEY AUTOINCREMENT                             |
| request_id    | INTEGER | NOT NULL, FOREIGN KEY → requests(id) ON DELETE CASCADE|
| reason        | TEXT    | NOT NULL                                              |
| requested_by  | INTEGER | NOT NULL, FOREIGN KEY → users(id) ON DELETE CASCADE   |
| old_deadline  | DATETIME| NOT NULL                                              |
| new_deadline  | DATETIME| NOT NULL                                              |
| requested_at  | DATETIME| DEFAULT CURRENT_TIMESTAMP                             |

---

### 5. Вспомогательные таблицы

#### `ratings` (добавлено миграцией)
| Колонка      | Тип     | Ограничения                                           |
|--------------|---------|-------------------------------------------------------|
| id           | INTEGER | PRIMARY KEY AUTOINCREMENT                             |
| request_id   | INTEGER | NOT NULL, FOREIGN KEY → requests(id) ON DELETE CASCADE|
| assessor_id  | INTEGER | NOT NULL, FOREIGN KEY → users(id)                     |
| executor_id  | INTEGER | FOREIGN KEY → users(id)                               |
| rating       | INTEGER | NOT NULL CHECK (1–5)                                  |
| comment      | TEXT    |                                                       |
| created_at   | DATETIME| DEFAULT CURRENT_TIMESTAMP                             |

#### `request_wizard_drafts` (черновики заявок)
| Колонка     | Тип     | Ограничения                                     |
|-------------|---------|-------------------------------------------------|
| user_id     | INTEGER | PRIMARY KEY, FOREIGN KEY → users(id) ON DELETE CASCADE |
| step        | INTEGER | NOT NULL CHECK (1–7)                           |
| data_json   | TEXT    | NOT NULL                                       |
| updated_at  | DATETIME| DEFAULT CURRENT_TIMESTAMP                      |

---

### 6. Триггеры и индексы

**Триггеры** (кратко):
- `set_request_deadline` – устанавливает `initial_deadline_at` и `current_deadline_at` на основе `urgency_code` при вставке заявки.
- `log_status_change` – вставляет запись в `status_history` при изменении `status_code`.
- `log_assignment_change` – вставляет запись в `assignment_history` при изменении `assignee_user_id` или `assignee_role_id`.
- `apply_deadline_extension` – обновляет `current_deadline_at` при добавлении записи в `deadline_extensions`.
- Триггеры ограничения количества фото для `request_imgs`, `revision_imgs`, `completion_imgs` (максимум 9).
- Триггеры обновления счётчиков `photo_count_initial` (заявки), `photo_count` (revisions, done_work) при вставке/удалении фото.

**Индексы** (выборочно):
- `idx_requests_status_deadline` – для поиска по статусу и дедлайну.
- `idx_requests_assignee_user`, `idx_requests_assignee_role` – для фильтрации по исполнителям.
- `idx_requests_created_paginate` – для пагинации по дате создания.
- `idx_users_vk`, `idx_users_active` – ускорение поиска пользователей.
- Остальные индексы на внешние ключи и часто используемые поля.

---

## Визуальное представление (диаграмма ER)

Для лучшего понимания связей можно представить упрощённую ER-диаграмму в текстовом виде:

```
users ──┬── users_roles ──┬── roles
        │                 │
        └── requests (user_id)
                 │
                 ├── request_imgs ── imgs
                 ├── revisions ── revision_imgs ──┤
                 ├── done_work ── completion_imgs ─┘
                 ├── status_history
                 ├── assignment_history
                 ├── deadline_extensions
                 ├── ratings
                 ├── locations ── rooms
                 └── request_wizard_drafts
```

*Примечание:* `locations` и `rooms` связаны с `requests` через `location_id` (внешний ключ явно не показан в коде, но `location_id` в таблице `requests` присутствует).

Такая структура обеспечивает полный жизненный цикл заявки: создание → назначение → выполнение → доработки → завершение, с аудитом всех значимых действий.