Skip to content

TrippyFrenemy/ParfumShop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ParfumShop

Полнофункциональная e-commerce платформа для продажи парфюмерии на FastAPI с серверным рендерингом (Jinja2 + Tailwind CSS), админ-панелью, CMS, оптовыми ценами, купонами, интеграцией с Новой Почтой и Telegram-уведомлениями.

Стек технологий

Компонент Технология
Backend FastAPI 0.128, Python 3.11+
База данных PostgreSQL 17 + SQLAlchemy 2.0 (async, asyncpg)
Миграции Alembic
Кэш / Брокер Redis (aioredis)
Фоновые задачи Celery 5.6 + Celery Beat
Аутентификация JWT (access + refresh в httponly cookies) + Google OAuth 2.0
Хэширование паролей Argon2 (passlib)
Шаблоны Jinja2 + Tailwind CSS + Alpine.js
Хранилище файлов S3-совместимое (Minio и др.) через aiobotocore
Деплой Docker Compose (web + db + redis)

Структура проекта

src/
├── admin/          # Админ-панель (дашборд, CRUD товаров/категорий/заказов/купонов, настройки, CMS)
├── auth/           # Аутентификация: JWT, Google OAuth 2.0, rate-limiting
├── cart/           # Корзина (гостевая по session_id + авторизованная по user_id)
├── content/        # CMS — управление контентом страниц (draft/publish)
├── coupons/        # Купоны и скидки (процент, фиксированная сумма)
├── delivery/       # Интеграция с Новой Почтой (города, отделения, трекинг)
├── logs/           # Логирование HTTP-запросов пользователей
├── orders/         # Заказы, checkout, история заказов
├── products/       # Каталог, категории, товары (HTML + JSON API)
├── settings/       # Модель настроек магазина (ShopSettings)
├── tasks/          # Celery-задачи (бэкапы, уведомления, очистка, отчёты)
├── users/          # Модели и роутеры пользователей
├── utils/          # Redis-клиент, S3, CSRF, IP-детекция, rate-limit, Celery worker
├── templates/      # Jinja2-шаблоны
│   ├── admin/      # Шаблоны админ-панели
│   ├── auth/       # Шаблоны входа/регистрации
│   ├── partials/   # Переиспользуемые компоненты (хедер, футер, фильтры)
│   └── static/     # CSS, JS, изображения
├── config.py       # Конфигурация (Pydantic Settings, .env)
├── main.py         # Точка входа FastAPI, lifespan, middleware
└── templating.py   # Настройка Jinja2, глобальные функции шаблонов
migrations/         # Alembic-миграции БД

Ключевые возможности

Аутентификация и безопасность

  • Регистрация и вход по email/паролю с хэшированием Argon2
  • Вход через Google OAuth 2.0 с автосозданием аккаунта и привязкой к существующему
  • JWT-токены (access + refresh) хранятся в httponly cookies
  • Rate-limiting: блокировка IP на 10 минут после 5 неудачных попыток входа
  • CSRF-защита форм
  • Состояние OAuth хранится в Redis с TTL 10 минут

Каталог и товары

  • Иерархические категории (родитель-потомок) с изображениями и сортировкой
  • Товары: название, slug (автогенерация), описание, бренд, объём (мл), розничная и скидочная цена
  • Оптовые ценовые уровни (wholesale tiers) — цена автоматически рассчитывается по количеству
  • Множественные изображения с выбором главного и сортировкой
  • Отслеживание остатков на складе
  • Статусы: активный/неактивный, избранный/обычный
  • Фильтрация: категория, бренд, диапазон цен, поиск, пагинация

Корзина

  • Двойной режим: для авторизованных (user_id) и гостей (session_id, cookie 30 дней)
  • Автоматический пересчёт цен с учётом оптовых уровней
  • Добавление, изменение количества, удаление товаров через JSON API
  • Сохранение состояния между сессиями

Заказы и checkout

  • Генерация номера: PF-YYYYMMDD-XXXX (инкремент в рамках дня)
  • Применение купона с реал-тайм валидацией
  • Минимальная сумма заказа (настраивается)
  • Снимок цен товаров на момент заказа (snapshot)
  • Выбор способа доставки: Нова Пошта, Укрпошта
  • Статусы заказа: created -> paid -> processing -> shipped
  • Статусы доставки: pending -> in_transit -> delivered -> received / returned
  • Назначение ТТН (трекинг-номер) через админку
  • История заказов пользователя с пагинацией

