377 lines
17 KiB
Markdown
377 lines
17 KiB
Markdown
# Техническое задание: Онлайн-магазин с корзиной
|
||
|
||
## 1. Описание проекта
|
||
|
||
Веб-приложение интернет-магазина с каталогом товаров, корзиной покупок и оформлением заказов. Проект закрепляет навыки CRUD, работы с отношениями многие-ко-многим, загрузки изображений, разграничения прав и совместной работы через Git.
|
||
|
||
**Команда:** 2–3 человека
|
||
|
||
---
|
||
|
||
## 2. Функциональные требования
|
||
|
||
### 2.1. Аутентификация и регистрация
|
||
- Регистрация, вход, выход (Laravel Breeze)
|
||
- Восстановление пароля (опционально)
|
||
|
||
### 2.2. Каталог товаров
|
||
- Просмотр списка товаров с пагинацией
|
||
- Детальная страница товара
|
||
- Фильтрация по категориям
|
||
- Поиск по названию и описанию
|
||
- Сортировка по цене, дате добавления, названию
|
||
|
||
### 2.3. Управление товарами (админка)
|
||
- CRUD товаров: название, описание, цена, изображение, количество на складе, наличие
|
||
- CRUD категорий товаров
|
||
- Загрузка изображений товаров (валидация: jpg/png, макс. 2MB)
|
||
- Привязка товара к нескольким категориям
|
||
|
||
### 2.4. Корзина
|
||
- Добавление товара в корзину (количество)
|
||
- Изменение количества в корзине
|
||
- Удаление позиции из корзины
|
||
- Отображение итоговой суммы
|
||
- Корзина сохраняется в сессии (для гостей) или в БД (для авторизованных)
|
||
|
||
### 2.5. Оформление заказа
|
||
- Форма оформления заказа: имя, телефон, email, адрес доставки, комментарий
|
||
- Перенос позиций корзины в заказ
|
||
- Очистка корзины после оформления
|
||
- Просмотр своих заказов (покупатель)
|
||
|
||
### 2.6. Управление заказами (админка)
|
||
- Просмотр списка всех заказов
|
||
- Изменение статуса заказа (новый, в обработке, отправлен, доставлен, отменён)
|
||
- Детали заказа (список товаров, сумма, данные покупателя)
|
||
|
||
### 2.7. Дашборд администратора
|
||
- Статистика: количество товаров, заказов, пользователей
|
||
- Последние заказы
|
||
- Товары, заканчивающиеся на складе
|
||
|
||
---
|
||
|
||
## 3. Структура базы данных
|
||
|
||
### Таблица `users`
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| id | BIGINT UNSIGNED | Первичный ключ |
|
||
| name | VARCHAR(255) | Имя |
|
||
| email | VARCHAR(255) | Email (unique) |
|
||
| password | VARCHAR(255) | Хеш пароля |
|
||
| role | ENUM('admin', 'order_manager', 'customer') | Роль |
|
||
| phone | VARCHAR(20) \| NULL | Телефон |
|
||
| created_at | TIMESTAMP | |
|
||
| updated_at | TIMESTAMP | |
|
||
|
||
### Таблица `categories`
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| id | BIGINT UNSIGNED | Первичный ключ |
|
||
| name | VARCHAR(255) | Название категории |
|
||
| slug | VARCHAR(255) | URL-идентификатор (unique) |
|
||
| description | TEXT \| NULL | Описание |
|
||
| created_at | TIMESTAMP | |
|
||
| updated_at | TIMESTAMP | |
|
||
|
||
### Таблица `products`
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| id | BIGINT UNSIGNED | Первичный ключ |
|
||
| name | VARCHAR(255) | Название товара |
|
||
| slug | VARCHAR(255) | URL-идентификатор (unique) |
|
||
| description | TEXT | Описание |
|
||
| price | DECIMAL(10, 2) | Цена |
|
||
| image | VARCHAR(255) \| NULL | Путь к изображению |
|
||
| stock_quantity | INT | Количество на складе |
|
||
| is_available | BOOLEAN | Доступен для покупки |
|
||
| created_at | TIMESTAMP | |
|
||
| updated_at | TIMESTAMP | |
|
||
|
||
### Таблица `category_product` (многие-ко-многим)
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| category_id | BIGINT UNSIGNED | FK → categories |
|
||
| product_id | BIGINT UNSIGNED | FK → products |
|
||
|
||
### Таблица `carts`
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| id | BIGINT UNSIGNED | Первичный ключ |
|
||
| user_id | BIGINT UNSIGNED \| NULL | Пользователь (FK → users), NULL для гостей |
|
||
| session_id | VARCHAR(255) \| NULL | ID сессии для гостей |
|
||
| created_at | TIMESTAMP | |
|
||
| updated_at | TIMESTAMP | |
|
||
|
||
### Таблица `cart_items`
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| id | BIGINT UNSIGNED | Первичный ключ |
|
||
| cart_id | BIGINT UNSIGNED | FK → carts |
|
||
| product_id | BIGINT UNSIGNED | FK → products |
|
||
| quantity | INT | Количество |
|
||
|
||
### Таблица `orders`
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| id | BIGINT UNSIGNED | Первичный ключ |
|
||
| user_id | BIGINT UNSIGNED \| NULL | Покупатель (FK → users) |
|
||
| total_amount | DECIMAL(10, 2) | Итоговая сумма |
|
||
| status | ENUM('new', 'processing', 'shipped', 'delivered', 'cancelled') | Статус |
|
||
| customer_name | VARCHAR(255) | Имя получателя |
|
||
| customer_phone | VARCHAR(20) | Телефон |
|
||
| customer_email | VARCHAR(255) | Email |
|
||
| shipping_address | TEXT | Адрес доставки |
|
||
| comment | TEXT \| NULL | Комментарий |
|
||
| created_at | TIMESTAMP | |
|
||
| updated_at | TIMESTAMP | |
|
||
|
||
### Таблица `order_items`
|
||
| Поле | Тип | Описание |
|
||
|---|---|---|
|
||
| id | BIGINT UNSIGNED | Первичный ключ |
|
||
| order_id | BIGINT UNSIGNED | FK → orders |
|
||
| product_id | BIGINT UNSIGNED | FK → products |
|
||
| quantity | INT | Количество |
|
||
| price | DECIMAL(10, 2) | Цена на момент заказа |
|
||
|
||
---
|
||
|
||
## 4. Маршруты и контроллеры
|
||
|
||
```php
|
||
// Публичные маршруты
|
||
Route::get('/', [ProductController::class, 'index'])->name('home');
|
||
Route::get('/products/{product:slug}', [ProductController::class, 'show'])->name('products.show');
|
||
|
||
// Корзина
|
||
Route::prefix('cart')->name('cart.')->group(function () {
|
||
Route::get('/', [CartController::class, 'index'])->name('index');
|
||
Route::post('/add/{product}', [CartController::class, 'add'])->name('add');
|
||
Route::patch('/update/{cartItem}', [CartController::class, 'update'])->name('update');
|
||
Route::delete('/remove/{cartItem}', [CartController::class, 'remove'])->name('remove');
|
||
});
|
||
|
||
// Аутентифицированные маршруты
|
||
Route::middleware('auth')->group(function () {
|
||
// Оформление заказа
|
||
Route::get('/checkout', [OrderController::class, 'create'])->name('checkout');
|
||
Route::post('/checkout', [OrderController::class, 'store'])->name('checkout.store');
|
||
Route::get('/my-orders', [OrderController::class, 'myOrders'])->name('orders.my');
|
||
Route::get('/my-orders/{order}', [OrderController::class, 'show'])->name('orders.show');
|
||
|
||
// Админка
|
||
Route::prefix('admin')->name('admin.')->middleware('can:access-admin-panel')->group(function () {
|
||
Route::resource('products', AdminProductController::class);
|
||
Route::resource('categories', AdminCategoryController::class);
|
||
Route::resource('orders', AdminOrderController::class)->only(['index', 'show', 'update']);
|
||
Route::patch('orders/{order}/status', [AdminOrderController::class, 'updateStatus'])->name('orders.status');
|
||
Route::get('dashboard', [AdminDashboardController::class, 'index'])->name('dashboard');
|
||
});
|
||
});
|
||
```
|
||
|
||
### Контроллеры
|
||
- `ProductController` — публичный каталог и детальный просмотр
|
||
- `CartController` — управление корзиной
|
||
- `OrderController` — оформление и просмотр своих заказов
|
||
- `AdminProductController` — CRUD товаров (с загрузкой изображений)
|
||
- `AdminCategoryController` — CRUD категорий
|
||
- `AdminOrderController` — управление заказами и статусами
|
||
- `AdminDashboardController` — панель администратора
|
||
|
||
---
|
||
|
||
## 5. Роли, Gates и Policies
|
||
|
||
### Роли
|
||
| Роль | Описание |
|
||
|---|---|
|
||
| `admin` | Полный доступ, управление пользователями, товарами, заказами |
|
||
| `order_manager` | Просмотр и обновление статусов заказов |
|
||
| `customer` | Просмотр каталога, корзина, оформление заказов, просмотр своих заказов |
|
||
|
||
### Gates
|
||
|
||
```php
|
||
Gate::define('access-admin-panel', function (User $user) {
|
||
return in_array($user->role, ['admin', 'order_manager']);
|
||
});
|
||
|
||
Gate::define('manage-products', function (User $user) {
|
||
return $user->role === 'admin';
|
||
});
|
||
|
||
Gate::define('manage-categories', function (User $user) {
|
||
return $user->role === 'admin';
|
||
});
|
||
|
||
Gate::define('manage-orders', function (User $user) {
|
||
return in_array($user->role, ['admin', 'order_manager']);
|
||
});
|
||
```
|
||
|
||
### Policies
|
||
|
||
**ProductPolicy:**
|
||
- `view` — все (публичный каталог)
|
||
- `create`, `update`, `delete` — только admin
|
||
|
||
**CategoryPolicy:**
|
||
- `create`, `update`, `delete` — только admin
|
||
|
||
**OrderPolicy:**
|
||
- `view` — владелец заказа или admin/order_manager
|
||
- `updateStatus` — admin или order_manager
|
||
- `create` — все аутентифицированные
|
||
|
||
---
|
||
|
||
## 6. Требования к интерфейсу (Bootstrap 5)
|
||
|
||
### Компоненты
|
||
- **Навбар** — логотип, ссылки, корзина (с бейджем количества), профиль
|
||
- **Карточки товаров** — изображение, название, цена, бейдж наличия, кнопка «В корзину»
|
||
- **Каталог** — боковая панель с категориями + сетка товаров (`col-md-4`)
|
||
- **Корзина** — таблица позиций с кнопками +/- количества, итоговая сумма
|
||
- **Форма заказа** — Bootstrap-форма с валидацией
|
||
- **Модальное окно** — быстрый просмотр товара
|
||
- **Таблица заказов** — статусы с цветными бейджами, кнопка просмотра деталей
|
||
- **Дашборд** — карточки статистики (`card` + `row`/`col`)
|
||
|
||
### Цветовая схема статусов заказа
|
||
- Новый — `bg-info`
|
||
- В обработке — `bg-warning`
|
||
- Отправлен — `bg-primary`
|
||
- Доставлен — `bg-success`
|
||
- Отменён — `bg-danger`
|
||
|
||
---
|
||
|
||
## 7. Git-workflow для команды
|
||
|
||
### Распределение модулей (для 2 человек)
|
||
|
||
| Участник | Модуль | Ветки |
|
||
|---|---|---|
|
||
| **Участник A** | Товары, категории, загрузка изображений, админка | `feature/products-crud`, `feature/categories`, `feature-image-upload` |
|
||
| **Участник B** | Корзина, оформление заказа, заказы, UI | `feature/cart`, `feature/checkout`, `feature-orders` |
|
||
|
||
### Распределение модулей (для 3 человек)
|
||
|
||
| Участник | Модуль | Ветки |
|
||
|---|---|---|
|
||
| **Участник A** | Товары, категории, загрузка изображений | `feature/products-crud`, `feature/categories`, `feature-image-upload` |
|
||
| **Участник B** | Корзина, оформление заказа, заказы | `feature/cart`, `feature/checkout`, `feature-orders` |
|
||
| **Участник C** | Аутентификация, админка, дашборд | `feature/admin-dashboard`, `feature/admin-orders`, `feature-statistics` |
|
||
|
||
### Правила
|
||
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/products-crud
|
||
checkout develop
|
||
branch feature/cart
|
||
checkout feature/products-crud
|
||
commit id: "feat: add products CRUD with images"
|
||
commit id: "feat: add categories CRUD"
|
||
checkout feature/cart
|
||
commit id: "feat: add cart session logic"
|
||
commit id: "feat: add checkout form"
|
||
checkout develop
|
||
merge feature/products-crud tag: "PR + review"
|
||
merge feature/cart 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/products-crud
|
||
checkout develop
|
||
branch feature/cart
|
||
checkout develop
|
||
branch feature/admin-dashboard
|
||
checkout feature/products-crud
|
||
commit id: "feat: add products CRUD"
|
||
commit id: "feat: add image upload"
|
||
checkout feature/cart
|
||
commit id: "feat: add cart management"
|
||
commit id: "feat: add checkout flow"
|
||
checkout feature/admin-dashboard
|
||
commit id: "feat: add admin panel"
|
||
commit id: "feat: add order management"
|
||
checkout develop
|
||
merge feature/products-crud tag: "PR + review"
|
||
merge feature/cart tag: "PR + review"
|
||
merge feature/admin-dashboard tag: "PR + review"
|
||
checkout main
|
||
merge develop tag: "release v1.1"
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Критерии приёмки
|
||
|
||
### Обязательно
|
||
- [ ] CRUD товаров с загрузкой изображений (валидация формата и размера)
|
||
- [ ] CRUD категорий
|
||
- [ ] Связь многие-ко-многим (товар ↔ категории)
|
||
- [ ] Корзина работает (добавление, изменение количества, удаление)
|
||
- [ ] Оформление заказа с валидацией всех полей
|
||
- [ ] Уменьшение `stock_quantity` при оформлении заказа
|
||
- [ ] Просмотр своих заказов (покупатель)
|
||
- [ ] Управление статусами заказов (админ/менеджер)
|
||
- [ ] Policies: покупатель не может управлять товарами/чужими заказами
|
||
- [ ] Адаптивная Bootstrap-вёрстка
|
||
- [ ] Flash-сообщения при действиях
|
||
- [ ] Пагинация каталога
|
||
- [ ] Git-история: минимум 3 ветки на участника, PR с ревью
|
||
|
||
### Дополнительно (бонусные баллы)
|
||
- [ ] Поиск товаров по названию/описанию
|
||
- [ ] Сортировка товаров (цена, дата, название)
|
||
- [ ] Фильтрация по нескольким категориям
|
||
- [ ] Избранное (wishlist)
|
||
- [ ] Промокоды со скидкой
|
||
- [ ] Генерация PDF-чека заказа
|
||
|
||
---
|
||
|
||
## 9. Дополнительные задания (для продвинутых)
|
||
|
||
1. **Промокоды:** система скидок с уникальными кодами и процентом/фиксированной суммой
|
||
2. **Избранное:** добавление товаров в wishlist (многие-ко-многим user ↔ product)
|
||
3. **Отзывы к товарам:** рейтинг 1–5 + текст, модерация
|
||
4. **Тесты:** PHPUnit Feature-тесты для CartController и OrderController
|
||
5. **API:** RESTful API для каталога товаров (resource-маршруты с JSON)
|
||
6. **Кэширование:** кэширование каталога через Laravel Cache
|
||
7. **Soft Deletes:** мягкое удаление товаров и категорий
|
||
|
||
---
|
||
|
||
## 10. Рекомендуемые материалы
|
||
|
||
- Laravel Docs: https://laravel.com/docs/12.x
|
||
- Laravel Filesystem (загрузка файлов): https://laravel.com/docs/12.x/filesystem
|
||
- Laravel Many-to-Many Relationships: https://laravel.com/docs/12.x/eloquent-relationships#many-to-many
|
||
- Bootstrap 5 Cards: https://getbootstrap.com/docs/5.3/components/card/
|
||
- Laravel Session & Cart: https://laravel.com/docs/12.x/session
|