# Техническое задание: Система бронирования помещений и оборудования ## 1. Описание проекта Веб-приложение для бронирования конференц-залов, рабочих мест или оборудования с календарём, подтверждением заявок и управлением расписанием. Проект закрепляет навыки CRUD, валидации дат и времени, разграничения прав и совместной работы через Git. **Команда:** 2–3 человека --- ## 2. Функциональные требования ### 2.1. Аутентификация и регистрация - Регистрация, вход, выход (Laravel Breeze) ### 2.2. Каталог ресурсов - Просмотр списка доступных ресурсов (помещения, оборудование) - Фильтрация по категориям (конференц-залы, переговорки, проекторы, ноутбуки) - Детальная страница ресурса (описание, вместимость, фото, календарь бронирований) - Поиск по названию ресурса ### 2.3. Управление ресурсами (админ) - CRUD ресурсов: название, описание, категория, вместимость/количество, изображение, доступен ли - CRUD категорий ресурсов - Загрузка изображений ресурсов ### 2.4. Бронирование - Создание заявки на бронирование: ресурс, дата начала, дата окончания (или время), цель - **Валидация:** проверка на пересечение с существующими бронированиями того же ресурса - Просмотр своих бронирований (статусы: ожидание, подтверждено, отклонено, завершено, отменено) - Отмена бронирования (пользователь — если статус «ожидание») - Календарь бронирований ресурса (визуальное отображение занятых дат) ### 2.5. Управление бронированиями (модератор/админ) - Просмотр всех бронирований - Подтверждение/отклонение заявки - Изменение дат бронирования - Отмена бронирования с комментарием ### 2.6. Дашборд модератора - Статистика: количество ресурсов, бронирований (по статусам) - Последние заявки, ожидающие подтверждения - Популярные ресурсы ### 2.7. Дашборд пользователя - Мои активные бронирования - История бронирований - Быстрая ссылка на создание заявки --- ## 3. Структура базы данных ### Таблица `users` | Поле | Тип | Описание | |---|---|---| | id | BIGINT UNSIGNED | Первичный ключ | | name | VARCHAR(255) | Имя | | email | VARCHAR(255) | Email (unique) | | password | VARCHAR(255) | Хеш пароля | | role | ENUM('admin', 'moderator', 'user') | Роль | | phone | VARCHAR(20) \| NULL | Телефон | | created_at | TIMESTAMP | | | updated_at | TIMESTAMP | | ### Таблица `resource_categories` | Поле | Тип | Описание | |---|---|---| | id | BIGINT UNSIGNED | Первичный ключ | | name | VARCHAR(255) | Название категории | | slug | VARCHAR(255) | URL-идентификатор (unique) | | created_at | TIMESTAMP | | | updated_at | TIMESTAMP | | ### Таблица `resources` | Поле | Тип | Описание | |---|---|---| | id | BIGINT UNSIGNED | Первичный ключ | | name | VARCHAR(255) | Название ресурса | | slug | VARCHAR(255) | URL-идентификатор (unique) | | description | TEXT | Описание | | category_id | BIGINT UNSIGNED | Категория (FK → resource_categories) | | capacity | INT \| NULL | Вместимость (для помещений) | | quantity | INT \| NULL | Количество (для оборудования) | | image | VARCHAR(255) \| NULL | Изображение | | is_available | BOOLEAN | Доступен для бронирования | | created_at | TIMESTAMP | | | updated_at | TIMESTAMP | | ### Таблица `bookings` | Поле | Тип | Описание | |---|---|---| | id | BIGINT UNSIGNED | Первичный ключ | | resource_id | BIGINT UNSIGNED | Ресурс (FK → resources) | | user_id | BIGINT UNSIGNED | Инициатор (FK → users) | | start_datetime | DATETIME | Дата и время начала | | end_datetime | DATETIME | Дата и время окончания | | purpose | TEXT | Цель бронирования | | status | ENUM('pending', 'confirmed', 'rejected', 'completed', 'cancelled') | Статус | | rejection_reason | TEXT \| NULL | Причина отклонения | | created_at | TIMESTAMP | | | updated_at | TIMESTAMP | | --- ## 4. Маршруты и контроллеры ```php // Публичные маршруты Route::get('/', [ResourceController::class, 'index'])->name('resources.index'); Route::get('/resources/{resource:slug}', [ResourceController::class, 'show'])->name('resources.show'); Route::get('/resources/{resource:slug}/calendar', [ResourceController::class, 'calendar'])->name('resources.calendar'); // Аутентифицированные маршруты Route::middleware('auth')->group(function () { // Бронирования пользователя Route::get('/my-bookings', [BookingController::class, 'myBookings'])->name('bookings.my'); Route::resource('bookings', BookingController::class)->except(['index', 'show']); Route::post('/bookings/{booking}/cancel', [BookingController::class, 'cancel'])->name('bookings.cancel'); // Панель модератора Route::prefix('moderator')->name('moderator.')->middleware('can:be-moderator')->group(function () { Route::get('dashboard', [ModeratorDashboardController::class, 'index'])->name('dashboard'); Route::get('bookings', [ModeratorBookingController::class, 'index'])->name('bookings.index'); Route::get('bookings/{booking}', [ModeratorBookingController::class, 'show'])->name('bookings.show'); Route::post('bookings/{booking}/confirm', [ModeratorBookingController::class, 'confirm'])->name('bookings.confirm'); Route::post('bookings/{booking}/reject', [ModeratorBookingController::class, 'reject'])->name('bookings.reject'); }); // Админка Route::prefix('admin')->name('admin.')->middleware('can:access-admin-panel')->group(function () { Route::resource('resources', AdminResourceController::class); Route::resource('categories', AdminCategoryController::class); Route::resource('users', AdminUserController::class); Route::get('dashboard', [AdminDashboardController::class, 'index'])->name('dashboard'); }); }); ``` ### Контроллеры - `ResourceController` — публичный каталог и календарь бронирований - `BookingController` — создание/отмена бронирований, мои бронирования - `ModeratorBookingController` — просмотр, подтверждение, отклонение - `ModeratorDashboardController` — панель модератора - `AdminResourceController` — CRUD ресурсов - `AdminCategoryController` — CRUD категорий - `AdminUserController`, `AdminDashboardController` — админка --- ## 5. Роли, Gates и Policies ### Роли | Роль | Описание | |---|---| | `admin` | Полный доступ, управление ресурсами, категориями, пользователями | | `moderator` | Подтверждение/отклонение бронирований, управление расписанием | | `user` | Создание бронирований, просмотр своих бронирований и доступных ресурсов | ### Gates ```php Gate::define('be-moderator', function (User $user) { return in_array($user->role, ['admin', 'moderator']); }); Gate::define('access-admin-panel', function (User $user) { return $user->role === 'admin'; }); ``` ### Policies **ResourcePolicy:** - `view` — все аутентифицированные - `create`, `update`, `delete` — только admin **BookingPolicy:** - `create` — все аутентифицированные (если ресурс доступен) - `view` — владелец бронирования или moderator/admin - `update` — moderator/admin (даты) или владелец (только если status = pending) - `cancel` — владелец (если status = pending или confirmed) или moderator/admin - `confirm`, `reject` — только moderator или admin --- ## 6. Требования к интерфейсу (Bootstrap 5) ### Компоненты - **Навбар** — логотип, каталог ресурсов, «Мои бронирования», профиль - **Карточки ресурсов** — изображение, название, категория (бейдж), вместимость - **Форма бронирования** — выбор ресурса, дата/время начала и окончания (input type="datetime-local"), цель - **Календарь ресурса** — таблица или упрощённый календарь с подсветкой занятых дней - **Таблица бронирований** — ресурс, даты, статус (цветные бейджи), действия - **Модальное окно** — подтверждение/отклонение бронирования (с полем причины) - **Дашборд** — карточки статистики (`card` + `row`/`col`) - **Алерты** — flash-сообщения об успехе/ошибке ### Цветовая схема статусов бронирования - Ожидание — `bg-warning` - Подтверждено — `bg-success` - Отклонено — `bg-danger` - Завершено — `bg-secondary` - Отменено — `bg-light text-muted` ### Валидация формы бронирования - Дата начала — не в прошлом - Дата окончания — позже даты начала - Сообщение об ошибке при пересечении с существующим бронированием --- ## 7. Git-workflow для команды ### Распределение модулей (для 2 человек) | Участник | Модуль | Ветки | |---|---|---| | **Участник A** | Ресурсы, категории, изображения, календарь | `feature/resources-crud`, `feature/categories`, `feature-resource-images` | | **Участник B** | Бронирования, валидация, модерация, дашборды | `feature/bookings-crud`, `feature-booking-validation`, `feature-booking-calendar` | ### Распределение модулей (для 3 человек) | Участник | Модуль | Ветки | |---|---|---| | **Участник A** | Ресурсы, категории, загрузка изображений | `feature/resources-crud`, `feature/categories`, `feature-resource-images` | | **Участник B** | Бронирования, валидация пересечений, календарь | `feature/bookings-crud`, `feature-booking-validation`, `feature-booking-calendar` | | **Участник C** | Управление бронированиями (модератор), дашборды | `feature/moderator-panel`, `feature/dashboards`, `feature-booking-statuses` | ### Правила 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/resources-crud checkout develop branch feature/bookings-crud checkout feature/resources-crud commit id: "feat: add resources CRUD" commit id: "feat: add resource categories" checkout feature/bookings-crud commit id: "feat: add bookings CRUD" commit id: "feat: add booking validation" checkout develop merge feature/resources-crud tag: "PR + review" merge feature/bookings-crud 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/resources-crud checkout develop branch feature/bookings-crud checkout develop branch feature/moderator-panel checkout feature/resources-crud commit id: "feat: add resources CRUD" commit id: "feat: add booking calendar" checkout feature/bookings-crud commit id: "feat: add bookings CRUD" commit id: "feat: add booking validation" checkout feature/moderator-panel commit id: "feat: add moderator panel" commit id: "feat: add booking statuses" checkout develop merge feature/resources-crud tag: "PR + review" merge feature/bookings-crud tag: "PR + review" merge feature/moderator-panel tag: "PR + review" checkout main merge develop tag: "release v1.1" ``` --- ## 8. Критерии приёмки ### Обязательно - [ ] CRUD ресурсов с загрузкой изображений - [ ] CRUD категорий ресурсов - [ ] Создание бронирования с валидацией дат (не в прошлом, окончание > начала) - [ ] **Валидация пересечения:** нельзя забронировать ресурс на время, которое уже занято - [ ] Отмена бронирования пользователем (если статус «ожидание») - [ ] Подтверждение/отклонение бронирования модератором - [ ] Просмотр своих бронирований (фильтрация по статусу) - [ ] Календарь бронирований ресурса (визуальное отображение) - [ ] Policies: пользователь не может управлять чужими бронированиями - [ ] Адаптивная Bootstrap-вёрстка - [ ] Flash-сообщения - [ ] Пагинация каталога ресурсов и списка бронирований - [ ] Git-история: минимум 3 ветки на участника, PR с ревью ### Дополнительно (бонусные баллы) - [ ] Повторяющиеся бронирования (еженедельно, ежемесячно) - [ ] Уведомления (email при подтверждении/отклонении) - [ ] Экспорт бронирований в CSV/ICS (календарь) - [ ] Поиск ресурсов по названию - [ ] Фильтрация по вместимости - [ ] Рейтинг ресурсов (пользователи оценивают) - [ ] Soft Deletes для ресурсов --- ## 9. Дополнительные задания (для продвинутых) 1. **Повторяющиеся бронирования:** возможность забронировать ресурс на каждую неделю/месяц 2. **Уведомления:** email при подтверждении/отклонении/напоминании за день 3. **ICS-экспорт:** генерация .ics-файла для добавления в Google/Apple Calendar 4. **Конфликты:** визуальное отображение конфликтов при создании бронирования 5. **Тесты:** PHPUnit Feature-тесты для BookingController (валидация пересечений) 6. **API:** RESTful API для каталога ресурсов и создания бронирований 7. **Queue:** асинхронная отправка email-уведомлений --- ## 10. Рекомендуемые материалы - Laravel Docs: https://laravel.com/docs/12.x - Laravel Validation (custom rules): https://laravel.com/docs/12.x/validation#custom-validation-rules - Bootstrap 5 Forms: https://getbootstrap.com/docs/5.3/forms/overview/ - Carbon (работа с датами): https://carbon.nesbot.com/docs/ - Laravel Policies: https://laravel.com/docs/12.x/authorization#creating-policies