# Заявления

# Управление заявлениями

Заявления — это основной механизм записи студентов на курсы. Заявление можно создать вручную (администратор) или через публичную форму регистрации (плательщик/студент). Описание публичной регистрации: [03-courses.md → Публичная регистрация](https://docs.huvis.ee/link/142#публичная-регистрация-iframe).

---

## Статусы заявлений

Каждое заявление проходит через определённые этапы:

| Статус | Описание |
|--------|----------|
| **Лист ожидания** | Места на курсе заняты, студент ожидает освобождения |
| **Создано** | Заявление создано, ожидает обработки |
| **Отправлено** | Документ отправлен плательщику на подписание |
| **Подписано** | Договор подписан, студент зачислен |
| **Закрыто** | Обучение завершено или студент отчислен |
| **Аннулировано** | Заявление отменено до подписания |
| **Пробный урок** | Студент записан на пробное занятие, ожидается подтверждение |

### Жизненный цикл заявления

```
Регистрация → [Создано] → Отправлено → Подписано → Закрыто
                  │              │
                  │              └─→ Аннулировано (отмена до подписания)
                  │
                  └─→ Лист ожидания (если нет мест)
                        └─→ Создано (при освобождении места)

Пробный урок → [Пробный] → Подтверждение → [Создано] → …
                          → Отказ → [Закрыто]
```

---

## Номер заявления

Каждому заявлению автоматически присваивается **номер** (например, `2025/42`). Формат номера настраивается организацией.

### Формат по умолчанию

`Учебный год / ID заявления` → `2025/42`

### Настройка формата

Администратор может изменить формат номера:

1. Перейдите в **Курсы → Настройки**.
2. Выберите вкладку **Avalduse mall** (Шаблон заявления).
3. Внизу страницы найдите блок **Avalduse numbri mall** (Шаблон номера заявления).
4. Введите шаблон с переменными и нажмите **Сохранить**.
5. Справа от поля отображается **живой предпросмотр** — как будет выглядеть номер.

Доступные переменные:

| Переменная | Что подставляется | Пример |
|------------|-------------------|--------|
| `[[ACADEMIC_YEAR]]` | Учебный год курса | `2025` |
| `[[YYYY]]` | Календарный год | `2026` |
| `[[YY]]` | Год (2 цифры) | `26` |
| `[[MM]]` | Месяц | `03` |
| `[[SEQ]]` | Порядковый номер | `0042` |
| `[[ID]]` | ID заявления | `42` |
| `[[COURSE]]` | Название курса | `Klaveriõpe` |
| `[[STUDENT_CODE]]` | Личный код студента | `50301040740` |
| `[[STUDENT_NAME]]` | Имя студента | `Mari Tamm` |

**Примеры:**
- `[[ACADEMIC_YEAR]]/[[SEQ]]` → `2025/0042` (учебный год + порядковый номер)
- `[[YYYY]]-[[SEQ]]` → `2026-0042` (календарный год + порядковый номер)
- `[[SEQ]]` → `0042` (только номер)

> **Важно:** Изменение шаблона влияет только на **новые** заявления. Существующие номера не меняются.

> **Примечание:** В DOCX-шаблонах доступны две переменные:
> - `[[APPLICATION_ID]]` — уникальный ID заявления из базы данных (число, например `42`)
> - `[[APPLICATION_NUMBER]]` — номер заявления по шаблону (например `2025/0042`)
>
> Используйте `[[APPLICATION_NUMBER]]` для отображения номера договора в документах.

---

## Список заявлений

Перейдите в **Курсы → Заявления**.

### Фильтрация по статусу

Вверху страницы расположены вкладки по статусам: **Лист ожидания**, **Создано**, **Отправлено**, **Подписано**, **Закрыто**, **Аннулировано**. Рядом с каждой вкладкой показано количество заявлений.

### Фильтры и поиск

- **Курс** — выпадающий список для фильтрации по конкретному курсу
- **Студент** — поиск по имени студента
- **Плательщик** — поиск по имени плательщика

### Столбцы таблицы

| Столбец | Описание |
|---------|----------|
| Номер | Номер заявления (формат настраивается, см. выше) |
| Студент | Имя и фамилия |
| Плательщик | Имя и фамилия |
| Курс | Название курса |
| Дата создания | Когда заявление было создано |
| Дата первого урока | С какой даты студент присоединяется |
| Дополнительные | Зависят от выбранной вкладки: дата отправки, подписания, закрытия |

Все столбцы сортируемые. Нажмите на заголовок столбца для сортировки.

### Экспорт

Кнопка **Экспорт** позволяет скачать таблицу в формате XLSX (текущая страница или все записи).

### Видимость

- **Работники** видят только заявления по своим курсам (где они преподаватель или ассистент).
- **Менеджеры** видят все заявления организации.

---

## Создание заявления (администратор)

1. Перейдите в **Курсы → Добавить заявление** (или кнопка «Создать» на странице списка).
2. Заполните форму:

### Блок «Курс»

- **Курс** — выберите из выпадающего списка. После выбора появятся доступные тарифы.
- **Тариф** — выберите вариант оплаты (например, ежемесячная, 3 месяца, полугодовая). Радиокнопки с ценами.

### Блок «Студент»

- **Личный код** — начните вводить. Система автоматически ищет студентов по коду.
- Если студент найден, поля имя/фамилия заполнятся автоматически.
- Если не найден, заполните **Имя**, **Фамилию** и контактные данные — студент будет создан.
- **Адрес**, **Телефон**, **Email** — видимость зависит от настроек.

### Блок «Плательщик»

- Аналогично студенту: поиск по личному коду или создание нового.
- Можно привязать существующего плательщика.

### Дополнительные поля

- **Дата первого урока** — с какой даты студент начинает посещать. Влияет на расчёт стоимости (проратирование).
- **Статус** — можно выбрать начальный статус (по умолчанию: Создано).

3. Нажмите **Сохранить**.

> **Что происходит при сохранении:**
> - Создаётся запись студента (если нового) и плательщика
> - Создаётся запись Party (билинговая сущность) для плательщика
> - Если нет мест и включён лист ожидания → статус «Лист ожидания»
> - Проверяется дубликат: у студента не может быть двух активных заявлений на один курс
> - Если включены уведомления преподавателей → им отправляется email

---

## Страница заявления (детали)

Нажмите на заявление в списке для открытия детальной страницы. Страница разделена на несколько блоков.

### Блок «Данные студента / плательщика / курса»

Три колонки:

**Студент:**
- Имя, фамилия (редактируемые inline)
- Личный код, возраст
- Адрес, телефон, email

**Плательщик:**
- Имя, фамилия (редактируемые inline)
- Личный код
- Адрес, телефон, email
- Индикатор «Братья/сёстры» — ссылка на другие заявления этого плательщика

**Курс:**
- Название (ссылка на страницу курса)
- Активные тарифы
- Расписание (сетка 7 дней: время, кабинет, онлайн-индикатор)

### Блок «Статус и даты»

- **Статус** — цветной бейдж текущего статуса
- **Индикатор перевода** — если заявление переведено, показана ссылка на новое заявление
- **Номер ссылки** — при включённом модуле счетов
- **Ссылка на конференцию** — при включённом модуле конференций (с кнопкой копирования)

**Даты:**

| Дата | Описание | Действие |
|------|----------|----------|
| Дата создания | Когда заявление было создано | — |
| Дата первого урока | С какого урока студент присоединяется | Редактирование (кнопка ✏️) |
| Дата отправки | Когда документ был отправлен | Повторная отправка (кнопка) |
| Дата подписания | Когда договор был подписан | Отметить как подписанное (кнопка) |
| Дата закрытия | Когда заявление было закрыто | Редактирование |
| Дата последнего урока | Последний оплачиваемый урок | Для закрытых заявлений |

**Информация о пробном уроке** (если заявление пробное):
- Дата пробного урока
- Статус: подтверждено / отклонено / ожидает решения
- Кнопки **Подтвердить** и **Отклонить** (если ожидает)

**Информация о листе ожидания** (если статус «Лист ожидания»):
- Позиция в очереди
- Кнопка **Активировать**

**Принудительная смена статуса:**
- Выпадающий список с доступными статусами + кнопка **Сохранить**
- Доступно для всех статусов кроме «Закрыто» и «Аннулировано»

### Блок «Цена и скидки»

**Цена:**
- Базовая цена (перечёркнута, если есть скидка)
- Итоговая сумма к оплате
- Частота оплаты (ежемесячно, 3 мес. и т.д.)
- Размер скидки

**Скидки:**
- Список активных скидок (зелёный фон): название, значение, срок действия
- Кнопки: закрыть скидку (установить дату окончания) / удалить
- Неактивные скидки (сворачиваемый блок)
- Кнопка **Добавить скидку** (для статусов Создано / Отправлено)

**Счета** (при включённом модуле):
- Кнопки: **Генерировать счёт**, **Пересчитать**, **Наличная оплата**, **Добавить начисление**
- Таблица счетов: номер, сумма, дата оплаты, статус, дата оплаты
- Статус каждого счёта цветным бейджем

### Блок «Файлы»

- Последние 4 файла с информацией: кто загрузил, название, назначение (бейдж), дата
- Кнопки: скачать, предпросмотр
- Ссылка **Показать все файлы**
- Кнопка **Загрузить файл**

**Назначения файлов:**

| Бейдж | Назначение |
|-------|------------|
| Документ на подпись | PDF, сгенерированный из шаблона и отправленный плательщику |
| Подписанный документ | Загруженный подписанный договор |
| Файл заявления | Пользовательский файл |

---

## Действия с заявлением

### Предпросмотр и отправка документа

Это ключевое действие для отправки договора плательщику.

1. Нажмите кнопку **Предпросмотр** на странице заявления.
2. Система генерирует PDF из шаблона заявления (настраивается на вкладке «Шаблон» курса).
3. PDF отображается в модальном окне.
4. Доступно **два действия**:

| Действие | Что происходит | Email |
|----------|----------------|-------|
| **Сохранить** | Файл сохраняется к заявлению с назначением «Документ на подпись». Статус → Отправлено. | **Нет** |
| **Отправить** | Файл сохраняется. Статус → Отправлено. Плательщику отправляется email с PDF во вложении. | **Да** |

> **Важно: разница между «Сохранить» и «Отправить».**
> - **Сохранить** — документ только прикрепляется к заявлению, плательщик **не получает** email. Полезно, если вы хотите передать документ лично.
> - **Отправить** — документ прикрепляется И плательщик **получает email** с PDF. Шаблон email настраивается в разделе «Шаблон» курса (для статуса «Отправлено»). Письмо добавляется в очередь отправки и обрабатывается фоновым процессом.

### Повторная отправка

Кнопка **Отправить повторно** рядом с датой отправки:
- Отправляет последний сохранённый документ (с назначением «Документ на подпись») на email плательщика.
- Статус заявления **не меняется**.
- Используется шаблон email, соответствующий текущему статусу заявления.

### Отметить как подписанное

1. Нажмите кнопку **Подписано** рядом с датой подписания.
2. В модальном окне укажите **дату подписания**.
3. Выберите, что делать с подписанным документом:

**Если к заявлению уже прикреплены файлы**, доступны три режима (переключатель):

| Режим | Что происходит |
|-------|----------------|
| **Без файла** | Заявление подписывается без привязки документа |
| **Выбрать загруженный файл** | Выбираете один из уже прикреплённых к заявлению файлов — его назначение меняется на «Подписанный документ» |
| **Загрузить новый файл** | Загружаете новый документ с компьютера (назначение «Подписанный документ») |

**Если файлов ещё нет** — показывается только поле загрузки, и оно **необязательно**: можно подписать заявление и без файла.

4. Нажмите **Сохранить**.

> **Что происходит:** Статус → Подписано (для пробного урока в статусе «Отправлено» — фиксируется подписание договора). Привязка/пометка файла и смена статуса выполняются **атомарно** — заявление не останется с «подписанным» файлом при неподписанном статусе. Если настроены счета — начинается процесс биллинга.

> **Доступ:** Действие требует права **«Редактирование заявления»** (`course.application.edit`). В режиме «Выбрать загруженный файл» система проверяет, что выбранный файл действительно принадлежит этому заявлению.

### Изменение даты первого урока

1. Нажмите ✏️ рядом с «Дата первого урока».
2. Выберите дату в календаре.
3. Нажмите **Сохранить**.

> **Последствие:** Дата первого урока используется как дата зачисления (enrollment_date) для расчёта проратирования стоимости. Изменение влияет на будущие счета.

### Изменение даты зачисления

1. Нажмите ✏️ рядом с «Дата зачисления» в блоке Lisainfo.
2. Выберите дату в календаре.
3. Нажмите **Сохранить**.

> **Назначение:** Дата зачисления определяет начало периода обучения для расчёта стоимости и проратирования. При создании заявления автоматически заполняется из даты первого урока. Если дата не установлена — генерация счетов невозможна.

### Изменение даты последнего урока

1. Нажмите ✏️ рядом с «Дата последнего урока» в блоке Lisainfo.
2. Выберите дату в календаре.
3. Нажмите **Сохранить**.

> **Назначение:** Дата последнего урока ограничивает период обучения. Если дата в прошлом — система не сможет создать счёт за текущий период. Обычно устанавливается автоматически из `date_end` курса при подписании.

### Изменение тарифа

1. Нажмите ✏️ рядом с блоком цены.
2. В модальном окне выберите новый тариф из доступных.
3. Нажмите **Сохранить**.

> **Последствие:** Пересчитываются все будущие счета. Уже выставленные счета (ISSUED/SENT/PAID) не изменяются.

### Закрытие заявления

1. Нажмите кнопку **Закрыть**.
2. В модальном окне:
   - **Дата закрытия** — по умолчанию сегодня.
   - **Дата последнего урока** (для подписанных заявлений) — ограничена датами расписания.
3. Нажмите **Подтвердить**.

> **Что происходит:**
> - Если статус **Создано/Отправлено** → статус меняется на **Аннулировано** (отмена до подписания)
> - Если статус **Подписано** → статус меняется на **Закрыто** (завершение обучения)
> - Система вычисляет дату последнего урока из расписания курса
> - Если включён модуль счетов → пересчитываются счета (cutoff), будущие запланированные счета удаляются

### Перевод на другой курс

1. Нажмите **Перевести**.
2. Выберите новый курс.
3. При необходимости выберите новый тариф и дату начала.

> **Что происходит:**
> - Если курс в той же специализации с совместимым тарифом → заявление переключается на новый курс
> - Если специализация или тариф отличаются → текущее заявление закрывается, создаётся новое с привязкой (`transferred_to_id`)
> - Активные скидки копируются на новое заявление
> - На странице старого заявления появляется ссылка на новое

### Заявления, созданные при копировании курса

При [копировании курса](https://docs.huvis.ee/link/142#копирование-курса-на-новый-учебный-год) в режиме **«Создать новые заявки»** система создаёт новые заявления на новом курсе. На странице каждого такого заявления видна ссылка **«Создано на основе заявления #N»** — нажмите, чтобы перейти к исходному заявлению на старом курсе.

Исходные заявления на старом курсе при этом **не меняются** — сохраняют прежний статус.

При копировании в режиме **«Перенести»** заявки переносятся на новый курс, а на старом курсе в заявлении появляется ссылка на новое (аналогично обычному переводу).

**Предупреждение о учебном годе:** Если вы открыли заявление, а его курс относится к другому учебному году, чем выбранный в верхней панели — вверху страницы появится **жёлтое предупреждение**. Это нормально — просто переключите год в верхней панели на нужный.

### Принудительная смена статуса

Выпадающий список в блоке статуса позволяет вручную перевести заявление в любой статус.

| Переход | Что происходит |
|---------|----------------|
| → Создано | Очищаются даты отправки, подписания, закрытия |
| → Отправлено | Устанавливается дата отправки |
| → Подписано | Устанавливается дата подписания |
| → Закрыто | Устанавливается дата закрытия, вычисляется дата последнего урока |
| → Аннулировано | Устанавливается дата закрытия |
| → Лист ожидания | Очищаются все даты |
| → Пробный | Устанавливается `is_trial=true`, создаётся запись пробного урока |

> **Внимание:** При переходе из «Пробный» в другой статус автоматически удаляются данные пробного урока и неоплаченные trial-счета.

### Активация из листа ожидания

Кнопка **Активировать** на заявлении со статусом «Лист ожидания»:
- Статус → Создано
- Отправляются уведомления: работникам и плательщику (шаблон «Активация из листа ожидания»)

---

## Управление скидками

### Добавление скидки

1. Нажмите **Добавить скидку** в блоке цены.
2. В модальном окне доступно три варианта (взаимоисключающие):

**Вариант 1 — Выбрать существующую скидку:**
- Выпадающий список доступных скидок из справочника (тип и значение: «-15.50%» или «-25.00 €»).

**Вариант 2 — Указать индивидуальную цену:**
- Введите итоговую цену. Система автоматически создаст скрытую скидку на разницу.

**Вариант 3 — По количеству уроков** (если в неделю > 1 урока):
- Укажите, сколько уроков в неделю студент посещает.
- Система рассчитает процент скидки: `(всего - посещает) / всего × 100`.

3. **Период действия** (необязательно):
   - **Дата начала** — с какой даты скидка начинает действовать
   - **Дата окончания** — до какой даты скидка действует

4. В реальном времени отображается расчёт итоговой цены с учётом скидки.

5. Нажмите **Сохранить**.

> **Последствия:**
> - Все будущие счета пересчитываются автоматически
> - Если заявление в статусе «Отправлено» или «Подписано» — появится предупреждение о необходимости повторного подписания

### Закрытие скидки

1. Нажмите кнопку закрытия (×) рядом со скидкой.
2. Укажите **дату окончания** (по умолчанию — сегодня).
3. Нажмите **Сохранить**.

> **Что происходит:** Скидка мягко удаляется (soft-delete) с указанной даты. Счета пересчитываются. Аудиторский след сохраняется.

### Удаление скидки

Кнопка удаления полностью убирает скидку (soft-delete). Счета пересчитываются.

---

## Массовая отправка на подписание

Для одновременной отправки документов по нескольким заявлениям:

1. Перейдите в список заявлений.
2. Нажмите **Массовая отправка**.
3. Можно выбрать конкретный курс или все курсы.
4. Система запускает фоновый процесс:
   - Для каждого заявления со статусом «Создано» генерируется PDF
   - PDF отправляется плательщику
   - Статус → Отправлено
5. Прогресс отображается в реальном времени на странице.

> **Внимание:** Массовая отправка обрабатывается в фоновом режиме (через очередь). При большом количестве заявлений процесс может занять несколько минут.

---

## Загрузка файлов

1. На странице заявления нажмите **Загрузить файл**.
2. Выберите файл на компьютере.
3. Файл будет прикреплён к заявлению с назначением «Файл заявления».

> **Примечание:** Загрузка файла только сохраняет его в системе. Файл **не отправляется** плательщику автоматически. Для отправки используйте функцию «Предпросмотр → Отправить».

### Прикрепление вложения из письма

Если плательщик прислал документ (например, подписанный договор или справку) на
почту, файл можно прикрепить к заявлению **прямо из почтового клиента**, не
скачивая его на компьютер.

1. Откройте письмо в разделе **Почта**.
2. У нужного вложения нажмите кнопку **📁 «Прикрепить к заявлению»**.
3. В открывшемся окне введите **номер заявления** или **имя студента** (минимум 2 символа) и выберите заявление из списка.
4. Вложение копируется в файлы заявления с назначением **«Файл заявления»**.

> **Подсказка:** Уже прикреплённые заявления отмечаются зелёной галочкой ✓ рядом с вложением — нажатие на неё открывает страницу заявления. Повторное прикрепление того же файла к тому же заявлению ничего не дублирует.

> **Доступ:** Кнопка доступна только при наличии права **«Загрузка файлов на заявление»** (`course.application.file_upload`). Оригинал письма и вложение остаются на месте — в заявление кладётся копия.

---

## Лист ожидания (Waitlist)

### Как работает

1. Когда все места на курсе заняты, новые заявления получают статус **Лист ожидания**.
2. На публичной форме регистрации отображается предупреждение.
3. Плательщик получает email о постановке в очередь.
4. При освобождении места следующее заявление из очереди **автоматически активируется**.
5. Администратор может **вручную активировать** заявление кнопкой на странице заявления (игнорируя лимит мест).

### Настройка

В форме курса, поле **Лимит листа ожидания**:
- **0** — лист ожидания отключён
- **> 0** — максимальное количество заявлений в очереди

---

## Пробный урок (Trial Lesson)

### Регистрация на пробный урок

1. На публичной форме или в кабинете плательщика выберите опцию **Пробный урок**.
2. Выберите дату пробного занятия.
3. Заявление получает статус **Пробный урок**.

### Подтверждение / Отказ

На странице заявления (или в кабинете плательщика):

**Подтвердить:**
1. Нажмите **Подтвердить**.
2. Выберите тариф оплаты.
3. Заявление → статус **Создано**, далее стандартный цикл.
4. Для «Всегда платный»: дата первого урока сдвигается на следующий после пробного.

**Отклонить:**
1. Нажмите **Отклонить**.
2. Заявление → статус **Закрыто**.
3. Для «Бесплатно, если останется»: создаётся счёт за пробный урок.

### Режимы оплаты

| Режим | При записи | При подтверждении | При отказе |
|-------|-----------|-------------------|------------|
| Бесплатно, если останется | Счёт не создаётся | Пробный бесплатен | Счёт создаётся |
| Всегда платный | Счёт создаётся сразу | Дата начала сдвигается | Доп. счёт не нужен |
| Всегда отдельный | Счёт создаётся сразу | Тариф выбирается отдельно | Доп. счёт не нужен |

---

## Шаблоны email-уведомлений

Система автоматически отправляет email при определённых действиях. Шаблоны настраиваются на вкладке «Шаблон» курса или в общих настройках.

### Шаблоны для плательщика

| Событие | Шаблон |
|---------|--------|
| Заявление создано | PAYER_COURSE_APPLICATION_STATUS_CREATED |
| Документ отправлен | PAYER_COURSE_APPLICATION_STATUS_SENT |
| Заявление подписано | PAYER_COURSE_APPLICATION_STATUS_SIGNED |
| Заявление закрыто | PAYER_COURSE_APPLICATION_STATUS_CLOSED |
| Заявление аннулировано | PAYER_COURSE_APPLICATION_STATUS_ANNULLED |
| Добавлено в лист ожидания | PAYER_COURSE_APPLICATION_STATUS_WAITLIST |
| Активировано из очереди | PAYER_COURSE_APPLICATION_STATUS_WAITLIST_ACTIVATED |
| Пробный урок создан | PAYER_TRIAL_LESSON_CREATED |

### Переменные шаблонов

В шаблонах можно использовать переменные в квадратных скобках:

| Переменная | Значение |
|------------|----------|
| `[childName]` | Полное имя студента |
| `[childFirstName]`, `[childLastName]` | Имя / фамилия студента |
| `[childCode]` | Личный код студента |
| `[payerName]` | Имя плательщика |
| `[payerEmail]`, `[payerPhone]` | Контакты плательщика |
| `[courseName]` | Название курса |
| `[applicationId]` | Номер заявления |
| `[applicationYear]` | Учебный год |
| `[applicationFirstLessonAtDate]` | Дата первого урока |
| `[applicationCloseDate]` | Дата закрытия |
| `[price]` | Базовая цена |
| `[pricePeriodName]` | Частота оплаты |
| `[priceEndNoVat]` | Итоговая цена |
| `[company_name]` | Название организации |
| `[company_email]`, `[company_phone]` | Контакты организации |

### Как отправляются письма

1. Система формирует содержание письма, подставляя переменные в шаблон.
2. Создаётся запись `OutboundMessage` в базе данных.
3. Файлы прикрепляются как `OutboundMessageAttachment` (если есть).
4. Фоновый процесс (Laravel Horizon) обрабатывает очередь и отправляет email.

> **Совет:** Если плательщик не получил письмо — проверьте очередь отправки в разделе **Уведомления → Список**.