refactor(db): консолидация миграций и рефакторинг кода
Объединены изменения из промежуточных миграций в начальные миграции для упрощения истории базы данных. Удалены миграции: accounts/0002, discounts/0002, orders/0003-0004, products/0002-0005, user_roles/0002, system_settings/0001-0002, integrations/0001-0002. Добавлена автоматическая creation пользователя при установке пароля. Обновлен UI страницы установки пароля с кастомным стилем. Добавлен conditional rendering для кнопки синхронизации Recommerce. Исправлены редиректы с 'index' на '/' в accounts views. Добавлена проверка request.tenant в navbar и authenticate метод в auth backend.
This commit is contained in:
@@ -175,7 +175,7 @@ class ProductDetailView(LoginRequiredMixin, ManagerOwnerRequiredMixin, DetailVie
|
||||
product_photos.sort(key=lambda x: (x.order, x.created_at))
|
||||
context['product_photos'] = product_photos
|
||||
context['photos_count'] = len(product_photos)
|
||||
|
||||
|
||||
# Кешируем cost_price_details, чтобы не делать множественные запросы к БД
|
||||
from ..services.cost_calculator import ProductCostCalculator
|
||||
context['cost_price_details'] = ProductCostCalculator.get_cost_details(self.object)
|
||||
@@ -277,7 +277,7 @@ class CombinedProductListView(LoginRequiredMixin, ManagerOwnerRequiredMixin, Lis
|
||||
def get_queryset(self):
|
||||
# Получаем фильтр по типу
|
||||
type_filter = self.request.GET.get('type', 'all')
|
||||
|
||||
|
||||
# Получаем товары и комплекты (только постоянные комплекты)
|
||||
# Аннотируем товары данными об остатках из агрегированной таблицы Stock
|
||||
total_available = Coalesce(Sum('stocks__quantity_available'), Value(0), output_field=DecimalField())
|
||||
@@ -331,13 +331,13 @@ class CombinedProductListView(LoginRequiredMixin, ManagerOwnerRequiredMixin, Lis
|
||||
elif is_active_filter == '0':
|
||||
products = products.filter(status__in=['archived', 'discontinued'])
|
||||
kits = kits.filter(status__in=['archived', 'discontinued'])
|
||||
|
||||
|
||||
# Фильтрация по наличию (только для товаров)
|
||||
if in_stock_filter == '1':
|
||||
products = products.filter(in_stock=True)
|
||||
elif in_stock_filter == '0':
|
||||
products = products.filter(in_stock=False)
|
||||
|
||||
|
||||
# Фильтрация по тегам
|
||||
if tags:
|
||||
products = products.filter(tags__id__in=tags).distinct()
|
||||
@@ -382,12 +382,12 @@ class CombinedProductListView(LoginRequiredMixin, ManagerOwnerRequiredMixin, Lis
|
||||
# Применяем фильтр по типу
|
||||
products_list = []
|
||||
kits_list = []
|
||||
|
||||
|
||||
if type_filter in ['all', 'products']:
|
||||
products_list = list(products.order_by('-created_at'))
|
||||
for p in products_list:
|
||||
p.item_type = 'product'
|
||||
|
||||
|
||||
if type_filter in ['all', 'kits']:
|
||||
kits_list = list(kits.order_by('-created_at'))
|
||||
for k in kits_list:
|
||||
@@ -411,6 +411,11 @@ class CombinedProductListView(LoginRequiredMixin, ManagerOwnerRequiredMixin, Lis
|
||||
from ..models.base import BaseProductEntity
|
||||
item_statuses = BaseProductEntity.STATUS_CHOICES
|
||||
|
||||
# Получаем состояние интеграции Recommerce
|
||||
from integrations.models import RecommerceIntegration
|
||||
recommerce_integration = RecommerceIntegration.objects.first()
|
||||
context['recommerce_integration_enabled'] = recommerce_integration.is_active if recommerce_integration else False
|
||||
|
||||
# Данные для фильтров
|
||||
context['filters'] = {
|
||||
'categories': ProductCategory.objects.filter(is_active=True),
|
||||
@@ -431,7 +436,7 @@ class CombinedProductListView(LoginRequiredMixin, ManagerOwnerRequiredMixin, Lis
|
||||
'has_discount': self.request.GET.get('has_discount', ''),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
context['item_statuses'] = item_statuses
|
||||
|
||||
# Кнопки действий
|
||||
|
||||
Reference in New Issue
Block a user