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.
492 lines
17 KiB
492 lines
17 KiB
import base64
|
|
from django.contrib.auth import authenticate, login
|
|
from django.core.mail import mail_managers, mail_admins
|
|
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
from django.template.loader import render_to_string
|
|
from django.views.generic import *
|
|
from accounts.models import Profile
|
|
from accounts.utils import normalize_phone, send_email
|
|
from batiskaf.jinja2_ext.html_filters import escape
|
|
from main.models import ProductsUpdate
|
|
from .models import *
|
|
from store.alemtat import AlemTat
|
|
from store.cart import Cart, CartItem
|
|
from store.currency import Currency as _Currency
|
|
from django.contrib import messages
|
|
from store.forms import OrderForm, ProductFeedbackForm
|
|
from django.http import JsonResponse
|
|
from datetime import datetime
|
|
from django.conf import settings
|
|
from django.contrib.sitemaps import Sitemap
|
|
import kkb
|
|
|
|
|
|
class CategoryBaseView(object):
|
|
category = None
|
|
|
|
def _get_full_category(self, categories_string):
|
|
cats = categories_string.split('/')
|
|
category = get_object_or_404(Category, slug=cats[0])
|
|
for c in cats:
|
|
if c != category.slug:
|
|
category = get_object_or_404(category.childs, slug=c)
|
|
return category
|
|
|
|
|
|
class CategoryView(CategoryBaseView, TemplateView):
|
|
template_name = 'category.jinja'
|
|
brand_pks = []
|
|
products_qs = Product.objects.none()
|
|
sort = None
|
|
is_search = False
|
|
is_sale = False
|
|
is_leaders = False
|
|
|
|
ORDER_PARAMETERS = (
|
|
('date', 'pk'),
|
|
('-date', '-pk'),
|
|
('price', 'price_min'),
|
|
('-price', '-price_min'),
|
|
)
|
|
|
|
def _get_brand_pks(self):
|
|
brand_pks = []
|
|
|
|
for v in self.request.GET.getlist('brand[]'):
|
|
try:
|
|
brand_pks.append(int(v))
|
|
except:
|
|
pass
|
|
|
|
return brand_pks
|
|
|
|
def _get_sort(self):
|
|
sort = self.request.GET.get('sort', None)
|
|
|
|
return sort
|
|
|
|
def paginate(self):
|
|
paginate_by = self.request.GET.get('paginate_by', 30)
|
|
|
|
if paginate_by == 'all':
|
|
paginate_by = 10000
|
|
|
|
paginator = Paginator(self.products_qs, int(paginate_by))
|
|
page = self.request.GET.get('page')
|
|
try:
|
|
self.products_qs = paginator.page(page)
|
|
except PageNotAnInteger:
|
|
self.products_qs = paginator.page(1)
|
|
except EmptyPage:
|
|
self.products_qs = paginator.page(paginator.num_pages)
|
|
|
|
def _get_filter_attributes(self):
|
|
|
|
for k in self.request.GET:
|
|
attr = Attribute.objects.filter(slug=k.replace('[]', ''))
|
|
if attr:
|
|
attr_values = self.request.GET.getlist(k)
|
|
while 'false' in attr_values:
|
|
attr_values.remove('false')
|
|
attr_values = [v.strip() for v in attr_values]
|
|
if attr_values:
|
|
self.products_qs = self.products_qs.filter(
|
|
product_attributes__attribute__attribute__in=attr,
|
|
product_attributes__value__in=attr_values).distinct()
|
|
|
|
def get_brands_by_products(self):
|
|
pass
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
retval = super(CategoryView, self).get_context_data()
|
|
q = None
|
|
|
|
if self.is_search:
|
|
q = self.request.GET.get('q', '')
|
|
self.products_qs = Product.objects.filter(title__icontains=q).\
|
|
sorted_in_stock_by_field('-pk')
|
|
brands_pks = [item.brand.pk for item in self.products_qs]
|
|
retval['brands'] = Brand.objects.filter(pk__in=brands_pks).order_by(
|
|
'title') # list(set(map(lambda item: item.brand, self.products_qs)))
|
|
|
|
elif self.is_sale:
|
|
self.products_qs = Product.objects.filter(variations__discount__gt=0).distinct().\
|
|
sorted_in_stock_by_field('-pk')
|
|
brands_pks = [item.brand.pk for item in self.products_qs]
|
|
retval['brands'] = Brand.objects.filter(pk__in=brands_pks).order_by('title')
|
|
|
|
elif self.is_leaders:
|
|
brands_pks = [item.brand.pk for item in self.products_qs]
|
|
retval['brands'] = Brand.objects.filter(pk__in=brands_pks).order_by('title')
|
|
|
|
else:
|
|
self.category = self._get_full_category(kwargs['categories'])
|
|
if not self.category.hide_products:
|
|
self.products_qs = self.category.get_all_products_in_stock_order_by('-pk')
|
|
|
|
self.brand_pks = self._get_brand_pks()
|
|
self.sort = self._get_sort()
|
|
|
|
if self.brand_pks:
|
|
self.products_qs = self.products_qs.filter(
|
|
brand__pk__in=self.brand_pks)
|
|
|
|
if self.sort:
|
|
sort_parameter = dict(self.ORDER_PARAMETERS)[self.sort]
|
|
preordered_qs = self.products_qs
|
|
|
|
if sort_parameter in ['price_min', '-price_min']:
|
|
preordered_qs = self.products_qs.extra(
|
|
select={
|
|
'price_min':
|
|
'SELECT MIN(price) FROM store_productvariation ' +
|
|
'WHERE store_productvariation.product_id ' +
|
|
'= store_product.id'
|
|
})
|
|
if preordered_qs:
|
|
self.products_qs = preordered_qs.order_by('-have_stock', sort_parameter)
|
|
else:
|
|
self.products_qs = preordered_qs.order_by(sort_parameter)
|
|
|
|
self._get_filter_attributes()
|
|
# print(self.products_qs)
|
|
self.paginate()
|
|
retval['category'] = self.category
|
|
retval['products'] = self.products_qs
|
|
retval['q'] = q
|
|
retval['is_sale'] = self.is_sale
|
|
|
|
return retval
|
|
|
|
|
|
class ProductView(CategoryBaseView, DetailView):
|
|
model = Product
|
|
template_name = 'product.jinja'
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
self.category = self._get_full_category(kwargs['categories'])
|
|
retval = super(ProductView, self).get(request, args, kwargs)
|
|
ranee = request.session.get('ranee', [])
|
|
#import pdb;pdb.set_trace()
|
|
if kwargs['slug'] not in ranee:
|
|
ranee.append(kwargs['slug'])
|
|
request.session['ranee'] = ranee
|
|
|
|
return retval
|
|
|
|
def get_context_data(self, **kwargs):
|
|
retval = super(ProductView, self).get_context_data()
|
|
retval['category'] = self.category
|
|
retval['form'] = ProductFeedbackForm(self.request.POST or None)
|
|
retval['updated'] = ProductsUpdate.objects.last()
|
|
ranee = self.request.session.get('ranee', [])
|
|
#import pdb;pdb.set_trace()
|
|
#ranee.pop(kwargs['object'].slug)
|
|
retval['ranee'] = []
|
|
for i in ranee:
|
|
#import pdb; pdb.set_trace()
|
|
if kwargs and i != kwargs['object'].slug:
|
|
try:
|
|
p = Product.objects.get(slug=i)
|
|
if p not in retval['ranee']:
|
|
retval['ranee'].append(p)
|
|
except: pass
|
|
#import pdb;pdb.set_trace()
|
|
if retval['ranee']:
|
|
retval['ranee'] = retval['ranee'][::-1][:4]
|
|
|
|
return retval
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
self.category = self._get_full_category(kwargs['categories'])
|
|
super(ProductView, self).get(request, args, kwargs)
|
|
context_data = self.get_context_data()
|
|
# context_data['category'] = self.category
|
|
|
|
form = ProductFeedbackForm(request.POST or None)
|
|
if form.is_valid():
|
|
obj = form.save(commit=False)
|
|
obj.product = self.object
|
|
obj.save()
|
|
messages.success(self.request, 'Ваш отзыв успешно опубликован. Спасибо!')
|
|
mail_managers('Оставили отзыв о товаре', 'Смотреть в админке')
|
|
return redirect(self.object.get_absolute_url())
|
|
else:
|
|
return self.render_to_response(context_data)
|
|
|
|
|
|
class CartAddView(RedirectView):
|
|
def dispatch(self, request, *args, **kwargs):
|
|
retval = super(CartAddView, self).dispatch(request, args, kwargs)
|
|
cart = Cart(self.request)
|
|
try:
|
|
item_variant = ProductVariation.objects.get(
|
|
pk=self.request.GET.get('pk'))
|
|
except ProductVariation.DoesNotExist:
|
|
return redirect('/')
|
|
except:
|
|
return redirect('/')
|
|
count = self.request.GET.get('count')
|
|
# messages.success(
|
|
# self.request, """Товар успешно добавлен в корзину!
|
|
# Вы можете перейти к оформлению заказа,
|
|
# либо продолжить выбор товаров.
|
|
# <a href='/store/cart/'>Открыть корзину...</a>""")
|
|
cart.add_item(CartItem(item_variant, count))
|
|
return retval
|
|
|
|
def get_redirect_url(self, *args, **kwargs):
|
|
from django.core.urlresolvers import reverse
|
|
|
|
return reverse('store_cart_detail')
|
|
|
|
|
|
class CartRemoveView(RedirectView):
|
|
def dispatch(self, request, *args, **kwargs):
|
|
retval = super(CartRemoveView, self).dispatch(request, args, kwargs)
|
|
cart = Cart(self.request)
|
|
item_id = self.request.GET.get('id')
|
|
cart.remove_item(item_id)
|
|
return retval
|
|
|
|
def get_redirect_url(self, *args, **kwargs):
|
|
return '/store/cart/'
|
|
|
|
|
|
class CartDetailView(TemplateView):
|
|
template_name = 'cart_detail.jinja'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
from .models import KAZPOST_CITIES
|
|
retval = super(CartDetailView, self).get_context_data()
|
|
retval['cart'] = Cart(self.request)
|
|
retval['form'] = OrderForm(self.request.POST or None)
|
|
retval['alemtat_cities'] = alemtat_get_cities_tuple()
|
|
retval['alemtat_services'] = alemtat_get_services_tuple()
|
|
retval['kazpost_cities'] = KAZPOST_CITIES
|
|
# retval['form_delivs'] = DelivsForm()
|
|
return retval
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
cart = Cart(self.request)
|
|
cart.update_items()
|
|
|
|
if 'order_next' in self.request.POST:
|
|
deliv_service = request.POST['deliv_service']
|
|
form = OrderForm(self.request.POST)
|
|
|
|
if form.is_valid():
|
|
order = form.save(commit=False)
|
|
json_items = map(lambda items: {items.item.pk: items.count}, cart.items)
|
|
order.items = str(list(json_items))
|
|
cart = Cart(request)
|
|
order.phone = normalize_phone(order.phone)
|
|
order.deliv_service = deliv_service
|
|
|
|
if deliv_service == 'alemtat':
|
|
a = AlemTat()
|
|
order.city = request.POST['city']
|
|
order.deliv_type = request.POST['deliv_type']
|
|
order_amount = dict(a.get_amount(
|
|
order.city,
|
|
len(cart.items),
|
|
cart.weight,
|
|
order.deliv_type,
|
|
))
|
|
order.amount = order_amount['AmountPlusFSAmount'] + cart.total
|
|
order.address = request.POST['alemtat_address']
|
|
|
|
elif deliv_service == 'kazpost':
|
|
amount = get_kazpost_tarif(cart.weight, request.POST['kazpost_city'])
|
|
order.amount = int(amount) + cart.total
|
|
order.kazpost_city = int(request.POST['kazpost_city'])
|
|
order.address = request.POST['kazpost_address']
|
|
|
|
elif deliv_service == 'pickup':
|
|
order.amount = cart.total
|
|
|
|
profile = None
|
|
|
|
try:
|
|
profile = Profile.objects.get(phone=normalize_phone(order.phone))
|
|
#profile.set_password(settings.PROFILE_TEMP_PASSWORD)
|
|
#profile.save()
|
|
send_email(profile, template='mail/order.jinja')
|
|
except:
|
|
from random import randint
|
|
import requests
|
|
password = randint(10000000, 99999999)
|
|
profile = Profile.objects.create(
|
|
phone=normalize_phone(order.phone),
|
|
email=order.email,
|
|
first_name=order.first_name,
|
|
last_name=order.last_name,
|
|
)
|
|
profile.set_password(password)
|
|
profile.save()
|
|
|
|
phone = normalize_phone(order.phone)
|
|
params = dict(
|
|
login='Jango.kz',
|
|
psw='AcEMXtLGz042Fc1ZJUSl',
|
|
phones='7{}'.format(phone),
|
|
mes='Batiskaf.kz - Vash parol: {}'.format(password)
|
|
)
|
|
requests.get('http://smsc.ru/sys/send.php', params=params)
|
|
|
|
send_email(profile, template='mail/registration.jinja')
|
|
user = authenticate(username=profile.phone, password=password)
|
|
if user.is_active:
|
|
login(request, user)
|
|
|
|
order.profile = profile
|
|
order.save()
|
|
|
|
mail_managers('Оформили заказ', 'Смотреть в админке')
|
|
payment_type = request.POST.get('payment_type', 'card')
|
|
if payment_type == 'card':
|
|
return redirect('/order/{}/kkb/'.format(order.pk))
|
|
return redirect('/order/{}/print/'.format(order.pk))
|
|
|
|
|
|
else:
|
|
return self.render_to_response(self.get_context_data())
|
|
|
|
return redirect(self.request.path)
|
|
|
|
|
|
def get_order_amount(request):
|
|
retval = None
|
|
_currency = _Currency(request)
|
|
a = AlemTat()
|
|
cart = Cart(request)
|
|
retval = dict(a.get_amount(
|
|
request.GET['city'],
|
|
len(cart.items),
|
|
cart.weight,
|
|
request.GET['deliv'],
|
|
))
|
|
|
|
_retval = {k: _currency.get_price(v) for k, v in retval.items() if k != 'FS'}
|
|
_retval['FS'] = retval['FS']
|
|
return JsonResponse(_retval)
|
|
|
|
|
|
def get_kazpost_tarif(weight, to):
|
|
|
|
import requests
|
|
import re
|
|
|
|
url="http://rates.kazpost.kz/postratesprod/postratesws.wsdl"
|
|
#headers = {'content-type': 'application/soap+xml'}
|
|
headers = {'content-type': 'text/xml'}
|
|
body = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pos="http://webservices.kazpost.kz/postratesws">
|
|
<soapenv:Header/>
|
|
<soapenv:Body>
|
|
<pos:GetPostRateRequest>
|
|
<pos:MailInfo>
|
|
<pos:Product>7</pos:Product>
|
|
<pos:MailCat>2</pos:MailCat>
|
|
<pos:SendMethod>2</pos:SendMethod>
|
|
<pos:Weight>{}</pos:Weight>
|
|
<pos:From>13</pos:From>
|
|
<pos:To>{}</pos:To>
|
|
<pos:SpecMarks/>
|
|
<pos:InCity/>
|
|
<pos:ExpressDlv/>
|
|
<pos:Size/>
|
|
<pos:DeclaredValue/>
|
|
</pos:MailInfo>
|
|
</pos:GetPostRateRequest>
|
|
</soapenv:Body>
|
|
</soapenv:Envelope>"""
|
|
|
|
body = body.format(weight*1000, to)
|
|
|
|
try:
|
|
response = requests.post(url, data=body, headers=headers)
|
|
m = re.search(r'<ns2:PostRate>(\d+)</ns2:PostRate>', response.text)
|
|
return m.group(1)
|
|
except:
|
|
return 0
|
|
|
|
|
|
def get_order_kazpost_amount(request):
|
|
retval = None
|
|
cart = Cart(request)
|
|
retval = dict(amount=get_kazpost_tarif(cart.weight, request.GET['city']))
|
|
return JsonResponse(retval)
|
|
|
|
|
|
def order_view(request, order):
|
|
order = get_object_or_404(OrderData, pk=order)
|
|
c = dict(order=order, date=datetime.now())
|
|
return render(request, 'order_ok.jinja', c)
|
|
|
|
|
|
def order_print(request, order):
|
|
order = get_object_or_404(OrderData, pk=order)
|
|
c = dict(order=order, date=datetime.now())
|
|
return render(request, 'order_print.jinja', c)
|
|
|
|
|
|
def order_kkb(request, order):
|
|
order = get_object_or_404(OrderData, pk=order)
|
|
|
|
cart = Cart(request)
|
|
context = kkb.get_context(order.pk, amount=order.amount, b64=True)
|
|
|
|
c_appendix = dict(items=cart.items, deliv_price=order.amount - cart.total)
|
|
render_appendix = render_to_string('kkb/appendix.xml', c_appendix)
|
|
appendix = base64.b64encode(
|
|
bytes(render_appendix, 'utf-8')
|
|
).decode('utf-8')
|
|
|
|
c = dict(order=order, context=context, appendix=appendix)
|
|
# print(c)
|
|
return render(request, 'kkb.jinja', c)
|
|
|
|
|
|
def kkb_result(request):
|
|
mail_admins('POST', str(request.POST))
|
|
response = request.POST['response']
|
|
result = kkb.postlink(response)
|
|
if result.status:
|
|
order = OrderData.objects.get(pk=int(result.data['ORDER_ID']))
|
|
order.status = 1
|
|
order.save()
|
|
mail_managers('Оплатили заказ картой', 'Заказ №{}'.format(order.pk))
|
|
else:
|
|
pass
|
|
# print(result.message)
|
|
return render(request, 'kkb_ok.jinja')
|
|
|
|
|
|
class ProductSitemap(Sitemap):
|
|
changefreq = "daily"
|
|
priority = 0.8
|
|
|
|
def items(self):
|
|
return Product.objects.all()
|
|
|
|
|
|
class CategorySitemap(Sitemap):
|
|
changefreq = "daily"
|
|
priority = 0.6
|
|
|
|
def items(self):
|
|
return Category.objects.all()
|
|
|
|
|
|
def set_currency(request, currency_code):
|
|
current_url = request.META.get('HTTP_REFERER', '/')
|
|
_currency = _Currency(request)
|
|
try:
|
|
current_currency = Currency.objects.get(ISO_letter_code=currency_code)
|
|
except Currency.DoesNotExist:
|
|
current_currency = Currency.objects.get(pk=1)
|
|
_currency.set_currency(current_currency.id, request)
|
|
|
|
return redirect(current_url)
|
|
|