update cart

remotes/origin/HEAD
Max Yakovenko 8 years ago
parent 87df0e9285
commit 4d74e4d173
  1. 91
      cart/forms.py
  2. 152
      cart/models.py
  3. 54
      cart/tasks.py
  4. 3
      cart/urls.py
  5. 1
      cart/utils.py
  6. 85
      cart/views.py

@ -10,7 +10,10 @@ from django.urls import reverse_lazy
from cart.models import ( from cart.models import (
Buying, BUYING_STATUS_IN_CART, Offer, SupplyType, SupplyTarget, Discount, Order 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.forms import QueryFormBase
from core.models import City
from core.utils import parse_path from core.utils import parse_path
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -28,15 +31,13 @@ class CartAddInlineForm(forms.ModelForm):
Field('offer'), Field('offer'),
Field('amount'), Field('amount'),
Div( Div(
Submit('Купить',value='submit'), Submit('add', value=_('Купить')),
css_class='catalog__btn' css_class='catalog__btn'
) )
) )
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def clean_amount(self): def clean_amount(self):
amount = self.cleaned_data['amount'] amount = self.cleaned_data['amount']
offer = self.cleaned_data['offer'] offer = self.cleaned_data['offer']
@ -73,7 +74,7 @@ class CartRemoveBuyingForm(forms.ModelForm):
self.helper.layout = Layout( self.helper.layout = Layout(
Field('offer'), Field('offer'),
Div( Div(
Submit('Убрать'), Submit('cancel', value=_('Убрать')),
css_class='catalog__btn' css_class='catalog__btn'
) )
) )
@ -88,38 +89,90 @@ class CartRemoveBuyingForm(forms.ModelForm):
} }
CartRemoveBuyingFormset = formset_factory(CartRemoveBuyingForm) 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'
class CartCheckoutForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_method = 'post' self.helper.form_method = 'post'
self.helper.form_action = reverse_lazy(**self.form_action) self.helper.form_action = reverse_lazy(**self.form_action)
self.helper.layout = Layout( self.helper.layout = Layout(
Field('customer_name'), Field('customer_name', css_class="order__input", template=self.field_template),
Field('customer_email'), Field('customer_email', css_class="order__input", template=self.field_template),
Field('customer_user'), Field('customer_user', css_class="order__input", template=self.field_template),
Field('phone'), Field('phone', css_class="order__input", template=self.field_template),
Field('customer_address'), Field('customer_address', css_class="order__input", template=self.field_template),
Field('city'), Field('city', css_class="order__input", template=self.field_template),
Field('buyings'), Field('comment', css_class="order__input", template=self.field_template),
Field('comment'),
Div( Div(
Submit('Подвердить'), Submit('checkout', value=_('Подтвердить'), style="margin: 0 auto;"),
css_class='catalog__btn' css_class='catalog__btn'
) )
) )
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
class Model: 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 model = Order
fields = ( fields = (
'customer_name', 'customer_email', 'customer_user', 'customer_name', 'customer_email', 'phone', 'customer_address', 'city', 'comment'
'phone', 'customer_address', 'city', 'buyings',
'comment'
) )
widgets = {
'city': forms.TextInput()
}
class ProductOfferPriceFilterForm(QueryFormBase): class ProductOfferPriceFilterForm(QueryFormBase):
min_price = 0 min_price = 0

