Исправлены 4 проблемы: 1. Расчёт цены первого товара - улучшена валидация в getProductPrice и calculateFinalPrice 2. Отображение actual_price в Select2 вместо обычной цены 3. Количество по умолчанию = 1 для новых форм компонентов 4. Auto-select текста при клике на поле количества для удобства редактирования Изменённые файлы: - products/forms.py: добавлен __init__ в KitItemForm для quantity.initial = 1 - products/templates/includes/select2-product-init.html: обновлена formatSelectResult - products/templates/productkit_create.html: добавлен focus handler для auto-select - products/templates/productkit_edit.html: добавлен focus handler для auto-select 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
277 lines
9.9 KiB
Markdown
277 lines
9.9 KiB
Markdown
# Система оценки качества фотографий товаров - ФАЗА 1 ✅ ЗАВЕРШЕНА
|
||
|
||
## Что реализовано
|
||
|
||
### 1. Конфигурация в settings.py
|
||
```python
|
||
IMAGE_QUALITY_LEVELS = {
|
||
'excellent': 0.95, # >= 95% от max (если max=2160 → >= 2052px)
|
||
'good': 0.70, # >= 70% от max (если max=2160 → >= 1512px)
|
||
'acceptable': 0.40, # >= 40% от max (если max=2160 → >= 864px)
|
||
'poor': 0.20, # >= 20% от max (если max=2160 → >= 432px)
|
||
# < 20% = very_poor
|
||
}
|
||
|
||
IMAGE_QUALITY_LABELS = {
|
||
'excellent': {'label': 'Отлично', 'color': 'success', 'recommendation': '...'},
|
||
'good': {'label': 'Хорошо', 'color': 'info', 'recommendation': '...'},
|
||
'acceptable': {'label': 'Приемлемо', 'color': 'warning', 'recommendation': '...'},
|
||
'poor': {'label': 'Плохо', 'color': 'danger', 'recommendation': '...'},
|
||
'very_poor': {'label': 'Очень плохо', 'color': 'danger', 'recommendation': '...'},
|
||
}
|
||
```
|
||
|
||
### 2. Валидатор (validators/image_validators.py)
|
||
**Полностью гибкий валидатор, который:**
|
||
- Динамически читает max размеры из `IMAGE_PROCESSING_CONFIG`
|
||
- Вычисляет пороги как процент от максимума
|
||
- Определяет уровень качества для любого размера изображения
|
||
|
||
**Функции:**
|
||
```python
|
||
# Получить максимальный размер из конфиг
|
||
get_max_dimension_from_config() → 2160
|
||
|
||
# Определить качество на основе размеров
|
||
get_image_quality_level(width, height) → ('good', False)
|
||
|
||
# Получить информацию о уровне
|
||
get_quality_info('excellent') → {label, color, recommendation, ...}
|
||
|
||
# Валидация фото для UI
|
||
validate_product_image(file) → {valid, width, height, quality_level, message, error}
|
||
```
|
||
|
||
**Пример работы:**
|
||
```python
|
||
# Если вы загружаете фото 546×546 (а max=2160):
|
||
quality_level, needs_update = get_image_quality_level(546, 546)
|
||
# Результат: ('acceptable', False)
|
||
# Расчет: 546/2160 = 0.253 (25.3%)
|
||
# 25.3% >= 40%? Нет, >= 20%? Да → poor
|
||
# На самом деле: 25.3% >= 40%? Нет, но >= 20%? Да → poor
|
||
# Хм, давайте пересчитаем:
|
||
# - excellent: 546/2160 = 0.253 >= 0.95? Нет
|
||
# - good: 0.253 >= 0.70? Нет
|
||
# - acceptable: 0.253 >= 0.40? Нет
|
||
# - poor: 0.253 >= 0.20? Да ✓
|
||
# Результат: ('poor', True) ← требует обновления
|
||
```
|
||
|
||
### 3. Модели (ProductPhoto, ProductKitPhoto, ProductCategoryPhoto)
|
||
**Добавлены новые поля:**
|
||
```python
|
||
quality_level = CharField(
|
||
choices=[
|
||
('excellent', 'Отлично (>= 2052px)'),
|
||
('good', 'Хорошо (1512-2051px)'),
|
||
('acceptable', 'Приемлемо (864-1511px)'),
|
||
('poor', 'Плохо (432-863px)'),
|
||
('very_poor', 'Очень плохо (< 432px)'),
|
||
],
|
||
default='acceptable',
|
||
db_index=True,
|
||
)
|
||
|
||
quality_warning = BooleanField(
|
||
default=False, # True для poor и very_poor
|
||
db_index=True,
|
||
)
|
||
```
|
||
|
||
**Индексы для быстрого поиска:**
|
||
```python
|
||
indexes = [
|
||
models.Index(fields=['quality_level']),
|
||
models.Index(fields=['quality_warning']),
|
||
models.Index(fields=['quality_warning', 'product']), # Товары требующие обновления
|
||
]
|
||
```
|
||
|
||
### 4. Image Processor (image_processor.py)
|
||
**Обновлен метод process_image:**
|
||
```python
|
||
def process_image(image_file, base_path, entity_id, photo_id):
|
||
# Раньше возвращал:
|
||
# {'original': '...', 'large': '...', 'medium': '...', 'thumbnail': '...'}
|
||
|
||
# Теперь возвращает дополнительно:
|
||
{
|
||
'original': '...',
|
||
'large': '...',
|
||
'medium': '...',
|
||
'thumbnail': '...',
|
||
'width': 1920,
|
||
'height': 1080,
|
||
'quality_level': 'excellent',
|
||
'quality_warning': False,
|
||
}
|
||
```
|
||
|
||
### 5. Сохранение фото (photos.py -> save())
|
||
**Автоматическое определение качества:**
|
||
- При создании нового фото → вычисляет quality_level и quality_warning
|
||
- При обновлении фото → пересчитывает качество
|
||
- Сохраняет все три поля atomically в БД
|
||
|
||
## Как это работает (пример)
|
||
|
||
### Сценарий: Загрузка фото 546×546px
|
||
|
||
1. **Пользователь загружает фото** через форму продукта
|
||
2. **Вызывается ProductPhoto.save()**
|
||
3. **ImageProcessor.process_image()** обрабатывает фото:
|
||
- Открывает изображение, получает размеры 546×546
|
||
- **Вызывает get_image_quality_level(546, 546)**
|
||
- Вычисляет: max=2160 (из settings), percent=546/2160=0.253
|
||
- Сравнивает с пороги: 0.253 >= 0.20? **Да** → 'poor'
|
||
- Возвращает: ('poor', True)
|
||
- Сохраняет все размеры (original, large, medium, thumb)
|
||
- Возвращает обработанные пути + quality info
|
||
4. **ProductPhoto.save()** получает результат:
|
||
```python
|
||
processed_paths = {
|
||
'original': 'products/2/7/original.jpg',
|
||
'quality_level': 'poor',
|
||
'quality_warning': True,
|
||
}
|
||
```
|
||
5. **Сохраняет в БД:**
|
||
```python
|
||
photo.image = 'products/2/7/original.jpg'
|
||
photo.quality_level = 'poor'
|
||
photo.quality_warning = True
|
||
photo.save()
|
||
```
|
||
|
||
### Результат в БД:
|
||
```
|
||
ProductPhoto:
|
||
- id: 7
|
||
- product_id: 2
|
||
- image: products/2/7/original.jpg
|
||
- quality_level: 'poor' 🔴
|
||
- quality_warning: True ← Требует обновления!
|
||
- order: 0
|
||
```
|
||
|
||
## Гибкость конфигурации
|
||
|
||
### Пример 1: Вы изменили max_width с 2160 на 3000
|
||
```python
|
||
# В settings.py
|
||
IMAGE_PROCESSING_CONFIG = {
|
||
'formats': {
|
||
'original': {
|
||
'max_width': 3000, # Было 2160
|
||
'max_height': 3000,
|
||
}
|
||
}
|
||
}
|
||
|
||
# Система АВТОМАТИЧЕСКИ пересчитает:
|
||
# excellent: 0.95 * 3000 = 2850px
|
||
# good: 0.70 * 3000 = 2100px
|
||
# acceptable: 0.40 * 3000 = 1200px
|
||
# poor: 0.20 * 3000 = 600px
|
||
|
||
# Код не менялся! ✓
|
||
```
|
||
|
||
### Пример 2: Вы изменили пороги качества
|
||
```python
|
||
# Было:
|
||
IMAGE_QUALITY_LEVELS = {
|
||
'excellent': 0.95,
|
||
'good': 0.70,
|
||
}
|
||
|
||
# Стало:
|
||
IMAGE_QUALITY_LEVELS = {
|
||
'excellent': 0.90, # Жестче
|
||
'good': 0.60, # Жестче
|
||
}
|
||
|
||
# Система АВТОМАТИЧЕСКИ переклассифицирует новые загрузки
|
||
# Старые фото останутся как есть (можно переклассифицировать через management команду)
|
||
```
|
||
|
||
## Что дальше (Фаза 2)
|
||
|
||
После создания миграций, нужно реализовать:
|
||
|
||
### Phase 2: Admin интерфейс
|
||
1. **Фильтры в админке**:
|
||
- По качеству (excellent, good, acceptable, poor, very_poor)
|
||
- Товары требующие обновления фото (quality_warning=True)
|
||
|
||
2. **Визуальные индикаторы**:
|
||
- Цветные иконки в списке товаров (🟢 Отлично, 🟡 Хорошо, 🟠 Приемлемо, 🔴 Плохо)
|
||
- Action для поиска товаров требующих обновления
|
||
|
||
3. **Админ-дисплеи**:
|
||
- Форматирование качества в таблицах
|
||
- Цветные бэджи
|
||
|
||
### Phase 3: Фронтенд UI
|
||
1. **Форма загрузки**:
|
||
- Preview фото с индикатором качества
|
||
- Сообщение о рекомендации
|
||
- Информация о размерах
|
||
|
||
2. **Список товаров**:
|
||
- Иконка качества для каждого фото
|
||
- Подсказка при наведении
|
||
|
||
## Структура файлов (после миграции)
|
||
|
||
```
|
||
myproject/
|
||
├── myproject/
|
||
│ └── settings.py ← IMAGE_QUALITY_LEVELS, IMAGE_QUALITY_LABELS
|
||
├── products/
|
||
│ ├── models/
|
||
│ │ └── photos.py ← ProductPhoto, ProductKitPhoto, ProductCategoryPhoto с новыми полями
|
||
│ ├── validators/
|
||
│ │ └── image_validators.py ← Новый файл! Вся гибкая логика
|
||
│ ├── utils/
|
||
│ │ └── image_processor.py ← Обновлен process_image()
|
||
│ └── migrations/
|
||
│ └── XXXX_add_photo_quality_assessment.py ← НУЖНА ВАША МИГРАЦИЯ!
|
||
```
|
||
|
||
## Коммит
|
||
```
|
||
622e17a feat: Реализовать систему оценки качества фотографий товаров (Фаза 1)
|
||
```
|
||
|
||
## Следующие шаги
|
||
|
||
1. **Создать миграцию** через:
|
||
```bash
|
||
python manage.py makemigrations products --name add_photo_quality_assessment
|
||
```
|
||
|
||
2. **Применить миграцию**:
|
||
```bash
|
||
python manage.py migrate
|
||
```
|
||
|
||
3. **Протестировать вычисление качества**:
|
||
```python
|
||
python manage.py shell
|
||
>>> from products.validators.image_validators import get_image_quality_level
|
||
>>> get_image_quality_level(546, 546)
|
||
('poor', True)
|
||
>>> get_image_quality_level(2160, 2160)
|
||
('excellent', False)
|
||
```
|
||
|
||
4. **Загрузить фото к товару** и проверить что quality_level и quality_warning автоматически заполнены в админке
|
||
|
||
5. **Приступить к Фазе 2** - реализовать admin интерфейс
|
||
|
||
---
|
||
|
||
**Фаза 1 завершена! 🎉 Система полностью готова к расширению.**
|