# -*- coding: utf-8 -*- from django import forms from django.forms import inlineformset_factory from .models import Order, OrderItem from customers.models import Customer, Address from shops.models import Shop from products.models import Product, ProductKit class OrderForm(forms.ModelForm): """Форма для создания и редактирования заказа""" class Meta: model = Order fields = [ 'customer', 'is_delivery', 'delivery_address', 'pickup_shop', 'delivery_date', 'delivery_time_start', 'delivery_time_end', 'delivery_cost', 'customer_is_recipient', 'recipient_name', 'recipient_phone', 'status', 'payment_method', 'discount_amount', 'is_anonymous', 'special_instructions', ] widgets = { 'delivery_date': forms.DateInput(attrs={'type': 'date'}), 'delivery_time_start': forms.TimeInput(attrs={'type': 'time'}), 'delivery_time_end': forms.TimeInput(attrs={'type': 'time'}), 'special_instructions': forms.Textarea(attrs={'rows': 3}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Добавляем Bootstrap классы ко всем полям for field_name, field in self.fields.items(): if isinstance(field.widget, forms.CheckboxInput): field.widget.attrs.update({'class': 'form-check-input'}) elif isinstance(field.widget, forms.Textarea): field.widget.attrs.update({'class': 'form-control', 'rows': 3}) else: field.widget.attrs.update({'class': 'form-control'}) # Select2 для выпадающих списков self.fields['customer'].widget.attrs.update({ 'class': 'form-select select2', 'data-placeholder': 'Выберите клиента' }) self.fields['delivery_address'].widget.attrs.update({ 'class': 'form-select select2', 'data-placeholder': 'Выберите адрес доставки' }) self.fields['delivery_address'].required = False self.fields['pickup_shop'].widget.attrs.update({ 'class': 'form-select select2', 'data-placeholder': 'Выберите точку самовывоза' }) self.fields['pickup_shop'].required = False # Опциональные поля даты/времени self.fields['delivery_date'].required = False self.fields['delivery_time_start'].required = False self.fields['delivery_time_end'].required = False # Подсказки self.fields['is_delivery'].label = 'С доставкой' self.fields['customer_is_recipient'].label = 'Покупатель = получатель' # Поля получателя опциональны self.fields['recipient_name'].required = False self.fields['recipient_phone'].required = False class OrderItemForm(forms.ModelForm): """Форма для позиции заказа""" class Meta: model = OrderItem fields = ['product', 'product_kit', 'quantity', 'price', 'is_custom_price'] widgets = { 'quantity': forms.NumberInput(attrs={'min': 1, 'value': 1}), # Скрываем поля product и product_kit - они будут заполняться через JS 'product': forms.HiddenInput(), 'product_kit': forms.HiddenInput(), 'is_custom_price': forms.HiddenInput(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Bootstrap классы for field_name, field in self.fields.items(): if not isinstance(field.widget, forms.HiddenInput): field.widget.attrs.update({'class': 'form-control'}) # Поля product и product_kit опциональны self.fields['product'].required = False self.fields['product_kit'].required = False # Поле цены заполняется автоматически, но можно редактировать вручную self.fields['price'].widget.attrs.update({ 'placeholder': 'Цена', 'step': '0.01' }) self.fields['price'].required = False # Поле is_custom_price устанавливается через JS self.fields['is_custom_price'].required = False def clean(self): """Валидация: должен быть выбран либо товар, либо комплект (не оба, не ни один)""" cleaned_data = super().clean() product = cleaned_data.get('product') product_kit = cleaned_data.get('product_kit') quantity = cleaned_data.get('quantity') # Пустая форма - это нормально (будет удалена) if not product and not product_kit: # Обнуляем количество для пустых форм cleaned_data['quantity'] = None return cleaned_data # Проверка: нельзя выбрать оба одновременно if product and product_kit: raise forms.ValidationError( 'Нельзя указывать одновременно товар и комплект. Выберите что-то одно.' ) # Проверка: если выбрано что-то, количество обязательно if (product or product_kit): if not quantity or quantity <= 0: raise forms.ValidationError('Необходимо указать количество больше 0') return cleaned_data # Formset для inline добавления товаров в заказ OrderItemFormSet = inlineformset_factory( Order, OrderItem, form=OrderItemForm, extra=1, # Одна пустая форма для добавления can_delete=True, min_num=1, # Минимум 1 товар в заказе validate_min=True, )