Исправлены 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>
67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
"""
|
||
Менеджеры и QuerySets для моделей продуктов.
|
||
Реализуют паттерн Soft Delete и фильтрацию активных записей.
|
||
"""
|
||
from django.db import models
|
||
from django.utils import timezone
|
||
|
||
|
||
class ActiveManager(models.Manager):
|
||
"""Менеджер для фильтрации только активных записей"""
|
||
def get_queryset(self):
|
||
return super().get_queryset().filter(is_active=True)
|
||
|
||
|
||
class SoftDeleteQuerySet(models.QuerySet):
|
||
"""
|
||
QuerySet для мягкого удаления (soft delete).
|
||
Позволяет фильтровать удаленные элементы и восстанавливать их.
|
||
"""
|
||
def delete(self):
|
||
"""Soft delete вместо hard delete"""
|
||
return self.update(
|
||
is_deleted=True,
|
||
deleted_at=timezone.now()
|
||
)
|
||
|
||
def hard_delete(self):
|
||
"""Явный hard delete - удаляет из БД окончательно"""
|
||
return super().delete()
|
||
|
||
def restore(self):
|
||
"""Восстановление из удаленного состояния"""
|
||
return self.update(
|
||
is_deleted=False,
|
||
deleted_at=None,
|
||
deleted_by=None
|
||
)
|
||
|
||
def deleted_only(self):
|
||
"""Получить только удаленные элементы"""
|
||
return self.filter(is_deleted=True)
|
||
|
||
def not_deleted(self):
|
||
"""Получить только не удаленные элементы"""
|
||
return self.filter(is_deleted=False)
|
||
|
||
def with_deleted(self):
|
||
"""Получить все элементы включая удаленные"""
|
||
return self.all()
|
||
|
||
|
||
class SoftDeleteManager(models.Manager):
|
||
"""
|
||
Manager для работы с мягким удалением.
|
||
По умолчанию исключает удаленные элементы из запросов.
|
||
"""
|
||
def get_queryset(self):
|
||
return SoftDeleteQuerySet(self.model, using=self._db).filter(is_deleted=False)
|
||
|
||
def deleted_only(self):
|
||
"""Получить только удаленные элементы"""
|
||
return SoftDeleteQuerySet(self.model, using=self._db).filter(is_deleted=True)
|
||
|
||
def all_with_deleted(self):
|
||
"""Получить все элементы включая удаленные"""
|
||
return SoftDeleteQuerySet(self.model, using=self._db).all()
|