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,descriptioncategory:sets|mocspricesellerFK ->auth_app.UsercharacteristicsJSONdetails_listJSONinstructions_linkstatus:draft|published|archivedprint_time_hours,material_typezip_file,parts_xlsx_fileviews_count,downloads_count- timestamps
ProductImage¶
productFK ->Model3Dimageis_primarycreated_at
4. Бизнес-правила¶
- Создавать товары могут только продавцы (
seller|both) или staff. - Для anonymous в списке по умолчанию доступны только
published. details_listскрывается от посторонних пользователей.- При загрузке
uploaded_partsформируется ZIP-файл деталей.
5. ETL и импорт¶
Команды:
import_sets_from_data.pyimport_sets.pyfix_product_files.pydelete_all_sets.py
Поток импорта:
- Сканирование
data/sets/<year>/<set_id>. - Чтение
parts.xlsx, расчет деталей и цены. - Создание
Model3D. - Загрузка изображений.
- Сохранение 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: расширенный доступ.
- anonymous/non-owner: только
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.pyproduct_service/product_app/management/commands/import_sets.pyproduct_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 |