Техническое задание: Система помощи питомцам (Pet Shelter Management)
1. Описание проекта
Веб-платформа для приюта животных: каталог питомцев, заявки на усыновление, управление волонтёрами и историями лечения. Проект закрепляет навыки CRUD, загрузки файлов, статусных переходов, разграничения прав и совместной работы через Git.
Команда: 2–3 человека
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. Маршруты и контроллеры
// Публичные маршруты
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
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 |
Правила
- Ветка
develop — основная ветка разработки
- Каждый участник создаёт фич-ветки от
develop
- Минимум 3 PR на участника
- Обязательный код-ревью перед мёржем
- Conventional Commits
Визуализация workflow (2 участника)
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 участника)
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. Критерии приёмки
Обязательно
Дополнительно (бонусные баллы)
9. Дополнительные задания (для продвинутых)
- Уведомления: email заявителю при изменении статуса заявки
- Совместимость: рекомендации питомцев заявителю на основе его опыта и условий
- Статистика приюта: дашборд с графиками (Chart.js) — усыновления по месяцам, популярные виды
- Тесты: PHPUnit Feature-тесты для статусных переходов заявок
- API: RESTful API для каталога питомцев и подачи заявок
- Queue: асинхронная отправка email-уведомлений
- Events & Listeners: событие «заявка одобрена» → обновление статуса питомца + email
10. Рекомендуемые материалы