Купоны и скидки

  • Типы: процент (percent) и фиксированная сумма (fixed)
  • Ограничения: срок действия (от/до), лимит использований, минимальная сумма заказа
  • JSON API для валидации купона в реальном времени на странице checkout

Интеграция с Новой Почтой

  • Поиск городов через API с кэшированием в Redis (24 часа)
  • Подбор отделений по городу (кэш 12 часов)
  • Трекинг посылок по ТТН с маппингом статусов НП на внутренние
  • Celery-задача для автоматического обновления статусов доставки

CMS — управление контентом

  • Редактируемый контент для страниц: главная, каталог, товар, корзина, checkout, заказы, контакты, авторизация, глобальные элементы (навигация, футер)
  • Рабочий процесс черновик / публикация
  • Управление видимостью блоков и ручная сортировка
  • Типы контента: short (короткий текст), text (длинный текст), html
  • Инвалидация кэша при публикации
  • Контент доступен в шаблонах через функцию t()

Хранилище файлов (S3)

  • Асинхронные операции через aiobotocore
  • Загрузка изображений товаров (images/products/{id}/) и категорий (images/categories/{id}/)
  • Валидация: форматы jpg, jpeg, png, webp; максимум 5 МБ
  • Уникальные имена файлов (UUID)
  • Удаление по ключу, URL или префиксу; автоочистка при удалении товара/категории

Логирование

  • Middleware логирует все HTTP-запросы в таблицу user_logs
  • Записываются: timestamp, user_id, действие, путь, IP, user agent, статус-код, query string
  • Просмотр в админ-панели с пагинацией (только admin)

Middleware

  • Content Middleware — загрузка опубликованного контента CMS в контекст запроса
  • Logging Middleware — логирование всех HTTP-запросов в БД
  • CORS — настроен для работы с фронтендом

Схема базы данных

Таблица Описание
users Пользователи (роли, Google OAuth ID, адрес по умолчанию)
products Товары (цены, остатки, slug, категория, бренд, объём)
categories Категории (иерархия parent-child, изображения, сортировка)
product_images Изображения товаров (main, sort_order)
wholesale_tiers Оптовые ценовые уровни (min_quantity -> price)
carts Корзины (user_id или session_id)
cart_items Позиции корзины (product, quantity, price)
orders Заказы (номер, статус, доставка, ТТН, купон)
order_items Позиции заказа (snapshot цены и названия)
coupons Купоны (тип скидки, лимиты, сроки, использования)
shop_settings Настройки магазина (название, мин. сумма, контакты, реквизиты)
site_content Контент CMS (страница, ключ, значение, draft/published)
user_logs Лог действий пользователей

Запуск

Docker Compose

docker-compose up --build

Сервисы: web (FastAPI на порту 8000), db (PostgreSQL), redis.

Локально

pip install -r requirements.txt
alembic upgrade head
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000

Celery worker (опционально):

celery -A src.utils.celery_worker:celery_app worker --loglevel=info
celery -A src.utils.celery_worker:celery_app beat --loglevel=info

Переменные окружения

Переменная Описание
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS Подключение к PostgreSQL
REDIS_HOST, REDIS_PORT Подключение к Redis
SECRET Секрет для JWT-токенов
SECRET_MANAGER Дополнительный секрет для менеджеров
ADMIN_EMAIL, ADMIN_PASSWORD, ADMIN_NAME, ADMIN_ROLE Автосоздание администратора при старте
MANAGER_EMAIL, MANAGER_PASSWORD, MANAGER_NAME, MANAGER_ROLE Автосоздание менеджера
WAREHOUSE_EMAIL, WAREHOUSE_PASSWORD, WAREHOUSE_NAME, WAREHOUSE_ROLE Автосоздание складского работника
OAUTH_GOOGLE_CLIENT_ID, OAUTH_GOOGLE_CLIENT_SECRET, OAUTH_GOOGLE_REDIRECT_URI Google OAuth 2.0
S3_ACCESS_KEY, S3_SECRET_KEY, S3_ENDPOINT, S3_BUCKET, S3_REGION, S3_PUBLIC_URL S3-хранилище изображений
NP_API_KEY API-ключ Новой Почты
TG_BOT_TOKEN, TG_CHAT_ID, TG_STAFF_CHAT_ID Telegram-уведомления
MIN_ORDER_AMOUNT Минимальная сумма заказа
CSRF_TOKEN_EXPIRY Время жизни CSRF-токена
DEBUG Режим отладки

