Project

General

Profile

Task #6108

Updated by Redmine Admin 1 day ago

Сопутствующая задача к ТЗ от 24.08.2026. Фронтенд реализован полностью (#6093–#6107) и 24.08.2026 — фронтенд уже отправляет/читает перечисленные поля. Задача самодостаточна: всё, что нужно бэкенду, описано здесь. 

 ## 1. Новые поля волонтера 

 `/api/volunteers` (GET списком, POST, PUT) отправляет и волонтер внутри `/api/volunteer-applications`: читает эти поля, требуется поддержка на бэкенде. 

 | Поле | Тип | Смысл | **Волонтер (`/api/volunteers`, `/api/volunteer-applications`):** 
 |------|-----|-------| 
 | `helpDirections` | `string[]` | * `helpDirections: string[]` — направления волонтерской помощи, 16 помощи (16 значений справочника (см. ниже) | справочника, см. #6096) 
 * `missionParticipationConfirmed: boolean | `missionParticipationConfirmed` | `boolean \| null` |  подтверждение участия; **`null` участия в волонтерской миссии; `null` = статус не поставлен**, это отдельное состояние, не `false` | 
 | `volunteerMissionId` | `string \| null` | миссия, к которой привязан волонтер | 
 | `volunteerMissionShiftId` | `string \| null` | смена | поставлен 

 Справочник `helpDirections` (ключ → подпись, подписи используются в Excel): 
 `NO_SPECIALIZATION`, `CONSTRUCTION_REPAIR`, `ROOFING`, `WELDING`, `ELECTRICAL`, `PLUMBING`, `DRIVER_CAR_B`, `DRIVER_TRUCK_C`, `COOKING`, `MEDICAL_HELP`, `PSYCHOLOGICAL_HELP`, `LEGAL_HELP`, `LOADING_UNLOADING`, `LOGISTICS`, `CHILDREN_ELDERLY`, `MEDIA_VOLUNTEER`. 
 Правило целостности: `NO_SPECIALIZATION` не может встречаться вместе с любым другим значением (на фронте это гарантировано UI, на бэкенде — желательно валидацией, т.к. есть импорт). 

 ## 2. Заявка **Заявка из внешнего контура 

 `POST /api/volunteer-applications/outer_perimeter` (multipart/form-data) дополнительно получает: (`/api/volunteer-applications/outer_perimeter`):** 
 * `helpDirections` — **повторяющееся поле**, по одному значению на запись (не строка через запятую) 
 * `personalDataConsent` `personalDataConsent: boolean``"true"` / `"false"`, согласие на обработку ПД (#6105). Без отметки фронт не даёт отправить заявку; значение стоит сохранять как юридический факт с датой. персональных данных 

 ## 3. Проставление подтверждения участия из таблицы (#6099) 

 **Дополнительно:** 
 * `PATCH /api/volunteers/{id}/participation-confirmation` 
 Тело: `{ "missionParticipationConfirmed": true | false | null }` 

 **Решение на согласование:** эндпоинт придуман фронтендом. Если удобнееможно обойтись существующим `PUT /api/volunteers/{id}`, тогда правится один вызов в `VolunteersIndex.tsx` (`handleParticipationChange`). Отдельный PATCH выбран потому, что оператор меняет статус построчно и слать целого волонтера ради одного поля не хочется. 

 Фронт применяет изменение оптимистично и **откатывает проставление статуса из таблицы «Волонтеры» (#6099). Фронтенд при ошибке откатывает значение в UI при любой ошибке**, так что до реализации эндпоинта колонка визуально работает, но не сохраняет. 

 ## 4. Импорт 

 `POST /api/volunteer-missions/{id}/import-volunteers` — в объектах массива `volunteers` теперь приходят `helpDirections` и `missionParticipationConfirmed` (см. п.1). Тот же эндпоинт используется импортом со страницы «Волонтеры» (#6101). 

 ## 5. Nullable даты (#6093, #6094) 

 * `VolunteerMission.missionStartDate` / `missionEndDate` — nullable UI. 
 * `VolunteerMissionShift.departureDate` / `arrivalDate` — nullable 

 Фронт отправляет `null` при пустом значении и корректно отображает отсутствующие даты. 

 ## 6. Желательно (не блокирует) 

 `GET /api/volunteers` — желательно отдавать связанные `mission` (`id`, `name`, `missionStartDate`, `missionEndDate`) миссию/смену для отображения в списке и `shift` (`id`, `shiftNumber`). Сейчас карточка волонтера при отсутствии этих данных фильтров (#6098, #6102); сейчас фронтенд догружает последнюю заявку волонтера заявки отдельным запросом (`/api/volunteer-applications?volunteerId=...&size=1&sort=createdAt,desc`), а фильтр по запросом. 
 * Даты миссии на странице «Волонтеры» работает только по тем волонтерам, у кого связь пришла в списке. 

 ## Совместимость 

 Все новые поля читаются фронтендом защитно (отсутствующее значение = пусто), поэтому фронт можно выкатывать до бэкенда — ничего не сломается, новые поля просто не будут сохраняться. и смены должны стать nullable (#6093, #6094).

Back