You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

310 lines
12 KiB

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Field, Div, HTML, Hidden, Fieldset, Submit
from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.forms import ALL_FIELDS, formset_factory
from django.urls import reverse_lazy
from cart.models import (
Buying, BUYING_STATUS_IN_CART, Offer, SupplyType, SupplyTarget, Discount, Order
)
from cart.tasks import send_user_order_notification, send_admin_order_notification
from contact_us.mixins import RequestNotifiable
from core.forms import QueryFormBase
from core.models import City
from core.utils import parse_path
from django.utils.translation import ugettext_lazy as _
from products.models import Product
class CartAddInlineForm(forms.ModelForm):
form_action = {'viewname': 'cart:add', 'kwargs': {}}
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.form_action = reverse_lazy(**self.form_action)
self.helper.layout = Layout(
Field('offer'),
Field('amount'),
Div(
Submit('add', value=_('Купить')),
css_class='catalog__btn'
)
)
super().__init__(*args, **kwargs)
def clean_amount(self):
amount = self.cleaned_data['amount']
offer = self.cleaned_data['offer']
if amount > offer.amount:
raise ValidationError('Колличество товара указано больше доступного')
elif amount <= 0:
raise ValidationError('Укажите колличество товара больше 0')
return amount
def save(self, cart, user, commit=True):
offer = Offer.active.get(self.offer)
self.instance.user = user
self.instance.offer = offer
self.instance.amount = self.cart[offer.product.id]['quantity']
self.instance.total_price = offer.product * self.cart[offer.product.id]['quantity']
return super().save(commit)
class Meta:
model = Buying
fields = ('offer', 'amount',)
widgets = {
'offer': forms.HiddenInput(),
'amount': forms.HiddenInput()
}
class CartRemoveBuyingForm(forms.ModelForm):
form_action = {'viewname': 'cart:remove', 'kwargs': {}}
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.form_action = reverse_lazy(**self.form_action)
self.helper.layout = Layout(
Field('offer'),
Div(
Submit('cancel', value=_('Убрать')),
css_class='catalog__btn'
)
)
super().__init__(*args, **kwargs)
class Meta:
model = Buying
fields = ('offer',)
widgets = {
'offer': forms.HiddenInput()
}
class CartCheckoutBuyingForm(forms.Form):
order = forms.Field()
offer = forms.Field()
amount = forms.IntegerField()
bonus_points = forms.IntegerField()
def get_initial_for_field(self, field, field_name):
if field_name == 'offer':
field = Offer.active.get(product_id=self.initia[field_name])
elif field_name == 'order':
field = Order.objects.get(order_code=self.initial[field_name])
elif field_name == 'amount' or field_name == 'bonus_points':
field.value = self.initial[field_name]
return super().get_initial_for_field(field, field_name)
def save(self, user):
buying = Buying()
buying.user = user
buying.offer = self.offer
buying.order = self.order
buying.bonus_points = self.bonus_points
buying.amount = self.amount
buying.total_price = self.offer.get_price_with_discount * self.amount
buying.save()
return buying
class CartCheckoutForm(RequestNotifiable, forms.ModelForm):
form_action = {'viewname': 'cart:confirm', 'kwargs': {}}
field_template = 'bootstrap/forms/cart_checkout.html'
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.form_action = reverse_lazy(**self.form_action)
self.helper.layout = Layout(
Field('customer_name', css_class="order__input", template=self.field_template),
Field('customer_email', css_class="order__input", template=self.field_template),
Field('customer_user', css_class="order__input", template=self.field_template),
Field('phone', css_class="order__input", template=self.field_template),
Field('customer_address', css_class="order__input", template=self.field_template),
Field('city', css_class="order__input", template=self.field_template),
Field('comment', css_class="order__input", template=self.field_template),
Div(
Submit('checkout', value=_('Подтвердить'), style="margin: 0 auto;"),
css_class='catalog__btn'
)
)
super().__init__(*args, **kwargs)
def save(self, commit=True):
if not City.objects.filter(name=self.cleaned_data['city']).exists():
city = City()
city.name = self.cleaned_data['city']
city.save()
self.instance.city = city
return super().save(commit)
def send_order_invoice(self, request):
return send_user_order_notification.delay(self.instance.id, request)
def send_order_request(self, request):
context = {
'from_email': settings.DEFAULT_FROM_EMAIL,
'recipients': (settings.DEFAULT_FROM_EMAIL,),
'email': {
'subject': _('У вас новый заказ'),
'order': self.instance,
},
'send_at_date': self.instance.create_at,
}
return send_admin_order_notification.delay(context)
class Meta:
model = Order
fields = (
'customer_name', 'customer_email', 'phone', 'customer_address', 'city', 'comment'
)
widgets = {
'city': forms.TextInput()
}
class ProductOfferPriceFilterForm(QueryFormBase):
min_price = 0
max_price = 9999
price = forms.IntegerField(min_value=0, max_value=0)
field_template = 'bootstrap/forms/product_filter.html'
title = _('Цена')
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'get'
self.helper.layout = Layout(
Div(HTML(self.title), css_class='category__title left-menu__price-item'),
Field('price', template=self.field_template)
)
super().__init__(*args, **kwargs)
self.helper.form_action = reverse_lazy(**self.form_action)
self.init_price_bounders()
self.init_field_params()
def init_price_bounders(self):
if Offer.active.exists():
off_qs = Offer.active
category_instance = ''
if self.form_action.get('kwargs', None):
category_instance = parse_path(self.form_action.get('kwargs').get('path', ''))
off_qs = Offer.active.filter(product__parent__name=category_instance,
product__name__icontains=self.query_params.get('name', ''))
if off_qs.exists():
self.min_price = round(off_qs.order_by('price').only('price').first().price, 0)
self.max_price = round(off_qs.order_by('-price').only('price').first().price, 0)
def init_field_params(self):
for field in self.fields:
if field == 'price':
self.fields[field].validators = [
MaxValueValidator(self.max_price),
MinValueValidator(self.min_price)
]
def get_initial_for_field(self, field, field_name):
return super().get_initial_for_field(field, field_name)
class ProductOfferSupplyTypeFilterForm(QueryFormBase):
supply_type = forms.ChoiceField()
field_template = 'bootstrap/forms/product_filter.html'
title = _('Тип поставки')
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'get'
self.helper.layout = Layout(
Div(HTML(self.title), css_class='category__title'),
Field('supply_type', template=self.field_template)
)
super().__init__(*args, **kwargs)
self.helper.form_action = reverse_lazy(**self.form_action)
def get_initial_for_field(self, field, field_name):
if field_name == 'supply_type':
sup_typ_qs = SupplyType.objects
category_instance = ''
if self.form_action.get('kwargs', None):
category_instance = parse_path(self.form_action.get('kwargs').get('path', ''))
off_qs = Offer.active.filter(product__parent__name=category_instance,
product__name__icontains=self.query_params.get('name', ''))
if off_qs.count():
sup_typ_qs = sup_typ_qs.filter(offer__pk__in=off_qs.all())
return sup_typ_qs.distinct('name').only('name', 'slug')
return super().get_initial_for_field(field, field_name)
class ProductOfferSupplyTargetFilterForm(QueryFormBase):
supply_target = forms.ChoiceField()
field_template = 'bootstrap/forms/product_filter.html'
title = _('Назначение')
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'get'
self.helper.layout = Layout(
Div(HTML(self.title), css_class='category__title'),
Field('supply_target', template=self.field_template)
)
super().__init__(*args, **kwargs)
self.helper.form_action = reverse_lazy(**self.form_action)
def get_initial_for_field(self, field, field_name):
if field_name == 'supply_target':
sup_tar_qs = SupplyTarget.objects
category_instance = ''
if self.form_action.get('kwargs', None):
category_instance = parse_path(self.form_action.get('kwargs').get('path', ''))
off_qs = Offer.active.filter(product__parent__name=category_instance,
product__name__icontains=self.query_params.get('name', ''))
if off_qs.count():
sup_tar_qs = sup_tar_qs.filter(product__pk__in=off_qs.all())
return sup_tar_qs.distinct('name').only('name', 'slug')
return super().get_initial_for_field(field, field_name)
# @TODO: NOT IMPLEMENTED ON THE FRONT END. TEST BEFORE PRODUCTION
class DiscountForm(forms.ModelForm):
class Meta:
model = Discount
fields = ('code',)
class OrderCreateForm(forms.ModelForm):
customer_name = forms.CharField(max_length=100, required=True, label='Customer_name',
widget=forms.TextInput(attrs={'placeholder': 'Ф.И.О.'}))
customer_phone = forms.CharField(required=True, label='Customer_phone',
widget=forms.TextInput(attrs={'placeholder': 'номер телефона'}))
customer_email = forms.EmailField(required=True, label='Customer_email',
widget=forms.TextInput(attrs={'placeholder': 'e-mail'}))
city = forms.CharField(max_length=100, label='City', widget=forms.TextInput(attrs={'placeholder': 'город'}))
class Meta:
model = Order
exclude = ('status',)