Роли пользователей

Роль Доступ
client Каталог, корзина, оформление заказа, история заказов
manager Всё вышеперечисленное + админ-панель
warehouse Ограниченный доступ к админке (заказы, склад)
admin Полный доступ, включая логи и настройки

Эндпоинты

Публичные страницы (HTML)

Метод Путь Описание
GET / Главная страница (хиты, новинки, категории)
GET /contacts Страница контактов
GET /catalog Каталог товаров с фильтрами (поиск, бренд, цена)
GET /catalog/{slug} Каталог отфильтрованный по категории
GET /product/{slug} Страница товара
GET /cart Страница корзины
GET /checkout Страница оформления заказа
GET /orders/{order_number} Подтверждение / детали заказа

Авторизация (/auth)

Метод Путь Описание
GET /auth/login Форма входа
POST /auth/login Вход по email + пароль
GET /auth/register Форма регистрации
POST /auth/register Регистрация нового пользователя
POST /auth/refresh Обновление JWT-токенов
GET /auth/google/start Начало OAuth-потока с Google
GET /auth/google Callback от Google OAuth
GET /auth/google/url Получить URL для Google OAuth (JSON)
GET /auth/logout Выход из аккаунта

Пользователь (/users)

Метод Путь Описание
GET /users/me Текущий профиль (JSON)
POST /users/me/delete Удаление / деактивация аккаунта

Корзина (JSON API)

Метод Путь Описание
GET /api/cart Получить текущую корзину
POST /api/cart/add Добавить товар в корзину
PATCH /api/cart/update/{item_id} Изменить количество товара
DELETE /api/cart/remove/{item_id} Удалить товар из корзины

Корзина работает как для гостей (по session_id в cookie), так и для авторизованных пользователей (по user_id).

Заказы

Метод Путь Описание
POST /orders/create Создание заказа из корзины
GET /orders/my История заказов пользователя (требуется авторизация)
GET /orders/{order_number} Детали заказа

Купоны (/coupons)

Метод Путь Описание
POST /coupons/validate Проверка купона (JSON: {code, cart_total})

Поддерживаются типы скидок: процент и фиксированная сумма. Ограничения по количеству использований и срокам действия.

Доставка (/delivery)

Метод Путь Описание
GET /delivery/np/cities?q=... Поиск городов Новой Почты (мин. 2 символа)
GET /delivery/np/warehouses?city_ref=... Отделения Новой Почты в городе
GET /delivery/track/{ttn} Трекинг посылки по ТТН

Товары (JSON API)

Метод Путь Описание
GET /api/products Список товаров (пагинация, фильтры)
GET /api/products/{id} Детали товара по ID
GET /api/categories Список категорий

Параметры фильтрации: search, brand, min_price, max_price, category_id, page, per_page.

Логи (/logs)

Метод Путь Описание
GET /logs/ Просмотр логов активности (только admin)

Админ-панель (/admin)

Доступ: роли admin и manager.

Дашборд

Метод Путь Описание
GET /admin/ Статистика: заказы, выручка, товары, низкий остаток

Товары

Метод Путь Описание
GET /admin/products Список товаров (поиск, фильтр по категории)
GET /admin/products/create Форма создания товара
POST /admin/products/create Сохранение нового товара
GET /admin/products/{id}/edit Форма редактирования товара
POST /admin/products/{id}/edit Сохранение изменений товара
POST /admin/products/{id}/delete Удаление товара

Категории

Метод Путь Описание
GET /admin/categories Список всех категорий
GET /admin/categories/create Форма создания категории
POST /admin/categories/create Сохранение новой категории
GET /admin/categories/{id}/edit Форма редактирования категории
POST /admin/categories/{id}/edit Сохранение изменений категории
POST /admin/categories/{id}/delete Удаление категории