@ -99,12 +99,20 @@ class SupplyTarget(AbstractDateTimeModel):
class Discount(AbstractDateTimeModel): class Discount(AbstractDateTimeModel):
code = models.CharField(max_length=50, blank=True, unique=True, default=str(uuid.uuid4())) def upload_file_to(self, filename):
valid_from = models.DateTimeField(auto_now_add=True, blank=True) return "discounts/{name}/{filename}".format(**{
valid_to = models.DateTimeField(default=now() + timedelta(days=7), blank=True) 'name': self.name,
value = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100)], default=0, 'filename': filename
})
name = models.CharField(_('Имя'), max_length=255)
image = models.FileField(_('Изображение'), upload_to=upload_file_to, blank=True, null=True)
code = models.CharField(_('Код'), max_length=50, blank=True, unique=True, default=str(uuid.uuid4()))
valid_from = models.DateTimeField(_('Начало'), auto_now_add=True, blank=True)
valid_to = models.DateTimeField(_('Конец'), default=now() + timedelta(days=7), blank=True)
value = models.IntegerField(_('Процент'), validators=[MinValueValidator(0), MaxValueValidator(100)], default=0,
help_text=_('Указываем целым числом. Пример: 30 = 30%')) help_text=_('Указываем целым числом. Пример: 30 = 30%'))
active = models.BooleanField(default=True) active = models.BooleanField(_('Активная'), default=True)
def __str__(self): def __str__(self):
return self.code return self.code
@ -171,71 +179,6 @@ class Offer(AbstractStatusModel):
verbose_name_plural = _('Позиции') verbose_name_plural = _('Позиции')
# ------------------------------------------ Buying status --------------------------------------------------- #
BUYING_STATUS_IN_CART = 25
BUYING_STATUS_PENDING = 50
BUYING_STATUS_PAID = 75
BUYING_STATUS_CHOICES = (
(BUYING_STATUS_IN_CART, _('В корзине')),
(BUYING_STATUS_PENDING, _('Обрабатываеться')),
(BUYING_STATUS_PAID, _('Оплаченно'))
)
BUYING_DEFAULT_CHOICE = BUYING_STATUS_IN_CART
class BuyingManager(ActiveOnlyManager, models.Manager):
def get_user_buyings(self, user):
qs = self.get_queryset()
return qs.filter(user=user).all()
def get_buying_total_price(self, user=None):
qs = self.get_user_buyings(user) if user else self.get_queryset()
return qs.aggregate(Sum('total_price'))
def get_buying_total_bonus_points(self, user=None):
qs = self.get_user_buyings(user) if user else self.get_queryset()
return qs.aggregate(Sum('bonus_points'))
def get_buying_total_cashback(self, user=None):
qs = self.get_user_buyings(user) if user else self.get_queryset()
return qs.select_related('buying_cashback').aggregate(Sum('amount'))
class Buying(AbstractStatusModel):
user = models.ForeignKey(get_user_model(), verbose_name=_('пользователь'), on_delete=models.CASCADE)
offer = models.ForeignKey(Offer, verbose_name=_('позиция'), on_delete=models.CASCADE)
bonus_points = models.IntegerField(_('бонусы'), validators=(MinValueValidator(0),))
status = models.SmallIntegerField(_('статус'), default=BUYING_DEFAULT_CHOICE, choices=BUYING_STATUS_CHOICES)
amount = models.SmallIntegerField(_('колличество'), default=0)
total_price = models.DecimalField(_('цена'), max_digits=10, decimal_places=2)
active = BuyingManager()
@property
def is_in_cart(self):
return self.status == BUYING_STATUS_IN_CART
@property
def is_pending(self):
return self.status == BUYING_STATUS_PENDING
@property
def is_paid(self):
return self.status == BUYING_STATUS_PAID
def __str__(self):
return "{product_name}({product_amount}) - {price}".format(**{
'product_name': self.offer.product.name,
'product_amount': self.amount,
'price': self.total_price
})
class Meta:
verbose_name = _('Покупка')
verbose_name_plural = _('Покупки')
STATUS_GAINED = 0 STATUS_GAINED = 0
STATUS_SPENT = 100 STATUS_SPENT = 100
CASHBACK_STATUS_CHOICES = ( CASHBACK_STATUS_CHOICES = (
@ -285,7 +228,7 @@ ORDER_STATUS_DEFAULT = ORDER_STATUS_NEW
class Order(AbstractStatusModel): class Order(AbstractStatusModel):
order_code = models.CharField(_('код заказа'), max_length=255, default=str(uuid.uuid4())) order_code = models.CharField(_('код заказа'), max_length=255, default=str(uuid.uuid4()))
customer_name = models.CharField(_('bмя'), max_length=255) customer_name = models.CharField(_('имя'), max_length=255)
customer_email = models.EmailField(_('email'), blank=True, null=True, default=None) customer_email = models.EmailField(_('email'), blank=True, null=True, default=None)
customer_user = models.ForeignKey( customer_user = models.ForeignKey(
get_user_model(), on_delete=models.SET_NULL, get_user_model(), on_delete=models.SET_NULL,
@ -302,7 +245,6 @@ class Order(AbstractStatusModel):
customer_address = models.TextField(_('адрес')) customer_address = models.TextField(_('адрес'))
city = models.ForeignKey(City, on_delete=models.PROTECT, verbose_name=_('Город')) city = models.ForeignKey(City, on_delete=models.PROTECT, verbose_name=_('Город'))
buyings = models.ManyToManyField(Buying, verbose_name=_('Покупки'))
total_price = models.DecimalField(_('стоимость'), max_digits=10, decimal_places=2, default=0) total_price = models.DecimalField(_('стоимость'), max_digits=10, decimal_places=2, default=0)
comment = models.TextField(_('комментарий'), blank=True, null=True, default=None) comment = models.TextField(_('комментарий'), blank=True, null=True, default=None)
status = models.SmallIntegerField(_('статус'), default=ORDER_STATUS_CHOICES, choices=ORDER_STATUS_DEFAULT) status = models.SmallIntegerField(_('статус'), default=ORDER_STATUS_CHOICES, choices=ORDER_STATUS_DEFAULT)
@ -316,6 +258,72 @@ class Order(AbstractStatusModel):
verbose_name_plural = _('Заказы') verbose_name_plural = _('Заказы')
# ------------------------------------------ Buying status --------------------------------------------------- #
BUYING_STATUS_IN_CART = 25
BUYING_STATUS_PENDING = 50
BUYING_STATUS_PAID = 75
BUYING_STATUS_CHOICES = (
(BUYING_STATUS_IN_CART, _('В корзине')),
(BUYING_STATUS_PENDING, _('Обрабатываеться')),
(BUYING_STATUS_PAID, _('Оплаченно'))
)
BUYING_DEFAULT_CHOICE = BUYING_STATUS_IN_CART
class BuyingManager(ActiveOnlyManager, models.Manager):
def get_user_buyings(self, user):
qs = self.get_queryset()
return qs.filter(user=user).all()
def get_buying_total_price(self, user=None):
qs = self.get_user_buyings(user) if user else self.get_queryset()
return qs.aggregate(Sum('total_price'))
def get_buying_total_bonus_points(self, user=None):
qs = self.get_user_buyings(user) if user else self.get_queryset()
return qs.aggregate(Sum('bonus_points'))
def get_buying_total_cashback(self, user=None):
qs = self.get_user_buyings(user) if user else self.get_queryset()
return qs.select_related('buying_cashback').aggregate(Sum('amount'))
class Buying(AbstractStatusModel):
order = models.ForeignKey(Order, verbose_name=_('пользователь'), on_delete=models.CASCADE)
user = models.ForeignKey(get_user_model(), verbose_name=_('пользователь'), on_delete=models.CASCADE)
offer = models.ForeignKey(Offer, verbose_name=_('позиция'), on_delete=models.CASCADE)
bonus_points = models.IntegerField(_('бонусы'), validators=(MinValueValidator(0),))
status = models.SmallIntegerField(_('статус'), default=BUYING_DEFAULT_CHOICE, choices=BUYING_STATUS_CHOICES)
amount = models.SmallIntegerField(_('колличество'), default=0)
total_price = models.DecimalField(_('цена'), max_digits=10, decimal_places=2)
active = BuyingManager()
@property
def is_in_cart(self):
return self.status == BUYING_STATUS_IN_CART
@property
def is_pending(self):
return self.status == BUYING_STATUS_PENDING
@property
def is_paid(self):
return self.status == BUYING_STATUS_PAID
def __str__(self):
return "{product_name}({product_amount}) - {price}".format(**{
'product_name': self.offer.product.name,
'product_amount': self.amount,
'price': self.total_price
})
class Meta:
verbose_name = _('Покупка')
verbose_name_plural = _('Покупки')
@receiver(post_save, sender=Order) @receiver(post_save, sender=Order)
def product_in_order_post_save(sender, instance, created, **kwargs): def product_in_order_post_save(sender, instance, created, **kwargs):
order = instance.order order = instance.order

@ -1,23 +1,17 @@
import celery import celery
from django.conf import settings
from celery import task
from django.template.loader import render_to_string
from django.core.mail import send_mail, EmailMessage
from io import BytesIO
import weasyprint import weasyprint
import pytils import pytils
from io import BytesIO
from cart.models import Order from django.conf import settings
from django.template.loader import render_to_string, get_template
from django.core.mail import EmailMessage, EmailMultiAlternatives
SUPPLIER_INFO = '''ООО "Русские Программы", ИНН 7713409230, КПП 771301001, from cart.models import Order
127411, Москва г, Дмитровское ш., дом 157, корпус 7, тел.: +74957258950'''
requisites = {'name': 'ООО "Русские Программы"', 'bank': 'АО "СМП БАНК" Г. МОСКВА', 'INN': '7713409230',
'KPP': '771301001', 'BIK': '44525503', 'bank_acc': '30101810545250000503', 'acc': '40702810300750000177',
'sup_info': SUPPLIER_INFO}
@celery.task @celery.task
def send_user_order_notification(order_id): def send_user_order_notification(order_id, request):
""" """
Sending Email of order creating Sending Email of order creating
""" """
@ -26,20 +20,44 @@ def send_user_order_notification(order_id):
verb_cur = pytils.numeral.choose_plural(round(order.total_price), ("рубль", "рубля", "рублей")) verb_cur = pytils.numeral.choose_plural(round(order.total_price), ("рубль", "рубля", "рублей"))
subject = 'Заказ № {}'.format(order.id) subject = 'Заказ № {}'.format(order.id)
message = 'Уважаемый, {}, номер Вашего заказа {}. \ message = 'Уважаемый, {}, номер Вашего заказа {}. \
Пожалуйста, совершите платеж по поручению в приложении к этому письму в течение 14 дней.'.format(order.customer_name, order.id) Пожалуйста, совершите платеж по поручению в приложении к этому письму в течение 14 дней.'.format(
order.customer_name, order.id)
mail_send = EmailMessage(subject, message, 'admin@myshop.ru', [order.customer_email]) mail_send = EmailMessage(subject, message, 'admin@myshop.ru', [order.customer_email])
# html = render_to_string('orders:AdminOrderPDF', args=[order_id]) # html = render_to_string('orders:AdminOrderPDF', args=[order_id])
html = render_to_string('orders/pdf.html', {**requisites, 'order': order, html = render_to_string('orders/pdf.html', {**settings.PAY_REQUISITES, 'order': order,
'verb_cur': verb_cur, 'verb_price': verb_price}) 'verb_cur': verb_cur, 'verb_price': verb_price})
rendered_html = html.encode(encoding="UTF-8") rendered_html = html.encode(encoding="UTF-8")
out = BytesIO() out = BytesIO()
weasyprint.HTML(string=rendered_html).write_pdf(out, weasyprint.HTML(string=rendered_html).write_pdf(out,
stylesheets=[weasyprint.CSS(settings.STATIC_ROOT + 'css/bootstrap.min.css')]) stylesheets=[
weasyprint.CSS(settings.STATIC_ROOT + 'css/build.css')])
# weasyprint.HTML(string=rendered_html, base_url=request.build_absolute_uri()).write_pdf(response, order_invoice_name = 'Order_' + order.order_code
# stylesheets=[weasyprint.CSS(settings.STATIC_ROOT + '/css/bootstrap.min.css')]) weasyprint.HTML(string=rendered_html, base_url=request.build_absolute_uri()).write_pdf(order_invoice_name,
stylesheets=[weasyprint.CSS(
settings.STATIC_ROOT + '/css/build.css')])
mail_send.attach('order_{}.pdf'.format(order_id), out.getvalue(), 'application/pdf') mail_send.attach('order_{}.pdf'.format(order_id), out.getvalue(), 'application/pdf')
mail_send.send() mail_send.send()
return mail_send return mail_send
@celery.task
def send_admin_order_notification(context):
body = get_template('emails/html/admin_order_request.html')
body_text = get_template('emails/txt/admin_order_request.txt')
email = EmailMultiAlternatives(
context['email']['subject'],
body_text.render(context['email']),
context['from_email'],
context['recipients']
)
email.attach_alternative(body.render(context['email']), 'text/html')
try:
email.send()
except Exception as e:
return False
return True

@ -6,10 +6,11 @@ from . import views
urlpatterns = [ urlpatterns = [
re_path(r'^history/', views.BuyingsHistory.as_view(), name='history'), re_path(r'^history/', views.BuyingsHistory.as_view(), name='history'),
re_path(r'^buyings/$', views.CartView.as_view(), name='buyings'), re_path(r'^buyings/$', views.CartView.as_view(), name='buyings'),
re_path(r'^discounts/$', views.DiscountListView.as_view(), name='discounts'),
re_path(r'^add/$', views.CartAddView.as_view(), name='add'), re_path(r'^add/$', views.CartAddView.as_view(), name='add'),
re_path(r'^remove/$', views.CartRemoveView.as_view(), name='remove'), re_path(r'^remove/$', views.CartRemoveView.as_view(), name='remove'),
re_path(r'^checkout/$', views.CartCheckoutView.as_view(),name='checkout'), re_path(r'^checkout/$', views.CartCheckoutView.as_view(), name='checkout'),
re_path(r'^confirm/$', views.CartConfirmView.as_view(), name='confirm'), re_path(r'^confirm/$', views.CartConfirmView.as_view(), name='confirm'),
# discount: @TODO: check if this logic is ready for production # discount: @TODO: check if this logic is ready for production

@ -29,6 +29,7 @@ class Cart(object):
self.store.modified = True self.store.modified = True
def remove(self, offer_id): def remove(self, offer_id):
offer_id = str(offer_id)
if offer_id in self.cart: if offer_id in self.cart:
del self.cart[offer_id] del self.cart[offer_id]
self.save() self.save()

@ -1,26 +1,30 @@
import datetime import datetime
import logging
import uuid import uuid
from functools import reduce from functools import reduce
from decimal import Decimal from decimal import Decimal
from django.conf import settings from django.conf import settings
from django.db import transaction
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic.edit import BaseFormView from django.views.generic import ListView
from cart.utils import Cart
from cart.models import Buying, Discount, Offer from cart.models import Buying, Discount, Offer
from core.views import ProtectedListView, ProtectedTemplateView, ProtectedView, ProtectedFormView from core.models import City
from core.views import ProtectedListView, ProtectedTemplateView, ProtectedView, ProtectedFormView, ProtectedBaseFormView
from .forms import ( from .forms import (
CartRemoveBuyingForm, CartRemoveBuyingForm,
DiscountForm, DiscountForm,
CartAddInlineForm, CartCheckoutForm CartAddInlineForm, CartCheckoutForm,
) CartCheckoutBuyingForm)
logger = logging.getLogger(__name__)
class CartAddView(BaseFormView):
class CartAddView(ProtectedBaseFormView):
http_method_names = ('post',) http_method_names = ('post',)
form_class = CartAddInlineForm form_class = CartAddInlineForm
@ -32,7 +36,7 @@ class CartAddView(BaseFormView):
return super().form_valid(form) return super().form_valid(form)
class CartRemoveView(BaseFormView): class CartRemoveView(ProtectedBaseFormView):
http_method_names = ('post',) http_method_names = ('post',)
model = Offer model = Offer
form_class = CartRemoveBuyingForm form_class = CartRemoveBuyingForm
@ -41,8 +45,8 @@ class CartRemoveView(BaseFormView):
return self.request.META.get('HTTP_REFERRER', reverse_lazy('products:product_list')) return self.request.META.get('HTTP_REFERRER', reverse_lazy('products:product_list'))
def form_valid(self, form): def form_valid(self, form):
self.request.cart.remove(form.cleaned_data['offer']) self.request.cart.remove(form.cleaned_data['offer'].product_id)
return super().form_valid() return super().form_valid(form)
class CartView(ProtectedListView): class CartView(ProtectedListView):
@ -75,7 +79,7 @@ class CartView(ProtectedListView):
context = super().get_context_data(object_list=object_list, **kwargs) context = super().get_context_data(object_list=object_list, **kwargs)
context['title'] = self.title context['title'] = self.title
context['total_price'] = self.get_total_price(self.object_list) context['total_price'] = self.get_total_price(self.object_list)
context['total_price_currency'] = context['total_cashback_currency'] = self.object_list.first().currency.sign context['total_price_currency'] = context['total_cashback_currency'] = self.object_list.first().currency.sign if self.object_list.first() else ''
context['total_cashback'] = self.get_total_cashback(self.object_list) context['total_cashback'] = self.get_total_cashback(self.object_list)
return context return context
@ -84,17 +88,50 @@ class CartCheckoutView(ProtectedFormView):
http_method_names = ('get', 'post',) http_method_names = ('get', 'post',)
template_name = 'cart/checkout.html' template_name = 'cart/checkout.html'
form_class = CartCheckoutForm form_class = CartCheckoutForm
title = _('Оформление заказа')
def get_form_kwargs(self): def get_form_kwargs(self):
return super().get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs['initial'] = {
def form_valid(self, form): 'customer_name': self.request.user.profile.full_name,
return super().form_valid(form) 'customer_email': self.request.user.email,
'phone': self.request.user.profile.phone,
'customer_address': self.request.user.profile.address,
class CartConfirmView(ProtectedTemplateView): 'city': City.objects.filter(name=self.request.user.profile.city).first()
}
return kwargs
class CartConfirmView(ProtectedFormView):
http_method_names = ('post',) http_method_names = ('post',)
template_name = 'cart/confirm.html' template_name = 'cart/confirm.html'
form_class = CartCheckoutForm
title = _('Подтверждение заказа')
def form_valid(self, form):
if form.is_valid():
try:
with transaction.atomic():
form.save()
for item in self.request.cart:
buying_form = CartCheckoutBuyingForm(initial={
'offer': item,
'order': form.instance.order_code,
'amount': self.request.cart[item]['quantity']
})
buying_form.save(self.request.user)
form.send_order_invoice(self.request)
form.send_order_request(self.request)
self.request.cart.clear()
except Exception as e:
logger.critical(e)
return super().form_invalid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = self.title
return context
class BuyingsHistory(ProtectedListView): class BuyingsHistory(ProtectedListView):
@ -114,6 +151,18 @@ class BuyingsHistory(ProtectedListView):
context['title'] = self.title context['title'] = self.title
return context return context
class DiscountListView(ListView):
template_name = 'cart/discount_list.html'
model = Discount
title = _('Акции / Cashback')
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs)
context['title'] = self.title
return context
# Discount views # @TODO: TEST FOR PRODUCTION # Discount views # @TODO: TEST FOR PRODUCTION
class PointsApply(ProtectedTemplateView): class PointsApply(ProtectedTemplateView):
http_method_names = ('post',) http_method_names = ('post',)
@ -124,8 +173,6 @@ class PointsApply(ProtectedTemplateView):
return redirect('cart:buyings') return redirect('cart:buyings')
class PointsRevoke(ProtectedView): class PointsRevoke(ProtectedView):
http_method_names = ('post',) http_method_names = ('post',)

Loading…
Cancel
Save