feat(discounts, orders): рефакторинг системы скидок - единый источник правды
- Добавлен combine_mode в форму создания/редактирования скидок - Добавлена колонка "Объединение" в список скидок с иконками - Добавлен фильтр по режиму объединения скидок - Добавлена валидация: только одна exclusive скидка на заказ - Удалены дублирующие поля из Order и OrderItem: - applied_discount, applied_promo_code, discount_amount - Скидки теперь хранятся только в DiscountApplication - Добавлены свойства для обратной совместимости Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -71,6 +71,7 @@ class DiscountListView(DiscountAccessMixin, ListView):
|
||||
discount_type = self.request.GET.get('type')
|
||||
scope = self.request.GET.get('scope')
|
||||
is_active = self.request.GET.get('is_active')
|
||||
combine_mode = self.request.GET.get('combine_mode')
|
||||
search = self.request.GET.get('search')
|
||||
|
||||
if discount_type:
|
||||
@@ -79,6 +80,8 @@ class DiscountListView(DiscountAccessMixin, ListView):
|
||||
queryset = queryset.filter(scope=scope)
|
||||
if is_active:
|
||||
queryset = queryset.filter(is_active=(is_active == 'active'))
|
||||
if combine_mode:
|
||||
queryset = queryset.filter(combine_mode=combine_mode)
|
||||
if search:
|
||||
queryset = queryset.filter(
|
||||
Q(name__icontains=search) | Q(description__icontains=search)
|
||||
@@ -92,6 +95,7 @@ class DiscountListView(DiscountAccessMixin, ListView):
|
||||
'type': self.request.GET.get('type', ''),
|
||||
'scope': self.request.GET.get('scope', ''),
|
||||
'is_active': self.request.GET.get('is_active', ''),
|
||||
'combine_mode': self.request.GET.get('combine_mode', ''),
|
||||
'search': self.request.GET.get('search', ''),
|
||||
}
|
||||
context['can_edit'] = self._can_edit()
|
||||
@@ -110,7 +114,7 @@ class DiscountCreateView(LoginRequiredMixin, RoleRequiredMixin, CreateView):
|
||||
template_name = 'discounts/discount_form.html'
|
||||
fields = [
|
||||
'name', 'description', 'discount_type', 'value', 'scope',
|
||||
'is_auto', 'is_active', 'priority',
|
||||
'is_auto', 'is_active', 'priority', 'combine_mode',
|
||||
'start_date', 'end_date',
|
||||
'min_order_amount', 'max_usage_count',
|
||||
'products', 'categories', 'excluded_products',
|
||||
@@ -119,6 +123,21 @@ class DiscountCreateView(LoginRequiredMixin, RoleRequiredMixin, CreateView):
|
||||
success_url = reverse_lazy('system_settings:discounts:list')
|
||||
|
||||
def form_valid(self, form):
|
||||
# Валидация: нельзя создать больше одной активной exclusive скидки на заказ
|
||||
if form.instance.combine_mode == 'exclusive' and form.instance.scope == 'order' and form.instance.is_active:
|
||||
existing_exclusive = Discount.objects.filter(
|
||||
combine_mode='exclusive',
|
||||
scope='order',
|
||||
is_active=True
|
||||
).exists()
|
||||
|
||||
if existing_exclusive:
|
||||
form.add_error(
|
||||
'combine_mode',
|
||||
'Уже существует активная исключающая скидка на заказ. Может быть только одна.'
|
||||
)
|
||||
return self.form_invalid(form)
|
||||
|
||||
form.instance.created_by = self.request.user
|
||||
messages.success(self.request, f'Скидка "{form.instance.name}" создана')
|
||||
return super().form_valid(form)
|
||||
@@ -142,7 +161,7 @@ class DiscountUpdateView(LoginRequiredMixin, RoleRequiredMixin, UpdateView):
|
||||
template_name = 'discounts/discount_form.html'
|
||||
fields = [
|
||||
'name', 'description', 'discount_type', 'value', 'scope',
|
||||
'is_auto', 'is_active', 'priority',
|
||||
'is_auto', 'is_active', 'priority', 'combine_mode',
|
||||
'start_date', 'end_date',
|
||||
'min_order_amount', 'max_usage_count',
|
||||
'products', 'categories', 'excluded_products',
|
||||
@@ -151,6 +170,21 @@ class DiscountUpdateView(LoginRequiredMixin, RoleRequiredMixin, UpdateView):
|
||||
success_url = reverse_lazy('system_settings:discounts:list')
|
||||
|
||||
def form_valid(self, form):
|
||||
# Валидация: нельзя создать больше одной активной exclusive скидки на заказ
|
||||
if form.instance.combine_mode == 'exclusive' and form.instance.scope == 'order' and form.instance.is_active:
|
||||
existing_exclusive = Discount.objects.filter(
|
||||
combine_mode='exclusive',
|
||||
scope='order',
|
||||
is_active=True
|
||||
).exclude(pk=self.object.pk).exists()
|
||||
|
||||
if existing_exclusive:
|
||||
form.add_error(
|
||||
'combine_mode',
|
||||
'Уже существует активная исключающая скидка на заказ. Может быть только одна.'
|
||||
)
|
||||
return self.form_invalid(form)
|
||||
|
||||
messages.success(self.request, f'Скидка "{form.instance.name}" обновлена')
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user