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 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).order_by('-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().order_by('-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().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' }) self.products_qs = preordered_qs.order_by(sort_parameter) self._get_filter_attributes() 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) 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() 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('/') count = self.request.GET.get('count') # messages.success( # self.request, """Товар успешно добавлен в корзину! # Вы можете перейти к оформлению заказа, # либо продолжить выбор товаров. # Открыть корзину...""") 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() deliv_service = request.POST['deliv_service'] if 'order_next' in self.request.POST: 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'] 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: 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(settings.PROFILE_TEMP_PASSWORD) profile.save() send_email(profile, template='mail/registration.jinja') user = authenticate(username=profile.phone, password=settings.PROFILE_TEMP_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 a = AlemTat() cart = Cart(request) retval = dict(a.get_amount( request.GET['city'], len(cart.items), cart.weight, request.GET['deliv'], )) return JsonResponse(retval) def get_kazpost_tarif(weight, to): import requests import json, xmljson from lxml.etree import fromstring, tostring import re url="http://rates.kazpost.kz/postratesws/postratesws.wsdl" #headers = {'content-type': 'application/soap+xml'} headers = {'content-type': 'text/xml'} body = """ 7 2 2 {} 13 {} """ body = body.format(weight*1000, to) try: response = requests.post(url, data=body, headers=headers) m = re.search(r'(\d+)', 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) 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: 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()