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