laravel-12-tech-specs/task10-pet-shelter.md

433 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Техническое задание: Система помощи питомцам (Pet Shelter Management)
## 1. Описание проекта
Веб-платформа для приюта животных: каталог питомцев, заявки на усыновление, управление волонтёрами и историями лечения. Проект закрепляет навыки CRUD, загрузки файлов, статусных переходов, разграничения прав и совместной работы через Git.
**Команда:** 23 человека
---
## 2. Функциональные требования
### 2.1. Аутентификация и регистрация
- Регистрация, вход, выход (Laravel Breeze)
### 2.2. Каталог питомцев
- Просмотр списка питомцев с пагинацией
- Фильтрация по видам (кошки, собаки, грызуны, птицы, рептилии)
- Поиск по кличке, породе
- Детальная страница питомца (фото, описание, вид, порода, возраст, пол, статус, истории лечения)
### 2.3. Управление питомцами (волонтёр/админ)
- CRUD питомцев: кличка, вид, порода, возраст (примерный), пол, описание, фото (до 3), статус (доступен для усыновления, на лечении, усыновлён)
- Загрузка фотографий питомца (валидация: jpg/png, макс. 2MB на каждое фото)
- Особенности характера (свободный текст или теги)
### 2.4. Категории питомцев
- CRUD категорий (видов): кошки, собаки, грызуны, птицы, рептилии
- Описание вида, особенности содержания
### 2.5. Заявки на усыновление
- Форма заявки: данные заявителя (ФИО, телефон, email, адрес), опыт содержания, цель усыновления, условия содержания
- Привязка заявки к питомцу
- Статусы заявки: новая, на рассмотрении, одобрена, отклонена, завершена
- Волонтёр меняет статус заявки (новая → на рассмотрении → одобрена/отклонена)
- При одобрении — питомец получает статус «усыновлён»
- При отклонении — комментарий с причиной
### 2.6. Волонтёры
- Профиль волонтёра: имя, телефон, email, дата начала волонтёрства, статус (активен/неактивен)
- Расписание волонтёра: дата, время, тип деятельности (выгул, кормление, уборка)
- CRUD расписания (волонтёр создаёт свои смены)
### 2.7. Истории питомцев
- Записи о здоровье питомца: дата, описание (лечение, вакцинация, осмотр, операция)
- Привязка к питомцу
- Хронология на странице питомца
### 2.8. Панель волонтёра
- Мои питомцы (за которыми закреплён)
- Входящие заявки на усыновление (управление статусами)
- Моё расписание
- Добавление историй питомцев
### 2.9. Панель потенциального хозяина
- Каталог питомцев
- Мои заявки на усыновление (статусы)
- Создание новой заявки
### 2.10. Панель администратора
- Управление пользователями и ролями
- Управление категориями питомцев
- Модерация заявок
- Общая статистика приюта
---
## 3. Структура базы данных
### Таблица `users`
| Поле | Тип | Описание |
|---|---|---|
| id | BIGINT UNSIGNED | Первичный ключ |
| name | VARCHAR(255) | Имя |
| email | VARCHAR(255) | Email (unique) |
| password | VARCHAR(255) | Хеш пароля |
| role | ENUM('admin', 'volunteer', 'adopter') | Роль |
| phone | VARCHAR(20) \| NULL | Телефон |
| avatar | VARCHAR(255) \| NULL | Аватар |
| volunteer_start_date | DATE \| NULL | Дата начала волонтёрства (для волонтёров) |
| is_active | BOOLEAN | Активен ли (для волонтёров) |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### Таблица `pet_categories`
| Поле | Тип | Описание |
|---|---|---|
| id | BIGINT UNSIGNED | Первичный ключ |
| name | VARCHAR(255) | Название вида (кошки, собаки, ...) |
| slug | VARCHAR(255) | URL-идентификатор (unique) |
| description | TEXT \| NULL | Описание вида |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### Таблица `pets`
| Поле | Тип | Описание |
|---|---|---|
| id | BIGINT UNSIGNED | Первичный ключ |
| name | VARCHAR(255) | Кличка питомца |
| slug | VARCHAR(255) | URL-идентификатор (unique) |
| species_id | BIGINT UNSIGNED | Вид (FK → pet_categories) |
| breed | VARCHAR(255) \| NULL | Порода |
| age_estimate | VARCHAR(50) | Примерный возраст (например, «2 года», «6 месяцев») |
| gender | ENUM('male', 'female') | Пол |
| description | TEXT | Описание, особенности характера |
| status | ENUM('available', 'treatment', 'adopted', 'reserved') | Статус |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### Таблица `pet_photos`
| Поле | Тип | Описание |
|---|---|---|
| id | BIGINT UNSIGNED | Первичный ключ |
| pet_id | BIGINT UNSIGNED | FK → pets |
| photo_path | VARCHAR(255) | Путь к изображению |
| is_primary | BOOLEAN | Главное фото (true/false) |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### Таблица `adoption_applications`
| Поле | Тип | Описание |
|---|---|---|
| id | BIGINT UNSIGNED | Первичный ключ |
| pet_id | BIGINT UNSIGNED | Питомец (FK → pets) |
| applicant_id | BIGINT UNSIGNED | Заявитель (FK → users) |
| full_name | VARCHAR(255) | ФИО заявителя |
| phone | VARCHAR(20) | Телефон |
| email | VARCHAR(255) | Email |
| address | TEXT | Адрес проживания |
| experience | TEXT | Опыт содержания животных |
| purpose | TEXT | Цель усыновления |
| living_conditions | TEXT | Условия содержания |
| status | ENUM('new', 'under_review', 'approved', 'rejected', 'completed') | Статус |
| rejection_reason | TEXT \| NULL | Причина отклонения |
| volunteer_notes | TEXT \| NULL | Заметки волонтёра |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### Таблица `volunteer_schedules`
| Поле | Тип | Описание |
|---|---|---|
| id | BIGINT UNSIGNED | Первичный ключ |
| volunteer_id | BIGINT UNSIGNED | Волонтёр (FK → users) |
| pet_id | BIGINT UNSIGNED \| NULL | Питомец (FK → pets), NULL если общая смена |
| schedule_date | DATE | Дата смены |
| start_time | TIME | Время начала |
| end_time | TIME | Время окончания |
| activity_type | ENUM('walking', 'feeding', 'cleaning', 'grooming', 'other') | Тип деятельности |
| notes | TEXT \| NULL | Заметки |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### Таблица `pet_histories`
| Поле | Тип | Описание |
|---|---|---|
| id | BIGINT UNSIGNED | Первичный ключ |
| pet_id | BIGINT UNSIGNED | FK → pets |
| history_date | DATE | Дата записи |
| type | ENUM('vaccination', 'treatment', 'examination', 'surgery', 'other') | Тип записи |
| description | TEXT | Описание |
| veterinarian | VARCHAR(255) \| NULL | Ветеринар |
| created_by | BIGINT UNSIGNED | Создатель записи (FK → users) |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
---
## 4. Маршруты и контроллеры
```php
// Публичные маршруты
Route::get('/', [PetController::class, 'index'])->name('pets.index');
Route::get('/pets/{pet:slug}', [PetController::class, 'show'])->name('pets.show');
// Аутентифицированные маршруты
Route::middleware('auth')->group(function () {
// Заявки на усыновление
Route::prefix('applications')->name('applications.')->group(function () {
Route::post('/apply/{pet}', [ApplicationController::class, 'store'])->name('apply');
Route::get('/my-applications', [ApplicationController::class, 'myApplications'])->name('my');
Route::get('/{application}', [ApplicationController::class, 'show'])->name('show');
});
// Расписание волонтёра
Route::prefix('volunteer')->name('volunteer.')->middleware('can:be-volunteer')->group(function () {
Route::resource('schedules', VolunteerScheduleController::class);
Route::get('dashboard', [VolunteerDashboardController::class, 'index'])->name('dashboard');
});
// Управление питомцами (волонтёр/админ)
Route::prefix('shelter')->name('shelter.')->middleware('can:manage-pets')->group(function () {
Route::resource('pets', ShelterPetController::class);
Route::resource('pets.photos', PetPhotoController::class)->scoped(['pets' => 'pet']);
Route::resource('pets.histories', PetHistoryController::class)->scoped(['pets' => 'pet']);
// Управление заявками
Route::get('applications', [ShelterApplicationController::class, 'index'])->name('applications.index');
Route::get('applications/{application}', [ShelterApplicationController::class, 'show'])->name('applications.show');
Route::post('applications/{application}/review', [ShelterApplicationController::class, 'startReview'])->name('applications.review');
Route::post('applications/{application}/approve', [ShelterApplicationController::class, 'approve'])->name('applications.approve');
Route::post('applications/{application}/reject', [ShelterApplicationController::class, 'reject'])->name('applications.reject');
Route::post('applications/{application}/complete', [ShelterApplicationController::class, 'complete'])->name('applications.complete');
});
// Админка
Route::prefix('admin')->name('admin.')->middleware('can:access-admin-panel')->group(function () {
Route::resource('users', AdminUserController::class);
Route::resource('categories', AdminCategoryController::class);
Route::get('dashboard', [AdminDashboardController::class, 'index'])->name('dashboard');
});
});
```
### Контроллеры
- `PetController` — публичный каталог и детальный просмотр
- `ApplicationController` — подача и просмотр своих заявок
- `VolunteerScheduleController` — CRUD расписания волонтёра
- `ShelterPetController` — CRUD питомцев (волонтёр/админ)
- `PetPhotoController` — загрузка/удаление фото питомца
- `PetHistoryController` — CRUD историй питомца
- `ShelterApplicationController` — управление заявками (смена статусов)
- `VolunteerDashboardController`, `AdminUserController`, `AdminCategoryController`, `AdminDashboardController` — панели
---
## 5. Роли, Gates и Policies
### Роли
| Роль | Описание |
|---|---|
| `admin` | Полный доступ, управление пользователями, категориями, модерация |
| `volunteer` | Управление питомцами, заявками, расписанием, историями питомцев |
| `adopter` | Просмотр каталога, подача заявок на усыновление, просмотр своих заявок |
### Gates
```php
Gate::define('be-volunteer', function (User $user) {
return in_array($user->role, ['admin', 'volunteer']);
});
Gate::define('manage-pets', function (User $user) {
return in_array($user->role, ['admin', 'volunteer']);
});
Gate::define('access-admin-panel', function (User $user) {
return $user->role === 'admin';
});
```
### Policies
**PetPolicy:**
- `view` — все (публичный каталог)
- `create`, `update`, `delete` — volunteer или admin
**PetPhotoPolicy:**
- `create`, `delete` — volunteer или admin
**PetHistoryPolicy:**
- `create`, `update`, `delete` — volunteer или admin
- `view` — все
**AdoptionApplicationPolicy:**
- `create` — adopter (не подавал одобренную заявку на этого питомца)
- `view` — заявитель, волонтёр/admin
- `review`, `approve`, `reject`, `complete` — volunteer или admin
**VolunteerSchedulePolicy:**
- `create`, `update`, `delete` — владелец расписания (волонтёр) или admin
- `view` — volunteer или admin
---
## 6. Требования к интерфейсу (Bootstrap 5)
### Компоненты
- **Навбар** — логотип, каталог питомцев, «Мои заявки», панель волонтёра, профиль
- **Карточки питомцев** — главное фото, кличка, вид (бейдж), порода, возраст, статус (бейдж)
- **Страница питомца** — галерея фото (карусель или грид), описание, характеристики, кнопка «Усыновить», истории питомца (хронология)
- **Карусель фото** — Bootstrap Carousel для галереи питомца
- **Форма заявки** — Bootstrap-форма с валидацией, textarea для опыта и условий
- **Таблица заявок** — питомец, заявитель, статус (цветные бейджи), действия
- **Календарь/таблица расписания** — дата, время, тип деятельности
- **Хронология историй** — вертикальный timeline (Bootstrap + кастомные стили)
- **Дашборд волонтёра** — статистика (карточки), входящие заявки, ближайшее расписание
- **Адаптивная сетка** — `col-md-4` для карточек, `col-md-8` + `col-md-4` для основного контента
### Цветовая схема статусов питомца
- Доступен — `bg-success`
- На лечении — `bg-warning`
- Усыновлён — `bg-primary`
- Зарезервирован — `bg-info`
### Цветовая схема статусов заявки
- Новая — `bg-info`
- На рассмотрении — `bg-warning`
- Одобрена — `bg-success`
- Отклонена — `bg-danger`
- Завершена — `bg-secondary`
---
## 7. Git-workflow для команды
### Распределение модулей (для 2 человек)
| Участник | Модуль | Ветки |
|---|---|---|
| **Участник A** | Питомцы, категории, фото, заявки на усыновление | `feature/pets-crud`, `feature-categories`, `feature-pet-photos` |
| **Участник B** | Расписание волонтёра, истории, дашборд, UI | `feature/applications`, `feature-application-statuses`, `feature-approval-flow` |
### Распределение модулей (для 3 человек)
| Участник | Модуль | Ветки |
|---|---|---|
| **Участник A** | Питомцы, категории, загрузка фото, каталог | `feature/pets-crud`, `feature-categories`, `feature-pet-photos` |
| **Участник B** | Заявки на усыновление, статусные переходы | `feature/applications`, `feature-application-statuses`, `feature-approval-flow` |
| **Участник C** | Расписание волонтёра, истории питомцев, UI, дашборд | `feature-volunteer-schedules`, `feature-pet-histories`, `feature-dashboard-ui` |
### Правила
1. Ветка `develop` — основная ветка разработки
2. Каждый участник создаёт фич-ветки от `develop`
3. Минимум 3 PR на участника
4. Обязательный код-ревью перед мёржем
5. Conventional Commits
### Визуализация workflow (2 участника)
```mermaid
gitGraph
commit id: "init" tag: "v1.0"
branch develop
checkout develop
branch feature/pets-crud
checkout develop
branch feature/applications
checkout feature/pets-crud
commit id: "feat: add pets CRUD"
commit id: "feat: add pet photos"
checkout feature/applications
commit id: "feat: add adoption applications"
commit id: "feat: add application statuses"
checkout develop
merge feature/pets-crud tag: "PR + review"
merge feature/applications tag: "PR + review"
checkout main
merge develop tag: "release v1.1"
```
### Визуализация workflow (3 участника)
```mermaid
gitGraph
commit id: "init" tag: "v1.0"
branch develop
checkout develop
branch feature/pets-crud
checkout develop
branch feature/applications
checkout develop
branch feature-volunteer-schedules
checkout feature/pets-crud
commit id: "feat: add pets CRUD"
commit id: "feat: add pet categories"
checkout feature/applications
commit id: "feat: add adoption applications"
commit id: "feat: add application statuses"
checkout feature-volunteer-schedules
commit id: "feat: add volunteer schedules"
commit id: "feat: add pet histories"
checkout develop
merge feature/pets-crud tag: "PR + review"
merge feature/applications tag: "PR + review"
merge feature-volunteer-schedules tag: "PR + review"
checkout main
merge develop tag: "release v1.1"
```
---
## 8. Критерии приёмки
### Обязательно
- [ ] CRUD питомцев с загрузкой фото (до 3 фото на питомца)
- [ ] CRUD категорий питомцев
- [ ] Каталог питомцев с пагинацией и фильтрацией по видам
- [ ] Подача заявки на усыновление (форма с валидацией всех полей)
- [ ] Просмотр своих заявок (заявитель)
- [ ] Управление статусами заявок волонтёром (новая → на рассмотрении → одобрена/отклонена)
- [ ] При одобрении заявки — обновление статуса питомца на «adopted»
- [ ] При отклонении — обязательная причина
- [ ] CRUD расписания волонтёра
- [ ] CRUD историй питомцев (лечение, вакцинация, осмотр)
- [ ] Панель волонтёра (мои питомцы, заявки, расписание)
- [ ] Policies: adoptter не может управлять питомцами или заявками
- [ ] Адаптивная Bootstrap-вёрстка
- [ ] Flash-сообщения
- [ ] Git-история: минимум 3 ветки на участника, PR с ревью
### Дополнительно (бонусные баллы)
- [ ] Поиск питомцев по кличке и породе
- [ ] Фильтрация по возрасту и полу
- [ ] Галерея фото (Bootstrap Carousel)
- [ ] Экспорт расписания волонтёра в PDF
- [ ] Уведомления (email при изменении статуса заявки)
- [ ] Мягкое удаление питомцев и историй
- [ ] Тесты: PHPUnit Feature-тесты для ApplicationController
- [ ] API: RESTful API для каталога питомцев
---
## 9. Дополнительные задания (для продвинутых)
1. **Уведомления:** email заявителю при изменении статуса заявки
2. **Совместимость:** рекомендации питомцев заявителю на основе его опыта и условий
3. **Статистика приюта:** дашборд с графиками (Chart.js) — усыновления по месяцам, популярные виды
4. **Тесты:** PHPUnit Feature-тесты для статусных переходов заявок
5. **API:** RESTful API для каталога питомцев и подачи заявок
6. **Queue:** асинхронная отправка email-уведомлений
7. **Events & Listeners:** событие «заявка одобрена» → обновление статуса питомца + email
---
## 10. Рекомендуемые материалы
- Laravel Docs: https://laravel.com/docs/12.x
- Laravel File Uploads (multiple): https://laravel.com/docs/12.x/filesystem#file-uploads
- Bootstrap 5 Carousel: https://getbootstrap.com/docs/5.3/components/carousel/
- Bootstrap 5 Badges: https://getbootstrap.com/docs/5.3/components/badge/
- Laravel Policies: https://laravel.com/docs/12.x/authorization#creating-policies
- State Machines (статусные переходы): https://github.com/brentroose/laravel-state-machine