Skip to content

Alexman2505/BOXSTORE_test

Repository files navigation

Sales Aggregator API

Мини-сервис для агрегации данных о продажах с маркетплейсов (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

Предварительные требования

  • Установленный Docker

Шаги для запуска

# 1. Клонировать репозиторий
git clone git@github.com:Alexman2505/BOXSTORE_test.git
cd BOXSTORE_test

2. Собрать Docker образ

Образ собирается с именем alexman2505/boxstore-api-image:latest:

docker build -t alexman2505/boxstore-api-image:latest .

3. Запустить контейнер и проверить

docker run -d -p 8008:8008 --name boxstore-api-container alexman2505/boxstore-api-image:latest
docker ps

4. После запуска проверить в браузере:

API: http://localhost:8008 Документация: http://localhost:8008/docs

5. Загрузка образа на Docker Hub (для деплоя на Render)

# Отправить образ на Docker Hub
docker push alexman2505/boxstore-api-image:latest

6. Остановить и удалить контейнер. Проверить контейнеры (отсутствие)

docker stop boxstore-api-container
docker rm boxstore-api-container
docker ps -a

7. Удалить образ и кэш

docker rmi alexman2505/boxstore-api-image:latest
docker images
docker system prune -f

8. Набор команд при редактировании кода и автоматическом перезаливе на докерхаб

docker 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_test

2. Создайте и активируйте виртуальное окружение. Установите в виртуальное окружение библиотеки для проекта.

python -m venv venv
source venv/Scripts/activate
pip install -r requirements.txt

3. Запустите одной командой

python main.py

Интерактиваня документация доступна по локальному адресу http://127.0.0.1:8008/docs

Раздел Kubernetes

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 для загрузки, хранения и агрегации данных о продажах с маркетплейсов

Сервис должен:

  1. Принимать данные о продажах через API
  2. Хранить их в памяти (или SQLite)
  3. Отдавать агрегированные метрики
  4. Забирать курс валют из открытого 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)

Реализуйте следующие эндпоинты:

POST /sales

Добавление одной или нескольких продаж (batch)

  • Вход: список объектов продаж
  • Выход: количество добавленных записей
  • Ошибки валидации должны возвращать понятные сообщения

GET /sales

Получение списка продаж с фильтрацией

Query-параметры (все опциональные):

  • marketplace — фильтр по маркетплейсу
  • status — фильтр по статусу
  • date_from, date_to — фильтр по диапазону дат
  • page, page_size — пагинация (по умолчанию page=1, page_size=20)

DELETE /sales/clear

Чистка базы

GET /analytics/summary

Агрегированные метрики за период

Query-параметры:

  • date_from, date_to — период (обязательные)
  • marketplace — фильтр по маркетплейсу (опционально)
  • group_by — группировка: marketplace | date | status (опционально)

Возвращаемые метрики (в каждой группе):

  • total_revenue — сумма (price * quantity) для delivered
  • total_cost — сумма (cost_price * quantity) для delivered
  • gross_profit — revenue - cost
  • margin_percent — (gross_profit / revenue) * 100
  • total_orders — количество уникальных order_id
  • avg_order_value — средний чек (revenue / total_orders)
  • return_rate — доля возвратов (returned / (delivered + returned)) * 100

GET /analytics/top-products

Топ продуктов за период

Query-параметры:

  • date_from, date_to — период (обязательные)
  • sort_byrevenue | quantity | profit (по умолчанию revenue)
  • limit — количество (по умолчанию 10)

===

Интеграция с внешним API

Реализуйте эндпоинт:

GET /analytics/summary-usd

То же, что /analytics/summary, но все денежные метрики конвертированы в USD

  • Курс получать из открытого API ЦБ РФ: https://www.cbr-xml-daily.ru/daily_json.js
  • Курс кэшировать на 1 час (не дёргать API на каждый запрос)
  • Если API недоступен — возвращать ошибку 503 с понятным сообщением

===

Обработка данных (Pandas)

Реализуйте эндпоинт:

POST /analytics/upload-csv

Загрузка продаж из 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)

Шпаргалка по VBA

alt + f11 запуск редактора макросов в xslm документе. Слева инспектор проектов ctrl + R запуск проджект-менеджера - среда программирования (не забыть на пкм добавить режим дебаггера) insert -> UserForm - добавить форму ввода. Ну и дальше понеслась мешанина окошек, лейблов, текстовых форм, шрифтов и т.д. и т.п. М-да.

Сравнение OpenPyXL vs xlwings

Аспект OpenPyXL xlwings
Как работает Работает с файлом напрямую (как с ZIP-архивом) Управляет процессом Excel через COM-интерфейс
Скорость 🚀 Очень быстрый 🐢 Медленнее (ждёт ответ от Excel)
Нужен ли установленный Excel ❌ Нет ✅ Да
Может открыть книгу на экране ❌ Нет ✅ Да
Может запускать VBA-макросы ❌ Нет (только встроить текст) ✅ Да
Форматирование ✅ Есть (шрифты, цвета, границы) ✅ Есть
Где работает Сервер (Linux, Render) Только Windows

===

Дополнительные задания (необязательно, но будет плюсом)

  1. Тесты — написать pytest-тесты хотя бы для ключевых эндпоинтов. В процессе.
  2. Dockerfile — контейнеризация приложения и развертка. СДЕЛАНО! В докере, и в кубернетис, и на рендере развернуто
  3. Логирование — структурированные логи (JSON-формат). СДЕЛАНО! Рендер пишет все логи
  4. Документация API — кастомизация Swagger (описания, примеры). СДЕЛАНО! Fastapi создает интерактивную документацию

Дополнительно проделанная работа

  1. CSV - добавил загрузку csv файла для наполнения базы данных
  2. Excel - добавил 3 отдельных эндпойнта для с выгрузкой данных для работы с excel + vba.

About

BOXSTORE_test

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors