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, """Товар успешно добавлен в корзину! # Вы можете перейти к оформлению заказа, # либо продолжить выбор товаров. # Открыть корзину...""") 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'] 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 = """ 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) # 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)