Перейти к содержанию

product_service

1. Назначение

product_service реализует каталог моделей: хранение карточек, изображений, технических атрибутов, статистики просмотров/скачиваний и файлов (ZIP/XLSX), а также ETL-импорт наборов из директории data.

2. API-каталог

Базовый префикс: /api/.

Метод Путь Auth Назначение
GET /ops/ttm/ AllowAny Серверные TTM-маркеры
POST /ops/ttm/mark/ AllowAny Запись TTM-маркера (CI/CD)
GET /models/ AllowAny (с фильтрацией) Список моделей
POST /models/ IsAuthenticated + seller check Создание модели
GET /models/{id}/ AllowAny Детали модели
PUT/PATCH /models/{id}/ IsAuthenticated Обновление
DELETE /models/{id}/ IsAuthenticated Удаление
POST /models/{id}/increment_views/ AllowAny Инкремент просмотров
GET /models/my_models/ IsAuthenticated Модели текущего продавца

Query-параметры списка:

  • status, category, seller, search, order_by.

3. Модель данных

Model3D

  • name, description
  • category: sets|mocs
  • price
  • seller FK -> auth_app.User
  • characteristics JSON
  • details_list JSON
  • instructions_link
  • status: draft|published|archived
  • print_time_hours, material_type
  • zip_file, parts_xlsx_file
  • views_count, downloads_count
  • timestamps

ProductImage

  • product FK -> Model3D
  • image
  • is_primary
  • created_at

4. Бизнес-правила

  • Создавать товары могут только продавцы (seller|both) или staff.
  • Для anonymous в списке по умолчанию доступны только published.
  • details_list скрывается от посторонних пользователей.
  • При загрузке uploaded_parts формируется ZIP-файл деталей.

5. ETL и импорт

Команды:

  • import_sets_from_data.py
  • import_sets.py
  • fix_product_files.py
  • delete_all_sets.py

Поток импорта:

  1. Сканирование data/sets/<year>/<set_id>.
  2. Чтение parts.xlsx, расчет деталей и цены.
  3. Создание Model3D.
  4. Загрузка изображений.
  5. Сохранение XLSX и служебных файлов.
flowchart LR
  dataSets["data/sets"] --> importCmd["import_sets_from_data"]
  importCmd --> parseXlsx["parse parts.xlsx"]
  parseXlsx --> buildModel["create Model3D"]
  buildModel --> uploadMedia["attach images + xlsx"]
  uploadMedia --> db["PostgreSQL"]
  uploadMedia --> media["media/product_*"]

6. Риски

  • Возможен IDOR на update/delete при отсутствии object-level owner check.
  • increment_views открыт публично и не имеет rate limiting.
  • Несогласованность между markdown-инструкциями импорта и фактической логикой кода.

7. Конфигурация

  • Внешний порт: 8003.
  • Основные env: DATABASE_URL, SECRET_KEY, DEBUG, PYTHONPATH.
  • Интеграционные зависимости: auth_service, user_service.

8. Дополнительная детализация внутренних функций (append-only)

8.1 Model3DSerializer прикладная логика

get_total_parts_count(self, obj)

  • Источник: product_service/product_app/serializers.py
  • Назначение: вычислить общее количество деталей из details_list.
  • Вход:
  • details_list (ожидается list словарей с amount).
  • Выход:
  • int сумма количеств.
  • Edge-cases:
  • нечисловые значения amount игнорируются без исключения.

to_representation(self, instance)

  • Назначение: скрыть приватные поля от не-владельцев.
  • Вход:
  • instance и request из serializer context.
  • Выход:
  • сериализованный payload с role-aware видимостью details_list.

create(self, validated_data) / update(self, instance, validated_data)

  • Назначение:
  • создание/обновление карточки с обработкой медиа.
  • Вход:
  • поля модели + uploaded_images + uploaded_parts.
  • Выход:
  • Model3D.
  • Side effects:
  • запись карточки и изображений в БД;
  • создание временного ZIP из uploaded_parts и сохранение в zip_file;
  • файловые операции в media.
  • Edge-cases:
  • при ошибке ZIP часть сценариев логируется без отката уже созданной карточки.

8.2 Model3DViewSet прикладная логика

get_queryset(self)

  • Источник: product_service/product_app/views.py
  • Назначение: фильтрация каталога с учетом роли пользователя.
  • Вход:
  • query params: status, category, seller, search, order_by.
  • Выход:
  • queryset моделей:
    • anonymous/non-owner: только published;
    • owner/staff: расширенный доступ.

get_object(self)

  • Назначение: разрешить доступ владельцу к draft-объектам.
  • Выход:
  • объект модели или NotFound.

create(self, request) и perform_create(self, serializer)

  • Назначение:
  • валидация seller-role и сохранение модели.
  • Side effects:
  • роль продавца проверяется через user_app.UserProfile;
  • после сохранения отправляется best-effort уведомление в admin_app.Notification.
  • Ошибки:
  • 403 если пользователь не продавец;
  • 500 при ошибках интеграции профилей.

increment_views(self, request, pk=None)

  • Назначение: инкремент счетчика просмотров.
  • Выход:
  • views_count после обновления.
  • Side effects:
  • запись views_count в БД.

8.3 Контракты файлов и данных

  • details_list:
  • фактически обрабатывается как список элементов с количеством; строгая схема не enforced на уровне модели.
  • uploaded_images:
  • список image-файлов в multipart.
  • uploaded_parts:
  • список файлов деталей, из которых формируется ZIP-архив.
  • parts_xlsx_file:
  • используется downstream сервисами для генерации выдачи.

8.4 ETL-функции management commands

  • Источники:
  • product_service/product_app/management/commands/import_sets_from_data.py
  • product_service/product_app/management/commands/import_sets.py
  • product_service/product_app/management/commands/fix_product_files.py
  • Внутренние функции:
  • чтение XLSX деталей;
  • вычисление price/характеристик;
  • загрузка изображений;
  • коррекция путей медиа.
  • Side effects:
  • массовые записи в БД и файловую систему.

9. Соответствие master-документации

Источник верхнего уровня: Master-документация проекта.

Контроль Требование Проверка Артефакт
Catalog contracts Фильтры/сортировка задокументированы и реализованы server-side проверка query-параметров и пагинации API tests
Data invariants Инварианты модели и ETL flow не нарушены ревью импорта и модельных ограничений migration + ETL docs
Access control Проверка seller-role и ownership обязательна негативные сценарии create/update/delete security tests
Delivery quality Изменения каталога синхронизируются с frontend контрактом cross-check frontend_filter_audit docs + QA