Заказы

Метод Путь Описание
GET /admin/orders Список заказов (фильтр по статусу, поиск)
GET /admin/orders/{id} Детали заказа
POST /admin/orders/{id}/status Изменение статуса заказа
POST /admin/orders/{id}/ttn Установка номера ТТН

Статусы заказа: createdpaidprocessingshipped. Статусы доставки: pendingin_transitdeliveredreceived.

Купоны

Метод Путь Описание
GET /admin/coupons Список купонов
GET /admin/coupons/create Форма создания купона
POST /admin/coupons/create Сохранение нового купона
POST /admin/coupons/{id}/delete Удаление купона

Настройки

Метод Путь Описание
GET /admin/settings Страница настроек магазина
POST /admin/settings Сохранение настроек

Настройки: название магазина, минимальная сумма заказа, телефон, email, текст оплаты, контакты, about.

Контент (CMS)

Метод Путь Описание
GET /admin/content Редактор контента (выбор страницы)
POST /admin/content Сохранение контента (draft/publish)

Поддерживаемые страницы: global, home, contacts, catalog, product, cart, checkout, orders, order_confirm, auth. Каждый блок имеет ключ, значение, тип (short/text/html), видимость и порядок сортировки.

Фоновые задачи (Celery)

Задача Расписание Описание
send_daily_order_summary Каждый день в 08:00 Сводка заказов за день в Telegram
send_weekly_performance_summary Каждый понедельник в 09:00 Недельный отчёт в Telegram
send_periodic_reports_task 3-го и 17-го числа в 06:00 Отчёт за 15 дней в Telegram
clean_old_logs Каждый день в 00:00 Удаление логов старше 90 дней
clean_expired_carts (доступна, не в расписании) Удаление пустых корзин старше 7 дней
update_delivery_statuses (доступна, не в расписании) Обновление статусов доставки через API НП
send_db_backup_task Каждый час с 08:00 до 21:00 Бекап базы данных
send_new_order_notification По событию Уведомление о новом заказе в Telegram
send_order_paid_notification По событию Уведомление об оплате заказа в Telegram

Что осталось доделать

Не реализованные страницы в админке

  • /admin/import-export — Импорт/Экспорт товаров. Ссылка есть в сайдбаре админки, но роут и логика не реализованы. Предполагается: импорт товаров из CSV/Excel, экспорт каталога.
  • /admin/reports — Раздел отчётов. Ссылка есть в сайдбаре, но роут не реализован. Предполагается: визуальные отчёты по продажам, графики, аналитика.

Celery-задачи не подключённые к расписанию

  • clean_expired_carts — задача написана, но не добавлена в beat_schedule в celery_worker.py.
  • update_delivery_statuses — задача для автоматического обновления статусов доставки через API НП написана, но не добавлена в расписание.

Функционал для доработки

  • Оплата — нет интеграции с платёжной системой (LiqPay, Monobank и т.д.). Статус paid устанавливается вручную через админку.
  • Загрузка изображений — сейчас изображения товаров задаются URL-ами. Маунты /media и /uploads закомментированы в main.py. Нужна загрузка файлов через форму.
  • Редактирование купонов — в админке есть создание и удаление купонов, но нет формы редактирования существующего купона.
  • Профиль пользователя (HTML) — есть JSON-эндпоинт /users/me, но нет HTML-страницы профиля с формой редактирования данных (имя, телефон, адрес доставки по умолчанию).
  • Уведомления при создании заказа — Celery-задача send_new_order_notification написана, но не вызывается из orders/router.py при создании заказа.
  • Объединение корзин — при логине гостевая корзина не переносится в корзину пользователя.
  • Подтверждение email — нет механизма верификации email при регистрации.
  • Восстановление пароля — нет функционала сброса/восстановления пароля.
  • Отмена заказа — нет статуса cancelled и возможности отмены заказа клиентом или админом.
  • Создание менеджера/складовщика — закомментировано в lifespan (main.py). Нет UI для управления пользователями/ролями в админке.
  • Тесты — нет юнит- и интеграционных тестов.

About

A project to create a simple perfume store

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors