Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #models.py
- from __future__ import unicode_literals
- import datetime
- import base64
- from django.core.exceptions import ValidationError
- from django.http import QueryDict
- from django.utils import timezone
- import urllib2
- from random import randint
- from django.template.defaultfilters import length
- import json
- from pyxtension.Json import Json
- from yandex_money.models import Payment
- from robokassa.models import SuccessNotification
- from paypal.standard.ipn.models import PayPalIPN
- import requests
- from django.contrib.auth.models import User
- from django.core.cache import cache
- from django.core.urlresolvers import reverse
- from django.db import models
- from django.db.models import Q, Sum
- from django.template.loader import get_template
- from django.utils.functional import cached_property
- from django.utils.safestring import mark_safe
- from core.models import ArticlePage, CartItemMixin
- from utils import gen_random_string
- from math import *
- def robokassa_order_number():
- number = gen_random_string(9, symbols='digits')
- if number.startswith('0'):
- number = str(randint(1, 9)) + number[1:]
- return number
- class DeliveryInfo(models.Model):
- template_name = 'delivery_info.html'
- DTYPES = [
- ('b2cpl', u'По России'),
- ('ems', u'EMS'),
- ]
- user = models.OneToOneField(UserProfile, related_name=u'delivery', verbose_name=u'Пользователь', blank=True,
- null=True)
- order = models.OneToOneField(Order, related_name='delivery', verbose_name=u'Заказ', blank=True, null=True)
- name = models.CharField(u'Имя Фамилия Отчество', max_length=255)
- phone = models.CharField(u'Телефон', max_length=255)
- email = models.CharField(u'E-mail', max_length=255)
- zipcode = models.CharField(u'Индекс', max_length=6, blank=True, null=True)
- country = models.ForeignKey(Country, models.SET_NULL, verbose_name=u'Страна', blank=True, null=True)
- city = models.CharField(u'Город', max_length=255, blank=True, null=True)
- address = models.CharField(u'Место проживания', max_length=255, blank=True, null=True)
- dtype = models.CharField(u'Тип доставки', choices=DTYPES, default='b2cpl', max_length=10, blank=True, null=True)
- last_delivery_price = models.PositiveIntegerField(default=0)
- code = models.CharField(u'Код доставки', max_length=50, default=u'курьер', blank=True, null=True)
- options = models.CharField(u'Информация о доставке', max_length=2000, blank=True, null=True)
- class Meta:
- verbose_name = u'запись'
- verbose_name_plural = u'Форма "Контактная информация"'
- def __unicode__(self):
- return self.name
- def _get_ship_options(self):
- if self.options and isinstance(self.options, dict):
- return Json(self.options)
- _get_ship_options.short_description = 'Опции доставки'
- ship_options = property(_get_ship_options)
- # Адрес пвз если доставка туда
- def _get_ship_pvz_address(self):
- if self.ship_options:
- param = self.ship_options['Адрес']
- if length(param) > 0:
- return param
- _get_ship_pvz_address.short_description = 'Адрес ПВЗ'
- ship_pvz_address = property(_get_ship_pvz_address)
- def get_info(self, plain=False):
- data = [
- {'value': getattr(self, 'name', '-'), 'label': u'Имя Фамилия Отчество'},
- {'value': getattr(self, 'phone', '-'), 'label': u'Телефон'},
- {'value': getattr(self, 'email', '-'), 'label': u'E-mail'},
- {'value': getattr(self, 'zipcode', '-'), 'label': u'Индекс'},
- {'value': getattr(self, 'country', '-'), 'label': u'Страна'},
- {'value': getattr(self, 'city', '-'), 'label': u'Город'},
- {'value': getattr(self, 'address', '-'), 'label': u'Место проживания'},
- {'value': self.dtype_verbose, 'label': u'Тип доставки'},
- ]
- if self.dtype_verbose == 'b2cpl':
- data.__add__({'value': getattr(self, 'options', '-')['Код'], 'label': u'Вариант доставки'})
- if plain:
- return u'\r\n'.join([u'{0}: {1}'.format(item['label'], item['value']) for item in data])
- else:
- html = get_template(self.template_name)
- html = html.render({'data': data})
- return html
- @property
- def dtype_verbose(self):
- return dict(self.DTYPES).get(self.dtype)
- def get_cost(self, request, weight):
- cost = 0
- options = None
- q = QueryDict('', mutable=True)
- if self.dtype == 'b2cpl':
- # Формируем ссылку для запроса через API
- params = {'func': 'tarif', 'type': '+post', 'zip': self.zipcode, 'weight': str(int(weight))}
- q.update(params)
- url = '%s?%s' % (reverse('cart:b2c_api'), q.urlencode(safe='/'))
- data = requests.get(request.build_absolute_uri(url)).json()
- if data.get('flag_delivery'):
- ways = data['delivery_ways']
- for way in ways:
- if way.get('Код') == self.code:
- options = way
- cost = options['Стоимость']
- break
- elif self.dtype == 'ems':
- params = {'method': 'ems.calculate', 'type': 'att', 'to': self.country.code, 'weight': str(weight)}
- q.update(params)
- url = '%s?%s' % (reverse('cart:ems_api'), q.urlencode(safe='/'))
- data = requests.get(request.build_absolute_uri(url)).json()
- if data['rsp']['stat'] == 'ok':
- cost = data['rsp']['price']
- if options:
- self.options = json.dumps(options)
- if cost:
- cost = int(round(float(cost.replace(',', "."))))
- return cost
- else:
- raise ValidationError(('Доставка с кодом: %(value)s невозможна, выберите другой вариант.'),
- code='delivery_unpossible',
- params={'value': self.code}, )
- #views.py
- class DeliveryFormView(UpdateView):
- form_class = DeliveryForm
- model = DeliveryInfo
- session_key = 'dform_id'
- tab = 'delivery'
- def get(self, request):
- raise Http404
- def get_object(self):
- return CabinetPage.get_form_instance(self.request, self.model, self.session_key)
- def form_valid(self, form):
- profile = self.get_or_create_user_profile(self.request)
- # if form.instance.user != profile:
- # form.instance.user = profile
- # form.save()
- delivery, created = DeliveryInfo.objects.get_or_create(user=profile)
- if self.request.POST.get('name'):
- delivery.name = self.request.POST.get('name')
- if self.request.POST.get('phone'):
- delivery.phone = self.request.POST.get('phone')
- if self.request.POST.get('email'):
- delivery.email = self.request.POST.get('email')
- if self.request.POST.get('zipcode'):
- delivery.zipcode = self.request.POST.get('zipcode')
- if self.request.POST.get('country'):
- try:
- delivery.country = Country.objects.get(id=self.request.POST.get('country'))
- except Country.DoesNotExist:
- pass
- if self.request.POST.get('city'):
- delivery.city = self.request.POST.get('city')
- if self.request.POST.get('address'):
- delivery.address = self.request.POST.get('address')
- delivery.code = form.cleaned_data['code']
- if self.request.POST.get('dtype'):
- delivery.dtype = self.request.POST.get('dtype')
- weight = CartForm.get_weight(self.request)
- try:
- delivery.last_delivery_price = delivery.get_cost(self.request, weight)
- except ValidationError as e:
- if e.code:
- if e.code == 'delivery_unpossible':
- form.add_error('code', ''.join(e.messages))
- return JsonResponse({'success': False, 'status': 'error', 'errors': form.errors})
- delivery.save()
- self.request.session[self.session_key] = form.instance.id
- CabinetPage.manage_tabs(self.request, self.tab, 'add')
- return JsonResponse({'success': True, 'status': 'ok'})
- def form_invalid(self, form):
- print(form.errors)
- CabinetPage.manage_tabs(self.request, self.tab, 'delete')
- return JsonResponse({'success': False, 'status': 'error', 'errors': form.errors})
- def get_or_create_user_profile(self, request):
- profile = getattr(request.user, 'profile', None) or UserProfile.objects.filter(
- id=request.session.get('profile_id')).first()
- if not profile:
- profile = UserProfile()
- profile.save()
- request.session['profile_id'] = profile.id
- return profile
- #robokassa/views
- from robokassa.conf import USE_POST
- from robokassa.forms import RobokassaForm, ResultURLForm, SuccessRedirectForm, FailRedirectForm
- from robokassa.signals import result_received, success_page_visited, fail_page_visited
- from robokassa.models import SuccessNotification
- from django.views.decorators.csrf import csrf_exempt
- from django.http import HttpResponseRedirect
- from django.conf import settings
- from cart.export import export_orders_to_b2c
- from cart.models import Order
- from cart.forms import SendBillForm
- from pay.views import SendPaymentView
- def get_order(order_number):
- try:
- return Order.objects.get(order_number=order_number)
- except Order.DoesNotExist:
- return None
- def payment_received(sender, **kwargs):
- order = get_order(order_number=kwargs['InvId'])
- if not order:
- return
- order.status = 'success'
- order.robokassa_payment = SuccessNotification.objects.filter(InvId=kwargs['InvId']).first()
- order.date = datetime.datetime.now()
- order.save()
- if order.has_delivery and order.delivery.dtype == 'b2cpl':
- export_orders_to_b2c(kwargs['request'], order)
- SendBillForm().send_email(order=order)
- result_received.connect(payment_received)
- #export.py
- import datetime
- import io
- import os
- import urlparse
- import uuid
- from django.core.urlresolvers import reverse
- from contextlib import closing
- import unicodecsv
- import xlwt
- import requests
- import codecs
- from django.db.models import Sum
- from django.http import HttpResponse, QueryDict
- from _conf.core import B2CPL_EXPORT_FIELDS, MEDIA_ROOT, B2CPL_EXPORT_DIR, B2CPL_PACKAGE_TYPE
- # Настройки для загрузки файлов ответов B2cpl после импорта заказа в их систему
- from cart.models import OrderItem
- def export_orders_to_b2c(request, order):
- col_delim = ';'
- row_delim = '\r\n'
- fname = str(uuid.uuid4()) + '.csv'
- fout = os.path.join(MEDIA_ROOT, B2CPL_EXPORT_DIR, fname)
- with codecs.open(fout, "wb+") as f:
- w = unicodecsv.DictWriter(f, encoding='utf-8', fieldnames=B2CPL_EXPORT_FIELDS, extrasaction='raise',
- delimiter=str(col_delim), lineterminator=row_delim, skipinitialspace=True)
- # header fields
- w.writeheader()
- # body
- rec = {}
- delivery = order.delivery
- rec['Дата заказа'] = order.date.strftime('%d/%m/%Y')
- rec['Индекс'] = delivery.zipcode
- rec['Город'] = delivery.city
- rec['Адрес'] = delivery.address
- rec['ФИО'] = delivery.name
- rec['E-mail'] = delivery.email
- rec['Телефон мобильный'] = delivery.phone
- # TODO выяснить назначение этих полей. Вроде вся доставка учтена при оплате
- # rec['Полная стоимость доставки'] = delivery.last_delivery_price
- # rec['Стоимость доставки к оплате'] = delivery.last_delivery_price
- rec['Полная стоимость доставки'] = 0
- rec['Стоимость доставки к оплате'] = 0
- rec['Тип доставки'] = delivery.code
- # TODO Uncomment to enable
- rec['Упаковка'] = B2CPL_PACKAGE_TYPE
- items2delivery = order.items.filter(dtype__in=['calendar', 'book'], export_name__isnull=False).distinct()
- sum_items2delivery = sum([item.sum for item in items2delivery]) if items2delivery else 0
- rec['Оценочная стоимость посылки'] = sum_items2delivery
- for item in items2delivery:
- rec['Номер посылки'] = order.order_number
- rec['Артикул'] = item.export_name
- rec['Товар'] = item.title
- rec['Кол-во ед. товара'] = item.amount
- rec['Полная стоимость ед. товара'] = item.page.productarticle.price
- rec['Стоимость ед. товара к оплате'] = 0
- # rec['Вес товара'] = item.page.weight
- w.writerow(rec)
- rec = {}
- protocol = request.scheme
- host = request.META['HTTP_HOST']
- fout_rel = urlparse.urljoin(protocol + '://' + host, os.path.relpath(fout))
- q = QueryDict('', mutable=True)
- params = {'func': 'upload', 'file': fout_rel, 'report': '1', 'stickers': '0'}
- q.update(params)
- url = '%s?%s' % (reverse('cart:b2c_api'), q.urlencode(safe='/'))
- absoluteUri = request.build_absolute_uri(url)
- print('absoluteUri: ' + absoluteUri)
- data = requests.get(absoluteUri).json()
- if data.get('cnt_ok'):
- packs = data.get('packages')
- track_number = packs[0]['codeb2c']
- if track_number:
- order.tracking_number = track_number
- order.save()
- order.send_email(tracking=True)
- return data
Add Comment
Please, Sign In to add comment