parent
d712f2f068
commit
80011eebb8
11 changed files with 260 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||||||
|
from django.contrib import admin |
||||||
|
|
||||||
|
# Register your models here. |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
from django.apps import AppConfig |
||||||
|
|
||||||
|
|
||||||
|
class CartConfig(AppConfig): |
||||||
|
name = 'cart' |
||||||
@ -0,0 +1,87 @@ |
|||||||
|
from decimal import Decimal |
||||||
|
from django.conf import settings |
||||||
|
from django.contrib import auth |
||||||
|
from products.models import Product |
||||||
|
# from discount.models import Discount |
||||||
|
|
||||||
|
class Cart(object): |
||||||
|
def __init__(self, request): |
||||||
|
self.session = request.session |
||||||
|
# self.discount_id = self.session.get('discount_id') |
||||||
|
if request.user.is_authenticated(): |
||||||
|
# self.points = self.session.get('points') |
||||||
|
self.points_quant = auth.get_user(request).profile.user_points |
||||||
|
cart = self.session.get(settings.CART_SESSION_ID) |
||||||
|
if not cart: |
||||||
|
request.session['points'] = False |
||||||
|
cart = self.session[settings.CART_SESSION_ID] = {} |
||||||
|
self.cart = cart |
||||||
|
|
||||||
|
def add(self, offer, price_per_itom, quantity=1, update_quantity=False): |
||||||
|
offer_slug = offer.slug |
||||||
|
if offer_slug not in self.cart: |
||||||
|
self.cart[offer_slug] = {'quantity': 0, |
||||||
|
'price': str(price_per_itom)} |
||||||
|
if update_quantity: |
||||||
|
self.cart[offer_slug]['quantity'] = int(quantity) |
||||||
|
else: |
||||||
|
self.cart[offer_slug]['quantity'] += int(quantity) |
||||||
|
self.save() |
||||||
|
|
||||||
|
def save(self): |
||||||
|
self.session[settings.CART_SESSION_ID] = self.cart |
||||||
|
self.session.modified = True |
||||||
|
|
||||||
|
def remove(self, offer_slug): |
||||||
|
# product_id = str(products.id) |
||||||
|
if offer_slug in self.cart: |
||||||
|
del self.cart[offer_slug] |
||||||
|
self.save() |
||||||
|
|
||||||
|
def __iter__(self): |
||||||
|
offers_ids = self.cart.keys() |
||||||
|
offers = Offer.objects.filter(slug__in=offers_ids) |
||||||
|
|
||||||
|
for offer in offers: |
||||||
|
self.cart[str(offer.slug)]['offer'] = offer |
||||||
|
|
||||||
|
for item in self.cart.values(): |
||||||
|
item['price'] = Decimal(item['price']) |
||||||
|
item['total_price'] = item['price'] * item['quantity'] |
||||||
|
yield item |
||||||
|
|
||||||
|
def __len__(self): |
||||||
|
return sum(item['quantity'] for item in self.cart.values()) |
||||||
|
|
||||||
|
def get_total_price(self): |
||||||
|
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values()) |
||||||
|
|
||||||
|
def get_max(self): |
||||||
|
return min(self.points_quant, self.get_total_price() - 1) |
||||||
|
|
||||||
|
def clear(self): |
||||||
|
del self.session[settings.CART_SESSION_ID] |
||||||
|
self.session.modified = True |
||||||
|
|
||||||
|
# @property |
||||||
|
# def discount(self): |
||||||
|
# if self.discount_id: |
||||||
|
# return Discount.objects.get(id=self.discount_id) |
||||||
|
# return None |
||||||
|
|
||||||
|
# def get_discount(self): |
||||||
|
# if self.discount: |
||||||
|
# return (self.discount.discount / Decimal('100')) * self.get_total_price() |
||||||
|
# return Decimal('0') |
||||||
|
|
||||||
|
# def get_total_price_after_discount(self): |
||||||
|
# return self.get_total_price() - self.get_discount() |
||||||
|
|
||||||
|
def get_total_deduct_points(self): |
||||||
|
total_price = self.get_total_price() |
||||||
|
if total_price <= self.points_quant: |
||||||
|
# self.points_quant = self.points_quant - total_price + 1 |
||||||
|
# self.save() |
||||||
|
return 1 |
||||||
|
return total_price - self.points_quant |
||||||
|
|
||||||
@ -0,0 +1,6 @@ |
|||||||
|
from .cart import Cart |
||||||
|
|
||||||
|
|
||||||
|
def cart(request): |
||||||
|
return {'cart': Cart(request)} |
||||||
|
|
||||||
@ -0,0 +1,21 @@ |
|||||||
|
from django import forms |
||||||
|
|
||||||
|
class CartAddProductForm(forms.Form): |
||||||
|
quantity = forms.CharField(widget=forms.TextInput(attrs={ |
||||||
|
'id': 'quantity', |
||||||
|
'name': 'quantity', |
||||||
|
'type': 'number', |
||||||
|
'min': '1', |
||||||
|
'max': '1000', |
||||||
|
'value': '1', |
||||||
|
'onchange': 'calculate()'})) |
||||||
|
product_slug = forms.CharField(widget=forms.TextInput(attrs={ |
||||||
|
'id': 'product_slug', |
||||||
|
'name': 'product_slug', |
||||||
|
'type': 'hidden'})) |
||||||
|
price_per_itom = forms.IntegerField(widget=forms.TextInput(attrs={ |
||||||
|
'id': 'price_per_itom', |
||||||
|
'name': 'price_per_itom', |
||||||
|
'type': 'hidden'})) |
||||||
|
update = forms.BooleanField(required=False, initial=False, widget=forms.HiddenInput) |
||||||
|
|
||||||
@ -0,0 +1,59 @@ |
|||||||
|
from django.db import models |
||||||
|
from django.contrib.auth import get_user_model |
||||||
|
from django.contrib.postgres.fields import HStoreField |
||||||
|
from django.utils.translation import ugettext_lazy as _ |
||||||
|
|
||||||
|
from autoslug import AutoSlugField |
||||||
|
|
||||||
|
# Create your models here. |
||||||
|
from core.models import AbstractStatusModel |
||||||
|
from products.models import Product |
||||||
|
|
||||||
|
OFFER_STATUS_ACTIVE = 25 |
||||||
|
OFFER_STATUS_INACTIVE = 50 |
||||||
|
|
||||||
|
OFFER_STATUS_CHOICES = ( |
||||||
|
(OFFER_STATUS_ACTIVE, _('Активный')), |
||||||
|
(OFFER_STATUS_INACTIVE, _('Неактивный')) |
||||||
|
) |
||||||
|
|
||||||
|
OFFER_DEFAULT_CHOICE = OFFER_STATUS_INACTIVE |
||||||
|
|
||||||
|
|
||||||
|
class Offer(AbstractStatusModel): |
||||||
|
name = models.CharField(max_length=64, blank=True, null=True, default=None) |
||||||
|
slug = AutoSlugField(populate_from='name') |
||||||
|
price = models.DecimalField(max_digits=8, decimal_places=2, null=True, default=0.00) |
||||||
|
product = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True, default=None, |
||||||
|
related_name='variants') |
||||||
|
attributes = HStoreField(blank=True, null=True, default={}) |
||||||
|
|
||||||
|
status = models.SmallIntegerField(_('статус'), default=OFFER_DEFAULT_CHOICE, choices=OFFER_STATUS_CHOICES) |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return self.name |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = _('Позиция') |
||||||
|
verbose_name_plural = _('Позиции') |
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------ Buying status --------------------------------------------------- # |
||||||
|
BUYING_STATUS_IN_CART = 25 |
||||||
|
BUYING_STATUS_BOUGHT = 50 |
||||||
|
BUYING_STATUS_CHOICES = ( |
||||||
|
(BUYING_STATUS_IN_CART, _('В корзине')), |
||||||
|
(BUYING_STATUS_BOUGHT, _('Куплен')) |
||||||
|
) |
||||||
|
|
||||||
|
BUYING_DEFAULT_CHOICE = BUYING_STATUS_IN_CART |
||||||
|
|
||||||
|
|
||||||
|
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) |
||||||
|
status = models.SmallIntegerField(_('статус'), default=BUYING_DEFAULT_CHOICE, choices=BUYING_STATUS_CHOICES) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = _('Покупка') |
||||||
|
verbose_name_plural = _('Покупки') |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.test import TestCase |
||||||
|
|
||||||
|
# Create your tests here. |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
from django.conf.urls import url |
||||||
|
from django.urls import re_path |
||||||
|
|
||||||
|
from . import views |
||||||
|
|
||||||
|
urlpatterns = [ |
||||||
|
# url(r'^$', views.CartDetail, name='CartDetail'), |
||||||
|
# url(r'^remove/(?P<offer_slug>[-\w]+)/$', views.CartRemove, name='CartRemove'), |
||||||
|
# url(r'^add/$', views.CartAdd, name='CartAdd'), |
||||||
|
re_path(r'^buyings/history/', views.BuyingsHistory.as_view(), name='buyings_history') |
||||||
|
|
||||||
|
] |
||||||
@ -0,0 +1,60 @@ |
|||||||
|
from django.shortcuts import render, redirect, get_object_or_404 |
||||||
|
from django.views.decorators.http import require_POST |
||||||
|
from django.views.decorators.csrf import csrf_exempt |
||||||
|
from django.contrib.auth.decorators import login_required |
||||||
|
from django.contrib import auth |
||||||
|
from django.views.generic import ListView |
||||||
|
|
||||||
|
from cart.models import Buying |
||||||
|
from core.views import ProtectedView |
||||||
|
|
||||||
|
from .cart import Cart |
||||||
|
from .forms import CartAddProductForm |
||||||
|
# from discount.layout import DiscountApllyForm |
||||||
|
|
||||||
|
# @csrf_exempt |
||||||
|
# @require_POST |
||||||
|
# @login_required(login_url='accounts_ext:accounts_ext') |
||||||
|
# def CartAdd(request): |
||||||
|
# cart = Cart(request) |
||||||
|
# form = CartAddProductForm(request.POST) |
||||||
|
# if form.is_valid(): |
||||||
|
# cd = form.cleaned_data |
||||||
|
# if int(cd['quantity']) < 1 or int(cd['quantity']) > 1000: |
||||||
|
# return redirect(request.META.get('HTTP_REFERER')) |
||||||
|
# offer = get_object_or_404(Offer, slug=cd['product_slug']) |
||||||
|
# cart.add(offer=offer, price_per_itom=cd['price_per_itom'], quantity=cd['quantity'], |
||||||
|
# update_quantity=cd['update']) |
||||||
|
# request.session.pop('points', None) |
||||||
|
# return redirect('cart:CartDetail') |
||||||
|
# |
||||||
|
# @csrf_exempt |
||||||
|
# @login_required(login_url='accounts_ext:accounts_ext') |
||||||
|
# def CartRemove(request, offer_slug): |
||||||
|
# cart = Cart(request) |
||||||
|
# # offer = get_object_or_404(Offer, slug=offer_slug) |
||||||
|
# cart.remove(offer_slug) |
||||||
|
# request.session.pop('points', None) |
||||||
|
# return redirect('cart:CartDetail') |
||||||
|
# |
||||||
|
# @csrf_exempt |
||||||
|
# @login_required(login_url='accounts_ext:accounts_ext') |
||||||
|
# def CartDetail(request): |
||||||
|
# user = auth.get_user(request) |
||||||
|
# cart = Cart(request) |
||||||
|
# for item in cart: |
||||||
|
# item['update_quantity_form'] = CartAddProductForm( |
||||||
|
# initial={ |
||||||
|
# 'quantity': item['quantity'], |
||||||
|
# 'product_slug': item['offer'].slug, |
||||||
|
# 'price_per_itom': item['price'], |
||||||
|
# 'update': True |
||||||
|
# }) |
||||||
|
# # discount_apply_form = DiscountApllyForm() |
||||||
|
# return render(request, 'cart/detail.html', {'username': user.username}) |
||||||
|
# # 'discount_apply_form': discount_apply_form}) |
||||||
|
|
||||||
|
|
||||||
|
class BuyingsHistory(ProtectedView,ListView): |
||||||
|
model = Buying |
||||||
|
template_name = 'cart/buying_history.html' |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
{% extends 'base.html' %} |
||||||
|
{% block content %} |
||||||
|
Missing buying history |
||||||
|
{% endblock %} |
||||||
Loading…
Reference in new issue