Мини-сервис для агрегации данных о продажах с маркетплейсов (Ozon, Wildberries, Yandex Market).
Сервис даже успешно развернут на рендере (!!!) https://render.com/ по адресу
Для локальной проверки сервиса можно использовать докер из папки с проектом, либо запустить по инструкции main.py из главной директории проекта
| Эндпоинт | Роутер | Сервис storage | Сервис aggregation | Сервис currency |
|---|---|---|---|---|
POST /sales |
sales.py |
add_sales() |
❌ | ❌ |
GET /sales |
sales.py |
get_sales_count() + get_sales_with_pagination() |
❌ | ❌ |
DELETE /sales/clear |
sales.py |
clear_storage() |
❌ | ❌ |
GET /analytics/summary |
analytics.py |
get_sales() |
calculate_summary() |
❌ |
GET /analytics/top-products |
analytics.py |
get_sales() |
calculate_top_products() |
❌ |
GET /analytics/summary-usd |
analytics.py |
get_sales() |
calculate_summary() |
get_usd_rate() |
POST /analytics/upload-csv |
analytics.py |
add_sales() |
❌ | ❌ |
- Установленный Docker
# 1. Клонировать репозиторий
git clone git@github.com:Alexman2505/BOXSTORE_test.git
cd BOXSTORE_testОбраз собирается с именем alexman2505/boxstore-api-image:latest:
docker build -t alexman2505/boxstore-api-image:latest .docker run -d -p 8008:8008 --name boxstore-api-container alexman2505/boxstore-api-image:latest
docker psAPI: http://localhost:8008 Документация: http://localhost:8008/docs
# Отправить образ на Docker Hub
docker push alexman2505/boxstore-api-image:latestdocker stop boxstore-api-container
docker rm boxstore-api-container
docker ps -adocker rmi alexman2505/boxstore-api-image:latest
docker images
docker system prune -fdocker stop boxstore-api-container && docker rm boxstore-api-container && docker build -t alexman2505/boxstore-api-image:latest . && docker push alexman2505/boxstore-api-image:latest
``
## 📦 Установка и запуск (без докера)
### 1. Клонировать репозиторий
```bash
git clone git@github.com:Alexman2505/BOXSTORE_test.git
cd BOXSTORE_test2. Создайте и активируйте виртуальное окружение. Установите в виртуальное окружение библиотеки для проекта.
python -m venv venv
source venv/Scripts/activate
pip install -r requirements.txtpython main.pyИнтерактиваня документация доступна по локальному адресу http://127.0.0.1:8008/docs
Windows (хост)
│
├── D:\Dev\boxstore_test\ (исходники)
│ ├── main.py
│ ├── Dockerfile
│ └── ...
│
└── WSL (Ubuntu) — виртуальная машина
│
├── /mnt/d/Dev/boxstore_test/ ← Доступ к коду (монтирование)
│
├── Docker (движок)
│ └── Образ: alexman2505/boxstore-api-image:latest
│ └── Контейнер (если запустить docker run)
│
└──Кластер Kubernetes (Minikube)
│
└── Нода (Node) — сервер/машина
│
├── Под (Pod 1) — API
│ └── Контейнер (boxstore-api)
│
├── Под (Pod 2) — API (реплика)
│ └── Контейнер (boxstore-api)
│
└── Другие поды (coredns, kube-proxy...)
│
└── Service (порт 30008) → Доступ из браузера Windows
┌───────────────────────────────────────────────────┐
│ POD ( минимальная и неделимая единица) │
│ ┌─────────────────────────────────────────────┐ │
│ │ Контейнер │ │
│ │ ┌───────────────────────────────────────┐ │ │
│ │ │ Docker-образ │ │ │
│ │ │ alexman2505/boxstore-api-image:latest │ │ │
│ │ └───────────────────────────────────────┘ │ │
│ │ │ │
│ │ FastAPI приложение │ │
│ │ (uvicorn main:app --port 8008) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ IP-адрес: 10.244.0.5 (внутри кластера) │
└───────────────────────────────────────────────────┘📋 Краткая шпаргалка
| Действие | Команда |
|---|---|
| Очистить поды | kubectl delete -f k8s/deployment.yaml |
| Очистить сервис | kubectl delete -f k8s/service.yaml |
| Остановить Minikube | minikube stop |
| Удалить Minikube | minikube delete |
| Запустить Minikube | minikube start |
| Собрать образ | docker build -t alexman2505/boxstore-api-image:latest . |
| Загрузить образ в Minikube | minikube image load alexman2505/boxstore-api-image:latest |
| Запустить деплоймент | kubectl apply -f k8s/deployment.yaml |
| Запустить сервис | kubectl apply -f k8s/service.yaml |
| Проверить поды | kubectl get pods |
| Открыть доступ | minikube service boxstore-api-service |
Необходимо создать мини-сервис — REST API для загрузки, хранения и агрегации данных о продажах с маркетплейсов
Сервис должен:
- Принимать данные о продажах через API
- Хранить их в памяти (или SQLite)
- Отдавать агрегированные метрики
- Забирать курс валют из открытого API
Модели данных (Pydantic)
Создай модели для представления продажи:
# Пример структуры одной продажи
{
"order_id": "ORD-001",
"marketplace": "ozon", # ozon | wildberries | yandex_market
"product_name": "Кабель USB-C",
"quantity": 3,
"price": 450.00, # цена за штуку, руб.
"cost_price": 120.00, # себестоимость за штуку, руб.
"status": "delivered", # delivered | returned | cancelled
"sold_at": "2025-03-15" # дата продажи, YYYY-MM-DD
}Требования:
- Валидация:
marketplace— только допустимые значения - Валидация:
priceиcost_price> 0 - Валидация:
quantity>= 1 - Валидация:
sold_at— корректная дата, не из будущего
===
API эндпоинты (FastAPI)
Реализуйте следующие эндпоинты:
Добавление одной или нескольких продаж (batch)
- Вход: список объектов продаж
- Выход: количество добавленных записей
- Ошибки валидации должны возвращать понятные сообщения
Получение списка продаж с фильтрацией
Query-параметры (все опциональные):
marketplace— фильтр по маркетплейсуstatus— фильтр по статусуdate_from,date_to— фильтр по диапазону датpage,page_size— пагинация (по умолчанию page=1, page_size=20)
Чистка базы
Агрегированные метрики за период
Query-параметры:
date_from,date_to— период (обязательные)marketplace— фильтр по маркетплейсу (опционально)group_by— группировка:marketplace|date|status(опционально)
Возвращаемые метрики (в каждой группе):
total_revenue— сумма (price * quantity) для deliveredtotal_cost— сумма (cost_price * quantity) для deliveredgross_profit— revenue - costmargin_percent— (gross_profit / revenue) * 100total_orders— количество уникальных order_idavg_order_value— средний чек (revenue / total_orders)return_rate— доля возвратов (returned / (delivered + returned)) * 100
Топ продуктов за период
Query-параметры:
date_from,date_to— период (обязательные)sort_by—revenue|quantity|profit(по умолчаниюrevenue)limit— количество (по умолчанию 10)
===
Интеграция с внешним API
Реализуйте эндпоинт:
То же, что /analytics/summary, но все денежные метрики конвертированы в USD
- Курс получать из открытого API ЦБ РФ:
https://www.cbr-xml-daily.ru/daily_json.js - Курс кэшировать на 1 час (не дёргать API на каждый запрос)
- Если API недоступен — возвращать ошибку 503 с понятным сообщением
===
Обработка данных (Pandas)
Реализуйте эндпоинт:
Загрузка продаж из CSV-файла
- Принимает файл через UploadFile
- Парсит CSV с помощью Pandas
- Валидирует данные (те же правила, что и для POST /sales)
- Возвращает: количество загруженных строк, количество ошибок, список ошибок с номерами строк
Пример CSV — файл "sample_data.csv" в этом каталоге
===
Примерная организация кода:
sales_aggregator/
├── main.py # Точка входа FastAPI
├── models/
│ ├── sale.py # Pydantic-модели (Что приходит от клиента)
│ └── analytics.py # Модели ответов аналитики (Что возвращается клиенту)
├── routers/ # описание эндпойнтов путей
│ ├── sales.py # CRUD эндпоинты (Использует sale.py)
│ └── analytics.py # Аналитические эндпоинты (Использует analytics.py)
├── services/ # Бизнес логика (работа со входящими моделями и выдача данных для исходящих)
│ ├── storage.py # Хранение данных (in-memory или SQLite)
│ ├── aggregation.py # Логика агрегации (Pandas, Возвращает dict, а не модели)
│ └── currency.py # Работа с API курсов валют
├── requirements.txt
└── README.md # Инструкция по запуску
Добавлено 3 эндпойнта для api для экселя. Используется OpenPyXL (т.е. работа с файлом, а не самим процессом экселя, как это было бы в xlwings)
alt + f11 запуск редактора макросов в xslm документе. Слева инспектор проектов ctrl + R запуск проджект-менеджера - среда программирования (не забыть на пкм добавить режим дебаггера) insert -> UserForm - добавить форму ввода. Ну и дальше понеслась мешанина окошек, лейблов, текстовых форм, шрифтов и т.д. и т.п. М-да.
| Аспект | OpenPyXL | xlwings |
|---|---|---|
| Как работает | Работает с файлом напрямую (как с ZIP-архивом) | Управляет процессом Excel через COM-интерфейс |
| Скорость | 🚀 Очень быстрый | 🐢 Медленнее (ждёт ответ от Excel) |
| Нужен ли установленный Excel | ❌ Нет | ✅ Да |
| Может открыть книгу на экране | ❌ Нет | ✅ Да |
| Может запускать VBA-макросы | ❌ Нет (только встроить текст) | ✅ Да |
| Форматирование | ✅ Есть (шрифты, цвета, границы) | ✅ Есть |
| Где работает | Сервер (Linux, Render) | Только Windows |
===
- Тесты — написать pytest-тесты хотя бы для ключевых эндпоинтов. В процессе.
- Dockerfile — контейнеризация приложения и развертка. СДЕЛАНО! В докере, и в кубернетис, и на рендере развернуто
- Логирование — структурированные логи (JSON-формат). СДЕЛАНО! Рендер пишет все логи
- Документация API — кастомизация Swagger (описания, примеры). СДЕЛАНО! Fastapi создает интерактивную документацию
- CSV - добавил загрузку csv файла для наполнения базы данных
- Excel - добавил 3 отдельных эндпойнта для с выгрузкой данных для работы с excel + vba.